017.014.story.md 22 KB

故事017.014: 个人信息页样式对照原型调整

元信息

  • 史诗: 017 - 人才小程序功能实现
  • 优先级: P1 - 用户体验改进
  • 状态: Ready for Review
  • 创建日期: 2025-12-26
  • 负责人: 开发团队

故事描述

作为 人才小程序开发者, 我想要 调整个人信息页面的布局和样式以符合原型设计, 以便 用户获得与原型一致的视觉体验和交互体验。

背景

现有实现状态:

  • ✅ 故事017.003已完成个人信息页基础功能实现
  • ✅ 个人基本信息、银行卡信息、证件照片查询功能正常
  • ✅ Navbar导航栏集成完成(TabBar页面,无返回按钮)
  • ✅ 测试覆盖完整(20个测试用例全部通过)

原型设计参考:

  • docs/小程序原型/rencai.html 提供了个人信息页面的完整原型设计
  • 个人信息页 (原型行483-628): 包含顶部用户信息区域、个人基本信息、银行卡信息、证件照片

发现的主要差异:

  1. 缺少顶部用户信息区域 - 原型有渐变背景的用户头像和状态展示区域
  2. 银行卡卡片样式不符 - 原型使用蓝色背景,当前实现使用白色
  3. 证件照片布局差异 - 原型使用2x2网格布局带边框
  4. Navbar标题不一致 - 原型显示"个人信息",当前显示"我的"

技术依赖:

  • ✅ 故事017.001: rencai mini ui包基础框架搭建完成
  • ✅ 故事017.002: 登录与首页实现完成
  • ✅ 故事017.003: 个人信息功能实现完成
  • ✅ 故事017.012: 统一Navbar导航栏组件规范完成
  • ✅ API接口正常工作(个人信息、银行卡、证件照片查询)

技术栈:

  • React 19.1.0
  • Taro 4.1.4
  • Tailwind CSS 4.1.11
  • Jest 30.2.0 (mini项目使用Jest)

验收标准

顶部用户信息区域

  • 添加渐变背景的顶部用户信息区域(蓝色渐变 bg-gradient-to-b from-blue-500 to-blue-700)
  • 显示用户头像(圆形,带白色边框,使用用户姓名首字作为占位符)
  • 显示用户姓名(大号字体,加粗)
  • 显示用户状态(残疾类型、等级、就业状态,如: "肢体残疾 · 三级 · 在职")
  • 右上角显示相机图标按钮(头像编辑功能,暂不实现点击功能)
  • 头像尺寸: 64x64 (w-16 h-16)
  • 文字颜色: 白色
  • 区域内边距: p-5

银行卡信息卡片样式

  • 银行卡信息卡片使用蓝色背景(bg-blue-50)
  • 卡片内边距: p-4
  • 右上角添加"添加"按钮(蓝色文字,带加号图标)
  • 银行名称使用较大字体(中号,加粗)
  • "默认"标签使用蓝色背景(bg-blue-100 蓝色文字 text-blue-800)
  • 卡号使用大号字体加粗显示(text-lg font-bold)
  • 显示持卡人姓名(小号灰色文字)
  • 保持现有银行卡数据查询功能

证件照片显示样式

  • 使用2x2网格布局(grid grid-cols-2 gap-3)
  • 每个照片项带边框(border border-gray-200 rounded-lg)
  • 照片区域内边距: p-3
  • 无照片时显示占位图标
  • 证件类型显示在照片下方(居中,小号文字)
  • 保持照片预览功能
  • 支持的证件类型: 身份证、残疾证、体检报告、征信报告

Navbar标题调整

  • Navbar标题从"我的"改为"个人信息"
  • 保持TabBar页面配置(无返回按钮)

页面整体布局

  • 页面滚动区域正确配置(减去TabBar高度)
  • 卡片之间间距正确(mb-4)
  • 内容区域内边距正确(px-4 py-3)
  • 所有数据加载状态正常显示
  • 错误处理正常工作

测试覆盖

  • 更新现有测试用例以匹配新的UI结构
  • 测试顶部用户信息区域渲染
  • 测试银行卡卡片新样式
  • 测试证件照片网格布局
  • 所有测试通过
  • 类型检查通过

