Skip to content

Latest commit

 

History

History
736 lines (597 loc) · 25.6 KB

File metadata and controls

736 lines (597 loc) · 25.6 KB

前端开发文档(最终版)

0. 前置条件与快速开始

  • 安装工具(只需做一次):

    npm install -g cursor-cli       # 安装 Cursor 命令行工具
    npm install --save-dev cypress  # 安装 Cypress 测试框架
    npm install --save-dev jq       # 安装 jq(用于解析 JSON 报告)
  • 配置脚本与文件:

    1. auto-dev.sh 放在项目根目录,执行:

      chmod +x auto-dev.sh
    2. 确保 package.json 包含:

      "scripts": {
        "test:ci": "cypress run --reporter json --reporter-options toConsole=false > reports/test-results.json"
      }
    3. 在项目根添加并填写 cypress.config.js

  • 快速启动:

    1. 编辑以下章节中"7. 验收标准与测试方法",将需求直接复制到脚本参数中。

    2. 运行:

      ./auto-dev.sh feature/login specs/login.md
    3. 脚本会循环执行「AI 生成 → 本地测试 → AI 修复 → 重测」直至所有测试通过。

    4. 全绿后,手动提交:

      git add . && git commit -m "feat: 完成登录模块" && git push

1. 项目概览

  • 业务目标: 通过 AI 语音交互,为 Web3 用户提供 MCP 服务入口;支持 MCP 内置服务与第三方 API。

  • 主要用户群:

    1. 普通用户:使用平台提供的语音功能和 MCP/第三方服务。
    2. 第三方开发者:上传并管理自己封装的 API(如 Dify 或 Coze),扩展平台功能。
  • 技术栈: React 18 + Vite、Ant Design Mobile、MSW、Cypress、Cursor CLI。

  • 架构: 组件化 + Hook 封装 + Mock 服务 + 自动化脚本。

1.1 目录结构与响应式策略

src/
├── components/       # 通用 UI 组件
├── hooks/            # 自定义 Hooks (useVoice, useApi, useIntent)
├── services/         # API 调用封装 (apiClient)
├── contexts/         # 全局状态 (Session, UserConfig, Theme, Auth)
├── mocks/            # Mock 数据 (仅 dev 环境)
├── utils/            # 工具函数 (格式化、schema 校验)
├── styles/           # 主题与全局样式 (tokens.css)
├── pages/            # 页面级组件 (主页面、登录、设置等)
├── App.jsx           # 应用根组件
└── index.js          # 入口文件

响应式策略(Mobile-First + Desktop-Enhance)

  1. 移动优先 (Mobile-First)

    • 默认样式针对最小设备(≥320px)编写,使用不带前缀的 Tailwind 类或基础 CSS 直接应用于所有设备。
    • 确保在最小视口下布局和交互可用,不需要额外的媒体查询。
  2. 断点设计 (Breakpoints)

    • sm (≥640px):小屏平板 / 大手机
    • md (≥768px):常规平板
    • lg (≥1024px):小笔记本
    • xl (≥1280px):大屏

    示例 Tailwind 配置:

    // tailwind.config.js
    module.exports = {
      theme: {
        screens: {
          sm: '640px',
          md: '768px',
          lg: '1024px',
          xl: '1280px',
        },
        container: {
          center: true,
          padding: '1rem',
        },
      },
    };
  3. 流式网格布局 (Fluid Grid)

    • CSS Grid

      .grid-container {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
        gap: var(--spacing-md);
      }
    • Tailwind

      <div class="grid gap-4 grid-cols-1 sm:grid-cols-2 md:grid-cols-3 lg:grid-cols-4">
        <!-- 卡片列表 -->
      </div>
  4. 流式排版 & 容器宽度

    • 字体响应式:使用 clamp() 随视口变化

      h1 {
        font-size: clamp(1.5rem, 5vw, 2.5rem);
      }
    • 容器

      .container {
        max-width: 1200px;
        width: 100%;
        padding: 0 var(--spacing-md);
        margin: 0 auto;
      }
  5. 关键组件适配示例

    <form class="max-w-md mx-auto p-4 bg-secondary rounded-lg">
      <label class="block mb-2">用户名</label>
      <input class="w-full p-2 mb-4 rounded border" />
      <label class="block mb-2">密码</label>
      <input class="w-full p-2 mb-4 rounded border" type="password" />
      <button class="w-full py-2 rounded bg-primary text-white">登录</button>
    </form>
    • max-w-md(Tailwind 默认 28rem)保证小屏全宽,大屏居中显示。
  6. 测试 & 校验

    • 在 Chrome DevTools 中模拟手机和平板断点预览。
    • Cypress 中使用 cy.viewport('iphone-6')cy.viewport(1280,800) 验证 E2E 脚本。