任务列表

任务1: 创建顶部用户信息区域组件 (AC: 顶部用户信息区域)

  • 1.1 在@d8d/rencai-personal-info-ui中创建UserInfoHeader.tsx组件
  • 1.2 实现渐变背景容器(bg-gradient-to-b from-blue-500 to-blue-700)
  • 1.3 实现用户头像展示:
    • 圆形头像,64x64尺寸(w-16 h-16 rounded-full)
    • 白色边框(border-2 border-white)
    • 使用用户姓名首字作为占位符(蓝色背景,白色文字)
    • 头像位于左侧
  • 1.4 实现用户信息展示:
    • 用户姓名(大号加粗,text-xl font-bold)
    • 用户状态(小号透明度80,显示"残疾类型 · 等级 · 就业状态")
    • 信息位于头像右侧
  • 1.5 实现右上角相机按钮:
    • 半透明白色背景(bg-white/20)
    • 圆形按钮(rounded-full p-2)
    • 使用Heroicons相机图标(i-heroicons-camera-20-solid)
    • 暂不实现点击功能
  • 1.6 集成到PersonalInfoPage页面组件(位于Navbar下方)
  • 1.7 从个人信息数据中提取相关字段(姓名、残疾类型、等级、就业状态)

任务2: 调整银行卡信息卡片样式 (AC: 银行卡信息卡片样式)

  • 2.1 修改BankCardInfo.tsx组件卡片容器样式:
    • 添加蓝色背景(bg-blue-50)
  • 2.2 修改BankCardItem.tsx组件布局样式:
    • 银行名称: 使用较大字体加粗(font-medium text-gray-800)
    • 卡号: 使用大号字体加粗(text-lg font-bold text-gray-800)
    • 卡类型: 保持小号灰色文字(text-sm text-gray-600)
    • 持卡人姓名: 新增显示,小号灰色文字(text-sm text-gray-600 mt-2)
  • 2.3 调整"默认"标签样式:
    • 使用蓝色背景(bg-blue-100)
    • 蓝色文字(text-blue-800)
    • 小号文字带圆角(text-xs px-2 py-1 rounded-full)
  • 2.4 在BankCardInfo.tsx中添加"添加"按钮:
    • 位于卡片标题右侧
    • 蓝色文字(text-blue-500)
    • 带加号图标(i-heroicons-plus-20-solid)
    • 小号文字(text-sm)
    • 暂不实现点击功能
  • 2.5 验证银行卡数据查询功能正常工作

任务3: 调整证件照片显示样式 (AC: 证件照片显示样式)

  • 3.1 修改DocumentPhotos.tsx组件容器布局:
    • 使用2x2网格布局(grid grid-cols-2 gap-3)
  • 3.2 修改DocumentPhotoItem.tsx组件样式:
    • 添加边框(border border-gray-200 rounded-lg)
    • 添加内边距(p-3)
    • 居中对齐(text-center)
  • 3.3 调整照片区域样式:
    • 正方形宽高比(aspect-square)
    • 圆角(rounded-lg)
    • 灰色背景(bg-gray-100)
    • 居中显示(mx-auto mb-2)
  • 3.4 调整占位图标:
    • 使用FontAwesome图标风格(如果可用)
    • 或使用Heroicons图标(i-heroicons-document-20-solid)
    • 灰色文字(text-gray-400)
    • 2xl尺寸(text-2xl)
  • 3.5 调整证件类型文字:
    • 居中显示(text-center)
    • 小号文字(text-xs)
    • 灰色文字(text-gray-600)
    • 单行截断(line-clamp-1)
  • 3.6 验证照片预览功能正常工作

任务4: 调整Navbar标题 (AC: Navbar标题调整)

  • 4.1 修改PersonalInfoPage.tsx中Navbar的title属性
  • 4.2 将title从"我的"改为"个人信息"
  • 4.3 验证TabBar页面配置保持正确(无返回按钮)

任务5: 更新测试用例 (AC: 测试覆盖)

  • 5.1 更新tests/pages/PersonalInfoPage/PersonalInfoPage.test.tsx:
    • 添加顶部用户信息区域渲染测试
    • 更新银行卡卡片样式断言
    • 更新证件照片布局断言
  • 5.2 更新tests/unit/components/PersonalBasicInfo.test.tsx(如果需要)
  • 5.3 更新tests/unit/components/BankCardItem.test.tsx:
    • 测试新的蓝色背景样式
    • 测试持卡人姓名显示
  • 5.4 更新tests/unit/components/DocumentPhotoItem.test.tsx:
    • 测试新的边框样式
    • 测试网格布局
  • 5.5 运行所有测试确保通过
  • 5.6 运行pnpm typecheck确保类型检查通过

任务6: 更新故事文档和文件列表 (AC: 完成)

  • 6.1 在故事017.003的"变更日志"中添加样式调整说明
  • 6.2 在故事017.003的"文件列表"中添加本故事修改的文件
  • 6.3 在本故事的"开发者记录"中更新完成说明
  • 6.4 在本故事的"文件列表"中记录所有修改的文件

开发者笔记

原型设计参考

来源: docs/小程序原型/rencai.html (行483-628)

顶部用户信息区域 (行498-513):

<div class="gradient-bg text-white p-5">
  <div class="flex justify-between items-start">
    <div class="flex items-center">
      <div class="w-16 h-16 rounded-full border-2 border-white mr-4 bg-blue-500 flex items-center justify-center text-white text-xl font-bold">
        张
      </div>
      <div>
        <h2 class="text-xl font-bold">张明</h2>
        <p class="text-sm opacity-80">肢体残疾 · 三级 · 在职</p>
      </div>
    </div>
    <button class="bg-white/20 rounded-full p-2">
      <i class="fas fa-camera text-white"></i>
    </button>
  </div>
</div>

银行卡信息卡片 (行556-573):

<div class="card bg-white p-4 mb-4">
  <div class="flex justify-between items-center mb-3">
    <h3 class="font-semibold text-gray-700">银行卡信息</h3>
    <button class="text-blue-500 text-sm">
      <i class="fas fa-plus mr-1"></i>添加
    </button>
  </div>
  <div class="bg-blue-50 rounded-lg p-4">
    <div class="flex justify-between items-center mb-2">
      <p class="font-medium text-gray-800">中国工商银行</p>
      <span class="bg-blue-100 text-blue-800 text-xs px-2 py-1 rounded-full">默认</span>
    </div>
    <p class="text-sm text-gray-600 mb-1">储蓄卡</p>
    <p class="text-lg font-bold text-gray-800">**** **** **** 5678</p>
    <p class="text-sm text-gray-600 mt-2">持卡人:张明</p>
  </div>
</div>

证件照片 (行575-604):

<div class="card bg-white p-4">
  <h3 class="font-semibold text-gray-700 mb-3">证件照片</h3>
  <div class="grid grid-cols-2 gap-3">
    <div class="border border-gray-200 rounded-lg p-3 text-center">
      <div class="w-12 h-12 rounded-lg bg-gray-100 flex items-center justify-center mx-auto mb-2">
        <i class="fas fa-id-card text-gray-400"></i>
      </div>
      <p class="text-xs text-gray-600">身份证</p>
    </div>
    <!-- 其他证件类型... -->
  </div>
</div>

前置故事见解

故事017.003完成状态:

  • ✅ 个人信息页基础功能完整实现
  • ✅ 个人基本信息、银行卡信息、证件照片查询功能正常
  • ✅ 数据脱敏逻辑正确实现
  • ✅ 照片预览功能正常工作
  • ✅ Navbar导航栏集成完成(TabBar页面)
  • ✅ 测试覆盖完整(20个测试用例)
  • ⚠️ 但发现与原型设计存在显著样式差异

故事017.012完成状态:

  • ✅ 统一Navbar导航栏组件规范
  • ✅ TabBar页面使用Navbar无返回按钮(leftIcon="" leftText="")
  • ✅ Navbar样式与用人方小程序保持一致

故事017.013完成状态:

  • ✅ 首页(Dashboard)样式对照原型调整
  • ✅ 提供了样式调整的最佳实践参考

技术栈要求

来源: architecture/tech-stack.md