2. 功能模块清单

序号 模块名称 说明 依赖
1 登录组件 用户名+密码表单,错误提示 API: /api/login
2 注册组件 用户名+邮箱+密码表单,表单校验 API: /api/register
3 首页列表 列表渲染,可分页、下拉刷新 API: /api/items
4 语音录制控件 录音/停止按钮,超时提示 --
5 语音识别结果展示 STT 结果 + 自动触发后续执行 API: /api/interpret
6 技能服务目录 动态展示 MCP & 第三方服务列表 API: /api/services
7 进度条组件 "识别中 → 理解中 → 执行中 → 完成" 四阶段进度反馈 --
8 通用弹窗/Toast 错误、成功、超时、重试提示 --
9 全局布局 Header/Footer/主内容区 --
10 错误边界 React ErrorBoundary 捕获渲染错误并展示友好提示 --
11 Mock 服务 MSW 拦截 /api/* 请求,提供本地模拟响应 --
12 第三方开发者控制台 允许开发者通过表单创建和管理 Dify/Coze API 集成。支持列表查看、启用/禁用、删除等功能。核心UI DeveloperConsolePage 已完成并通过单元测试。 API: /api/v1/dev/integrations
13 主题切换与设置 支持深色/浅色模式切换,自定义主题颜色、圆角等 ThemeContext, localStorage
14 样式调试面板 允许开发者在运行时修改设计令牌并导出配置 --

3. 验收标准引用

  • 各模块的详细验收标准见第7章"验收标准与测试方法",无需单独创建 specs/ 目录。

4. 页面样式与灵活主题设计

前端样式采用 设计变量 + 主题系统,确保在开发或上线后可以运行时灵活调整

4.1 设计变量 (tokens.css)

:root {
  --color-primary: #4FD1C5;
  --bg-primary: #1E1E2F;
  --text-primary: #F8F8F8;
  --error-color: #F56565;
  --warning-color: #ECC94B;
  --radius-base: 8px;
  --spacing-sm: 8px;
  --spacing-md: 16px;
  --spacing-lg: 24px;
  --font-base: 'Inter', sans-serif;
}

4.2 Ant Design Mobile 主题覆盖 (vite.config.ts)

import { defineConfig } from 'vite';
export default defineConfig({
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: {
          '@primary-color': 'var(--color-primary)',
          '@layout-body-background': 'var(--bg-primary)',
          '@text-color': 'var(--text-primary)',
          '@border-radius-base': 'var(--radius-base)',
        },
        javascriptEnabled: true,
      }
    }
  }
});

4.3 Styled-Components / Emotion 主题 (src/theme.js)

export const theme = {
  colors: {
    primary: 'var(--color-primary)',
    background: 'var(--bg-primary)',
    text: 'var(--text-primary)',
    error: 'var(--error-color)',
    warning: 'var(--warning-color)',
  },
  radii: { base: 'var(--radius-base)' },
  spacing: {
    sm: 'var(--spacing-sm)',
    md: 'var(--spacing-md)',
    lg: 'var(--spacing-lg)',
  },
  fontFamily: 'var(--font-base)',
};

4.4 运行时主题切换

  • 动态切换: 提供 ThemeProvider (通过 ThemeContext) 和相关设置组件 (ThemeToggle, ThemeSettings),允许用户切换预设主题(如深色/浅色)或自定义主题参数。修改会通过 CSS 变量实时生效:

    document.documentElement.style.setProperty('--color-primary', newColor);
  • 集成:通过 import StyleEditor from '@/components/StyleEditor' 嵌入到设置页面或特定的开发者调试区域。

4.5 UI/UX 动效与布局规范

  • 布局: 侧边栏 + 主区;底部状态栏展示录音/识别/执行进度。

  • 动效: 使用 Framer Motion:

    • 页面过渡淡入淡出 (opacity 0→1, y 10→0, duration 0.3s)
    • 按钮点击波纹(Ripple)效果
  • 可调整参数: 动效时长与缓动可通过 theme.transitions 进行全局配置。

4.6 建议

  • 保持所有样式通过变量驱动,避免硬编码。
  • 在 Storybook 中建立"Theme Switcher"体验,确保每个组件响应变量改变。
  • 组件库(shadcn/ui、AntD)均能通过上述变量层面实现不改源码的主题定制。

5. 本地开发与自动化流程

5.1 自动化驱动脚本 (auto-dev.sh)

#!/usr/bin/env bash
set -e
FEATURE_BRANCH=$1
SPEC_FILE=$2
if [ -z "$FEATURE_BRANCH" ] || [ -z "$SPEC_FILE" ]; then
  echo "Usage: ./auto-dev.sh <feature/xxx> <path/to/spec.md>"
  exit 1
fi

git checkout -b "$FEATURE_BRANCH"
 echo "🔧 AI 生成首版代码…"
 cursor complete --prompt "$(cat $SPEC_FILE)" > /dev/null
while true; do
  echo "🧪 本地运行测试…"
  npm ci
  npm run test:ci
  FAILS=$(jq '.stats.failures' reports/test-results.json)
  if [ "$FAILS" -eq "0" ]; then
    echo "✅ 测试全通过!"
    break
  fi
  echo "❌ 测试失败 ($FAILS), AI 修复补丁…"
  cursor complete \
    --prompt "请根据测试结果 JSON,生成可打补丁修复方案:" \
    --file reports/test-results.json \
    --output cursor-fix.patch
  git apply cursor-fix.patch
done
 echo "🎉 功能完成,请审查并提交远程分支。"

5.2 本地测试配置

package.json

{
  "scripts": {
    "test:ci": "cypress run" 
  },
  "devDependencies": {
    "cypress": "^12.0.0",
    "jq": "^1.6",
    "cypress-mochawesome-reporter": "^3.0.0"
  }
}

安装额外的测试依赖 (如果尚未安装):

# (在 frontend 目录下)
npm install --save-dev cypress-mochawesome-reporter jq cypress-axe axe-core

cypress.config.js (已集成HTML报告器)

const { defineConfig } = require('cypress')

module.exports = defineConfig({
  reporter: 'cypress-mochawesome-reporter',
  reporterOptions: {
    charts: true,
    reportPageTitle: 'Echo Project E2E Test Report',
    embeddedScreenshots: true,
    inlineAssets: true, 
    saveAllAttempts: false, 
  },
  e2e: {
    baseUrl: 'http://localhost:3000',
    setupNodeEvents(on, config) {
      require('cypress-mochawesome-reporter/plugin')(on);
      on('task', {
        log(message) {
          console.log(message)
          return null
        },
        table(message) {
          console.table(message)
          return null
        },
      })
    },
  },
})

测试报告: 当通过 npm run test:cicypress run 执行测试后,详细的HTML测试报告会自动生成在 cypress/reports/html/index.html

无障碍测试 (Accessibility Testing) with cypress-axe: 为了确保应用的无障碍性,我们在E2E测试中集成了 cypress-axe

  1. 确保已导入 cypress-axefrontend/cypress/support/e2e.js 文件中:
    // frontend/cypress/support/e2e.js
    import './commands'
    import 'cypress-axe' // 确保这行已取消注释
  2. 在你的测试用例中,通常在页面加载或重要UI交互后,注入并运行检查:
    // 示例: my_test.cy.js
    cy.visit('/some-page');
    cy.injectAxe();
    cy.checkA11y(); // 检查整个页面
    // cy.checkA11y('.specific-component', { /* options */ }); // 或检查特定组件