运行时和框架:

  • Node.js: 20.18.3
  • React: 19.1.0 (UI组件)
  • Taro: 4.1.4 (小程序框架)
  • Tailwind CSS: 4.1.11 (样式)

测试框架:

  • Jest: 30.2.0 (mini项目使用Jest,不是Vitest!)
  • ts-jest: 29.4.5 (TypeScript预处理器)
  • @testing-library/react: 16.3.0 (React组件测试)
  • @d8d/mini-testing-utils: workspace包 (Taro小程序测试工具)

Mini UI包开发规范

来源: architecture/mini-ui-package-standards.md

关键规范要求:

1. Taro小程序布局规范

重要: 在Taro小程序中,<View> 组件内的子元素默认是横向布局flex-row),需要显式添加 flex flex-col 类才能实现垂直布局

正确示例:

// ✅ 正确: 使用 flex flex-col 实现垂直布局
<View className="flex flex-col">
  <Text>姓名: 张三</Text>
  <Text>性别: 男</Text>
</View>

// ❌ 错误: 缺少 flex flex-col,子元素会横向排列
<View>
  <Text>姓名: 张三</Text>
  <Text>性别: 男</Text>
</View>

2. 图标使用规范

必须使用Heroicons图标类:不要使用emoji或文本符号。

图标类命名格式i-heroicons-{icon-name}-{size}-{style}

正确示例:

// ✅ 正确: 使用Heroicons图标类
<View className="i-heroicons-camera-20-solid w-5 h-5 text-white" />
<View className="i-heroicons-plus-20-solid text-blue-500" />
<View className="i-heroicons-document-20-solid text-gray-400" />

// ❌ 错误: 使用emoji或FontAwesome
<Text>📷</Text>
<i class="fas fa-camera"></i>

本故事需要的图标:

  • camera-20-solid - 相机图标(右上角头像编辑按钮)
  • plus-20-solid - 加号图标(银行卡添加按钮)
  • document-20-solid - 文档图标(证件照片占位)

3. 渐变背景规范

Tailwind CSS渐变类:

// 蓝色渐变(从上到下)
<View className="bg-gradient-to-b from-blue-500 to-blue-700">
  {/* 内容 */}
</View>

// 其他常用渐变方向:
// bg-gradient-to-r (从左到右)
// bg-gradient-to-l (从右到左)
// bg-gradient-to-t (从下到上)

4. 网格布局规范

Tailwind CSS网格类:

// 2x2网格布局
<View className="grid grid-cols-2 gap-3">
  <View>项目1</View>
  <View>项目2</View>
  <View>项目3</View>
  <View>项目4</View>
</View>

// 其他网格配置:
// grid-cols-1 (单列)
// grid-cols-3 (三列)
// gap-4 (更大间距)

5. 边框样式规范

Tailwind CSS边框类:

// 完整边框
<View className="border border-gray-200 rounded-lg p-3">
  {/* 内容 */}
</View>

// 其他边框样式:
// border-0 (无边框)
// border-2 (加粗边框)
// rounded (圆角)
// rounded-full (完全圆角)

项目结构指南

来源: architecture/source-tree.md

rencai-personal-info-ui包结构:

mini-ui-packages/rencai-personal-info-ui/
├── src/
│   ├── api/
│   │   ├── talentPersonalInfoClient.ts
│   │   └── index.ts
│   ├── components/
│   │   ├── PersonalBasicInfo.tsx
│   │   ├── BankCardInfo.tsx
│   │   ├── BankCardItem.tsx
│   │   ├── DocumentPhotos.tsx
│   │   ├── DocumentPhotoItem.tsx
│   │   └── UserInfoHeader.tsx (本故事新增)
│   ├── pages/
│   │   └── PersonalInfoPage/
│   │       └── PersonalInfoPage.tsx (本故事修改)
│   ├── utils/
│   │   └── maskUtils.ts
│   └── index.ts
├── tests/
│   ├── unit/
│   │   └── components/
│   │       ├── PersonalBasicInfo.test.tsx
│   │       ├── BankCardItem.test.tsx (本故事修改)
│   │       └── DocumentPhotoItem.test.tsx (本故事修改)
│   └── pages/
│       └── PersonalInfoPage/
│           └── PersonalInfoPage.test.tsx (本故事修改)
├── package.json
├── jest.config.cjs
└── tsconfig.json

UI包内部导入规范

重要: UI包内部导入必须使用相对路径,不要使用别名。

正确示例:

// ✅ 正确: 使用相对路径导入同一包内的模块
import { talentPersonalInfoClient } from '../../api'
import { BankCardItem } from '../components/BankCardItem'
import UserInfoHeader from '../components/UserInfoHeader'

错误示例:

// ❌ 错误: 不要使用别名导入UI包内部的模块
import { talentPersonalInfoClient } from '@/api'
import { BankCardItem } from '@/components/BankCardItem'
import UserInfoHeader from '@/components/UserInfoHeader'

数据模型参考

个人信息数据结构 (从故事017.003):

export interface PersonalInfoResponse {
  name: string              // 姓名
  gender: string            // 性别
  idCard: string            // 身份证号
  disabilityId: string      // 残疾证号
  disabilityType: string    // 残疾类型
  disabilityLevel: string   // 残疾等级
  phone: string             // 联系电话
  province: string          // 省份
  city: string              // 城市
  district: string | null   // 区县
  detailedAddress: string | null  // 详细地址
  birthDate: string | null  // 出生日期
  jobStatus: number         // 就业状态 (0-待业, 1-在职)
  // ... 其他字段
}

就业状态映射:

const jobStatusMap: Record<number, string> = {
  0: '待业',
  1: '在职'
}

银行卡数据结构 (从故事017.003):

export interface BankCardInfo {
  id: number
  subBankName: string       // 支行名称
  bankName: string | null   // 银行名称
  cardNumber: string        // 卡号
  cardholderName: string    // 持卡人姓名
  cardType: string | null   // 卡类型
  isDefault: number         // 是否默认 (0-否, 1-是)
  fileUrl: string | null    // 证件照片URL
}

测试策略

来源: architecture/mini-ui-testing-standards.md

测试框架: Jest (mini项目使用Jest,不是Vitest!)

测试要求:

  1. 更新现有测试用例以匹配新的UI结构
  2. 测试顶部用户信息区域渲染
  3. 测试银行卡卡片新样式
  4. 测试证件照片网格布局
  5. 验证数据查询功能不受影响
  6. 运行pnpm typecheck确保类型检查通过

测试执行:

# 运行所有测试
cd mini-ui-packages/rencai-personal-info-ui && pnpm test

# 运行特定测试
pnpm test --testNamePattern="UserInfoHeader"
pnpm test --testNamePattern="PersonalInfoPage"

# 生成覆盖率报告
pnpm test:coverage

技术约束

  1. 向后兼容: 不影响现有mini-talent项目功能
  2. 类型安全: 使用TypeScript严格模式,所有组件必须有类型定义
  3. 模块独立性: 新组件遵循UI包内部导入规范
  4. 测试覆盖: 所有修改的组件必须有测试覆盖
  5. 代码规范: 遵循Mini UI包开发规范
  6. 数据安全: 保持现有的数据脱敏逻辑不变

风险和缓解措施

主要风险:

  1. 布局调整风险: 顶部用户信息区域可能影响整体页面布局
  2. 样式冲突风险: 新的样式可能与现有样式冲突
  3. 测试更新风险: 测试用例需要大幅更新
  4. 数据字段缺失风险: 就业状态字段可能需要额外处理

缓解措施:

  1. 分阶段实现: 先实现顶部区域,再调整银行卡,最后调整证件照片
  2. 参考原型: 严格按照原型设计实现样式
  3. 渐进式测试: 每完成一个组件立即测试
  4. 类型安全: 使用TypeScript确保类型正确
  5. 数据验证: 验证所有需要的数据字段都存在

测试

测试框架和模式

来源: architecture/testing-strategy.md

测试框架:

  • Jest: 30.2.0 (mini项目使用Jest,不是Vitest!)
  • ts-jest: 29.4.5 (TypeScript预处理器)
  • @testing-library/react: 16.3.0 (React组件测试)
  • @d8d/mini-testing-utils: workspace包 (Taro小程序测试工具)