### 5.3 AI 调用模板

```bash
cursor complete --prompt "基于 ADM + React,按第7章内容生成登录组件。"
cursor complete --prompt "基于第7章内容生成 Cypress E2E 脚本。"
cursor complete --prompt "以下是测试结果 JSON,请生成修复补丁:" --file reports/test-results.json --output cursor-fix.patch

5.4 Mock 服务配置

// src/mocks/handlers.js
import {rest} from 'msw'; export const handlers=[rest.post('/api/login',(req,res,ctx)=>{const{password}=req.body;return password==='correct'?res(ctx.status(200),ctx.json({token:'abc'})):res(ctx.status(401),ctx.json({message:'密码不正确'}));}),rest.get('/api/services',(req,res,ctx)=>res(ctx.status(200),ctx.json([{id:'translate',name:'文本翻译',description:'中英互译',icon:'/icons/translate.svg'}]))];
// src/mocks/browser.js
import{setupWorker}from'msw';import{handlers}from'./handlers';export const worker=setupWorker(...handlers);
// src/index.js
if(process.env.NODE_ENV==='development'){import('./mocks/browser').then(({worker})=>worker.start());}

5.5 服务目录组件示例

export function ServiceDirectory(){const[services,setServices]=useState([]);useEffect(()=>fetch('/api/services').then(r=>r.json()).then(setServices),[]);return (<div style={{display:'grid',gridTemplateColumns:'repeat(auto-fill,minmax(140px,1fr))',gap:'16px'}}>{services.map(svc=>(<Card key={svc.id}><img src={svc.icon}/><h4>{svc.name}</h4><p>{svc.description}</p><Button>调用</Button></Card>))}</div>);}  

5.6 全自动测试闭环说明

  • 流程: auto-dev.sh 自动化执行 AI 生成 → npm run test:ci → 解析 reports/test-results.json → AI 修复 → 直至测试通过
  • 无需手动触发测试或查看日志,全部由脚本与工具完成。

5.7 版本管理 & 同步

npm version patch
git add package.json
git commit -m "chore: bump version"
git push origin HEAD --follow-tags

6. 其他注意事项

6.1 第三方开发者控制台

  • 功能: 通过表单创建、管理 Dify/Coze API 集成
  • 访问控制: 仅对具有 "developer" 或 "admin" 角色的用户可见
  • 创建流程:
    1. 开发者登录后进入控制台,点击"创建 API 集成"
    2. 选择平台类型(Dify 或 Coze)
    3. 填写表单:
      • Dify:集成名称、描述、API Key (app-*),响应模式自动设为 blocking
      • Coze:集成名称、描述、API Key (pat-*)、Bot ID
    4. 点击"创建并测试连接"
    5. 后端自动执行:
      • 格式验证(API Key 格式、HTTPS 检查)
      • 连通性测试(发送测试消息到 Dify/Coze)
      • 自动生成 tool_id 和 request_schema
      • Dify 自动强制使用 blocking 模式(SSE 流式暂未支持)
    6. 测试通过 → 创建成功,立即可用
    7. 测试失败 → 显示详细错误(如"API Key 无效"、"Bot ID 不存在")
  • 管理功能:
    • 列表查看:显示所有已创建的 API 集成
    • 启用/禁用:控制集成在服务目录中的可见性
    • 删除:移除不再需要的集成
  • UI 要点:
    • 表单动态切换(根据平台显示不同字段)
    • 实时验证(前端格式校验 + 后端连通性测试)
    • 详细错误反馈(连接失败时显示具体原因)
    • 创建成功后自动刷新列表

6.2 状态管理架构

  • 使用 React Context + useReducer 管理核心状态:

    • SessionContext: { sessionId, stage }
    • UserConfigContext: { contacts, wallets }
    • ThemeContext: { theme, setTheme }
    • AuthContext: { user, token, role }
  • 关键 Hooks:

    • useSession(): 对话流程与阶段切换
    • useVoice(): 封装 Web Speech API 录音与 TTS
    • useIntent(): 意图分类与分发
    • useApi(): apiClient 封装与错误处理

6.2 用户角色与权限体系

  • 用户角色:

    • user: 普通用户,访问基本功能
    • developer: 开发者用户,可访问开发者控制台,上传和管理自定义API
    • admin: 管理员用户,拥有所有权限
  • 权限控制实现:

    • 基于 AuthContext 中存储的用户角色信息
    • 使用增强的 ProtectedRoute 组件,支持 requireRole 参数
    • 根据用户角色动态生成导航菜单项
    • 后端通过JWT中携带的角色信息验证API访问权限
  • 界面差异:

    • 普通用户: 不显示"开发者"导航项,无法访问开发者控制台
    • 开发者用户: 显示"开发者"导航项,可访问开发者控制台管理自己的API
    • 管理员用户: 拥有所有界面访问权限

7. 验收标准与测试方法

以下集中列出各模块的 Gherkin 场景与测试要点,复制即可用作 auto-dev.sh 的 Spec 输入。

7.1 登录组件

Feature: 登录组件
  Scenario: 正常登录
    Given 登录页已打开
    When 输入用户名 "alice" 和密码 "correct"
    And 点击 "登录" 按钮
    Then 页面应跳转到首页

  Scenario: 密码错误
    Given 登录页已打开
    When 输入用户名 "alice" 和密码 "wrong"
    And 点击 "登录" 按钮
    Then 页面应显示红色提示 "密码不正确"

测试要点: 单元(Jest+RTL)、E2E(Cypress)、Mock(MSW)

7.2 注册组件

Feature: 注册组件
  Scenario: 成功注册
    Given 注册页已打开
    When 输入邮箱 "test@example.com"、用户名 "bob" 和密码 "123456"
    And 点击 "注册" 按钮
    Then 页面应显示绿色提示 "注册成功"
  Scenario: 邮箱格式错误
    Given 注册页已打开
    When 输入邮箱 "invalid-email"
    And 点击 "注册" 按钮
    Then 页面应显示红色提示 "请输入有效邮箱"

测试要点: 表单校验、E2E 脚本、Mock

7.3 首页列表

Feature: 首页列表
  Scenario: 列表加载
    Given 首页已打开
    When 后端返回 5 条条目
    Then 页面应渲染 5 个列表项
  Scenario: 下拉刷新
    Given 列表已渲染
    When 用户下拉页面
    Then 发送新请求并刷新列表

测试要点: 组件渲染、下拉操作、Mock 响应

7.4 语音录制控件

Feature: 语音录制控件
  Scenario: 点击录音
    Given 页面加载完毕
    When 点击 "录音" 按钮
    Then 按钮文本变为 "停止" 且开始捕获音频流
  Scenario: 录音超时
    Given 录音进行 60 秒
    Then 页面弹出 "录音超时" 并自动停止

测试要点: 模拟 Timer、fake-audio、超时逻辑

7.5 语音识别结果展示

Feature: 语音识别结果展示
  Scenario: STT 成功
    Given 录音上传完成
    When 后端返回文本 "你好"
    Then 页面应显示 "你好" 并触发执行流程

测试要点: Hook 模拟、E2E 断言结果

7.6 技能服务目录

Feature: 服务目录
  Scenario: 服务列表加载
    Given 服务页已打开
    When 后端返回 3 个服务
    Then 页面应展示 3 个卡片
  Scenario: 搜索过滤
    Given 在搜索框输入关键字
    When 匹配服务列表
    Then 只显示匹配卡片

测试要点: 列表渲染、搜索输入、Mock 响应

7.7 进度条组件

Feature: 进度条组件
  Scenario: 阶段渲染
    Given 状态为 "理解中"
    Then 进度条填充至 50% 并高亮文本

测试要点: Props 驱动渲染、样式断言

7.8 通用弹窗/Toast

Feature: 全局提示
  Scenario: 显示错误信息
    Given 调用 showError("错误消息")
    Then 页面顶部出现红色 Toast 文本 "错误消息"

测试要点: 调用函数、断言组件显示

7.9 全局布局 & 404

Feature: 全局布局 & 404 (包括Header, Footer)
  Scenario: 访问首页应包含页眉和页脚
    Given 用户访问首页
    Then 页面应正确渲染 Header 组件
    And 页面应正确渲染 Footer 组件
  Scenario: 未知路由
    Given 访问 `/unknown`
    Then 展示 404 页面

测试要点: 路由断言、404 文案、Header/Footer 组件渲染、已集成 jest-axe 进行无障碍测试 (Footer)。

7.10 错误边界捕获

Feature: 错误边界
  Scenario: 组件抛错
    Given 子组件抛出异常
    Then ErrorBoundary 捕获并展示友好提示

测试要点: 手动抛错、断言异常 UI

7.11 Mock 服务

Feature: Mock 服务
  Scenario: 返回模拟登录成功
    Given 开发环境已开启 Mock
    When 访问 "/api/login" 并传入正确密码
    Then MSW 应返回 {"token":"abc"}

  Scenario: 关闭 Mock 回退真实后端
    Given 开发环境已关闭 Mock
    When 访问 "/api/login"
    Then 请求应发送到真实后端服务

测试要点: 验证 handlers.js 中的 Mock 逻辑,E2E 场景断言接口返回及环境切换

7.12 第三方开发者控制台

Feature: 第三方开发者控制台 - Dify API 集成创建
  Scenario: 成功创建 Dify API 集成
    Given 已以开发者身份登录控制台
    And 选择平台类型为 "Dify"
    When 填写集成名称 "客服助手"
    And 填写 API Key "app-validkey123"
    And 点击 "创建并测试连接" 按钮
    Then 页面应显示 "正在测试连接..."
    And 后端应自动将响应模式设为 blocking(强制)
    And 后端应发送测试消息到 Dify API
    And 页面应显示 "创建成功"
    And 集成列表中应出现 "客服助手"

  Scenario: API Key 格式错误
    Given 已以开发者身份登录控制台
    When 填写 API Key "wrong-key"(不以 app- 开头)
    And 点击创建按钮
    Then 页面应立即显示错误 "Dify API Key 必须以 'app-' 开头"
    And 不应发送测试请求

  Scenario: 连通性测试失败
    Given 填写了格式正确但无效的 API Key "app-invalidkey"
    When 点击创建按钮
    Then 后端应尝试连接 Dify API
    And 页面应显示详细错误 "连通性测试失败 (dify):API Key 无效或已过期,请检查后重新提交"
    And API 集成不应被创建

Feature: 第三方开发者控制台 - Coze API 集成创建
  Scenario: 成功创建 Coze API 集成
    Given 选择平台类型为 "Coze"
    When 填写 API Key "pat_validkey"
    And 填写 Bot ID "7234567890"
    And 点击创建按钮
    Then 应成功创建 API 集成

  Scenario: Bot ID 不存在
    Given 填写了正确的 API Key 但错误的 Bot ID
    When 点击创建按钮
    Then 页面应显示 "连通性测试失败 (coze):Bot ID 不存在,请确认 Bot ID 是否正确"

Feature: 第三方开发者控制台 - 管理功能
  Scenario: 启用/禁用 API 集成
    Given 控制台列表中有 API 集成 "客服助手"(状态为启用)
    When 点击 "禁用" 按钮
    Then 集成状态应变为 "已禁用"
    And 该集成在服务目录中应不可见

  Scenario: 删除 API 集成
    Given 控制台列表中有 API 集成 "客服助手"
    When 点击 "删除" 按钮
    And 确认删除操作
    Then API 集成应从列表中移除

测试要点:

  • 表单提交与验证(格式校验 + 连通性测试)
  • 错误处理(网络错误、API 错误、超时)
  • 列表渲染、状态切换、删除操作
  • Mock 与真实后端联调
  • DeveloperConsolePage 组件单元测试(Jest+RTL)

7.13 主题切换与设置 (ThemeToggle, ThemeSettings, SettingsPage 相关部分)

Feature: 主题切换与设置
  Scenario: 切换主题模式
    Given 用户在设置页面
    When 点击主题切换按钮 (ThemeToggle)
    Then 应用的主题(如背景色、文字颜色)应在深色/浅色模式间切换
    And 主题选择应被持久化存储
  Scenario: 调整自定义主题参数
    Given 用户在主题设置组件 (ThemeSettings)
    When 修改主色调或圆角大小
    Then 应用界面的对应样式应实时更新
  Scenario: 无障碍访问检查
    Given ThemeToggle, ThemeSettings, SettingsPage 组件已渲染
    Then 组件应通过 jest-axe 无障碍规范检查

测试要点: UI交互、样式变更断言、localStorage持久化验证、已集成 jest-axe 进行无障碍测试。


文档完