测试要求

  1. 组件测试:

    • 测试UserInfoHeader组件渲染正确
    • 测试银行卡卡片新样式
    • 测试证件照片网格布局
    • 测试Navbar标题正确显示
  2. 布局测试:

    • 测试顶部用户信息区域样式
    • 测试渐变背景正确应用
    • 测试网格布局正确渲染
  3. 集成测试:

    • 测试PersonalInfoPage页面整体布局
    • 测试数据查询功能不受样式调整影响
    • 测试滚动区域配置正确
  4. 回归测试:

    • 验证现有功能不受影响
    • 运行pnpm typecheck确保类型检查通过

测试执行

# 运行所有测试
cd mini-ui-packages/rencai-personal-info-ui && pnpm test

# 运行特定测试
pnpm test --testNamePattern="UserInfoHeader"
pnpm test --testNamePattern="BankCardItem"
pnpm test --testNamePattern="DocumentPhotoItem"
pnpm test --testNamePattern="PersonalInfoPage"

# 生成覆盖率报告
pnpm test:coverage

变更日志

日期 版本 描述 作者
2025-12-26 1.0 创建故事文档 James (Dev Agent)

开发者记录

此部分由开发代理在实施过程中填写

使用的代理模型

Claude Sonnet (claude-sonnet-4-20250514)

调试日志引用

无重大调试问题。实施过程顺利。

完成说明列表

  1. ✅ 创建了 UserInfoHeader 组件,实现了渐变背景的顶部用户信息区域
  2. ✅ 更新了 BankCardInfo 和 BankCardItem 组件,采用蓝色背景样式和新的布局
  3. ✅ 更新了 DocumentPhotos 和 DocumentPhotoItem 组件,添加边框样式和新的占位图标
  4. ✅ 更新了 PersonalInfoPage 页面,集成 UserInfoHeader 并调整 Navbar 标题为"个人信息"
  5. ✅ 更新了所有相关测试用例,新增 UserInfoHeader.test.tsx
  6. ✅ 修复了 UserInfoHeader 在 personalInfo 为 null 时不显示的问题
  7. ✅ 为所有卡片组件添加 flex flex-col 以确保正确的垂直布局(Taro 小程序规范)
  8. ✅ 所有 28 个测试用例通过
  9. ✅ TypeScript 类型检查通过
  10. ✅ 包成功构建

文件列表

新增文件:

  • mini-ui-packages/rencai-personal-info-ui/src/components/UserInfoHeader.tsx - 顶部用户信息区域组件
  • mini-ui-packages/rencai-personal-info-ui/tests/unit/components/UserInfoHeader.test.tsx - UserInfoHeader 组件测试

修改文件:

  • mini-ui-packages/rencai-personal-info-ui/src/pages/PersonalInfoPage/PersonalInfoPage.tsx - 集成 UserInfoHeader,更新 Navbar 标题
  • mini-ui-packages/rencai-personal-info-ui/src/components/BankCardInfo.tsx - 添加"添加"按钮,添加 flex flex-col
  • mini-ui-packages/rencai-personal-info-ui/src/components/BankCardItem.tsx - 蓝色背景样式,显示持卡人姓名
  • mini-ui-packages/rencai-personal-info-ui/src/components/DocumentPhotos.tsx - 添加 flex flex-col
  • mini-ui-packages/rencai-personal-info-ui/src/components/DocumentPhotoItem.tsx - 添加边框样式,更新占位图标
  • mini-ui-packages/rencai-personal-info-ui/src/components/PersonalBasicInfo.tsx - 添加 flex flex-col
  • mini-ui-packages/rencai-personal-info-ui/tests/pages/PersonalInfoPage/PersonalInfoPage.test.tsx - 更新测试用例
  • mini-ui-packages/rencai-personal-info-ui/tests/unit/components/BankCardItem.test.tsx - 更新测试用例
  • mini-ui-packages/rencai-personal-info-ui/tests/unit/components/DocumentPhotoItem.test.tsx - 更新测试用例
  • mini-ui-packages/rencai-personal-info-ui/tests/unit/components/UserInfoHeader.test.tsx - 更新测试用例以匹配新行为

QA结果

此部分由QA代理在审查完成后填写