017.001.story.md 42 KB

故事017.001: rencai mini ui包基础框架搭建

元信息

  • 史诗: 017 - 人才小程序功能实现
  • 优先级: P1 - 核心基础设施
  • 状态: Approved
  • 创建日期: 2025-12-25
  • 负责人: 开发团队

故事描述

作为 人才小程序开发者, 我想要 搭建rencai系列mini ui包的基础框架, 以便 为人才小程序的6个核心页面提供可复用的UI组件和API客户端集成,建立完整的技术基础。

背景

现有系统状态:

  • 史诗015已完成3/8核心故事(38%),核心API就绪
  • 人才用户认证API和个人信息查询API已实现
  • mini-talent项目已从mini项目复制基础框架
  • mini-ui-packages目录下已有yongren系列UI包作为参考

原型设计参考:

  • docs/小程序原型/rencai.html 提供了完整的6个页面原型设计
  • 原型包含: 登录页、首页/个人主页、考勤记录页、个人信息页、就业信息页、设置页

技术集成模式:

  • 参照史诗011(用人方小程序)的成功模式和架构
  • 每个UI包内部管理自己的API客户端和RPC类型
  • API调用逻辑封装在页面组件内部
  • mini-talent只需导入页面组件使用,无需关心API实现

需要创建的7个UI包:

  1. @d8d/rencai-dashboard-ui - 首页/个人主页UI包
  2. @d8d/rencai-auth-ui - 登录认证UI包
  3. @d8d/rencai-personal-info-ui - 个人信息UI包
  4. @d8d/rencai-attendance-ui - 考勤记录UI包
  5. @d8d/rencai-employment-ui - 就业信息UI包
  6. @d8d/rencai-settings-ui - 设置页UI包
  7. @d8d/rencai-shared-ui - 共享UI组件包

验收标准

UI包基础结构

  • rencai系列7个UI包基础目录结构创建完成
  • 每个UI包包含必需的子目录: src/api/, src/pages/, src/components/, src/types/, src/utils/, tests/

API客户端集成

  • 每个UI包包含自己的API客户端文件 (src/api/index.ts)
  • API客户端基于史诗015提供的RPC路由定义
  • 使用Hono RPC的hc客户端实现类型安全的API调用
  • API客户端封装在页面组件内部,mini-talent无需关心实现细节

package.json配置

  • 每个UI包的package.json配置了完整的exports字段
  • exports字段包含页面组件的导出路径(如"./pages/LoginPage/LoginPage")
  • 参照yongren-dashboard-ui的package.json格式
  • 正确配置workspace依赖关系
  • 每个UI包包含dev脚本: "dev": "tsc --watch" 用于TypeScript编译监视

项目集成

  • mini-talent项目的路由结构配置完成,支持页面导航
  • 页面组件使用exports配置的完整路径导入: import LoginPage from '@d8d/rencai-auth-ui/pages/LoginPage/LoginPage'
  • 基础布局组件(状态栏、底部导航、页面容器)可用并符合移动端设计
  • 人才用户认证框架就绪,支持后续登录页面集成
  • 根目录package.json配置了rencai系列UI包的开发脚本
  • dev:mini-ui-packages脚本包含所有rencai UI包的并行编译监视
  • pnpm run dev命令能够正常启动所有服务,包括rencai UI包的编译监视

兼容性验证

  • 现有mini-talent项目功能不受影响
  • rencai系列UI包遵循yongren系列UI包的API客户端模式
  • 保持路由结构的统一性,新增路由不影响现有功能
  • rencai系列UI包遵循现有的mini-ui-packages包结构规范

测试验证

  • 编写基础测试验证UI包结构正确性
  • 测试验证现有功能保持完整
  • 类型检查通过 (pnpm typecheck)

任务列表

任务1: 分析史诗015已完成的API模块 (AC: UI包基础结构, API客户端集成)

  • 1.1 查阅史诗015的PRD文档,确认已完成的API列表
  • 1.2 确认每个UI包需要集成的RPC客户端和路由
  • 1.3 分析API路径约定 (api/v1/rencai 前缀)
  • 1.4 确认史诗015已实现的API:
    • 人才用户认证API (登录)
    • 个人信息查询API (基本信息、银行卡、证件照片)

任务2: 创建rencai系列UI包基础结构 (AC: UI包基础结构)

  • 2.1 在mini-ui-packages下创建7个UI包目录:
    • rencai-dashboard-ui/
    • rencai-auth-ui/
    • rencai-personal-info-ui/
    • rencai-attendance-ui/
    • rencai-employment-ui/
    • rencai-settings-ui/
    • rencai-shared-ui/
  • 2.2 为每个UI包创建标准子目录结构:
    • src/api/ - API客户端
    • src/pages/ - 页面组件
    • src/components/ - UI组件
    • src/types/ - TypeScript类型定义
    • src/utils/ - 工具函数
    • src/index.ts - 包主入口 (保持为空,仅包含注释)
    • tests/ - 测试文件
  • [ ] 2.3 创建src/index.ts文件,内容为:

    // 采用细粒度路径导出方式
    // 不再导出任何内容,所有工具和组件通过具体路径导入
    

任务3: 配置每个UI包的package.json、Jest配置和开发脚本 (AC: package.json配置)

  • 3.1 参照yongren-dashboard-ui/package.json创建每个UI包的package.json
  • 3.2 配置包名称为@d8d/rencai-<name>-ui
  • 3.3 配置exports字段,支持以下导出路径:
    • "." - 主入口
    • "./api" - API客户端
    • "./pages/<PageName>/<PageName>" - 页面组件导出路径
  • 3.4 配置workspace依赖:
    • @d8d/mini-shared-ui-components
    • @d8d/rencai-shared-ui (共享UI组件)
    • 对应的后端模块包 (如@d8d/allin-company-module)
  • 3.5 配置Taro相关依赖:
    • @tarojs/components: "4.1.4"
    • @tarojs/plugin-platform-weapp: "4.1.4"
    • @tarojs/react: "4.1.4"
    • @tarojs/taro: "4.1.4"
  • [ ] 3.6 配置scripts脚本 (必须包含以下脚本):

    "scripts": {
    "build": "tsc",
    "dev": "tsc --watch",
    "typecheck": "tsc --noEmit",
    "test": "jest",
    "test:watch": "jest --watch",
    "test:coverage": "jest --coverage"
    }
    

    重要: dev脚本使用tsc --watch,用于开发时监视TypeScript文件变化并自动编译

  • [ ] 3.7 配置测试相关依赖:

    • devDependencies中添加: "@d8d/mini-testing-utils": "workspace:*"
    • 其他测试依赖: jest, ts-jest, @testing-library/react, 等
  • [ ] 3.8 创建jest.config.cjs配置文件,参照yongren-dashboard-ui/jest.config.cjs:

    module.exports = {
    preset: 'ts-jest',
    testEnvironment: 'jsdom',
    setupFilesAfterEnv: ['@d8d/mini-testing-utils/setup'],
    moduleNameMapper: {
      '^@/(.*)$': '<rootDir>/src/$1',
      '^~/(.*)$': '<rootDir>/tests/$1',
      '^@tarojs/taro$': '@d8d/mini-testing-utils/testing/taro-api-mock.ts',
      '\\.(css|less|scss|sass)$': '@d8d/mini-testing-utils/testing/style-mock.js',
      '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
        '@d8d/mini-testing-utils/testing/file-mock.js'
    },
    testMatch: [
      '<rootDir>/tests/**/*.spec.{ts,tsx}',
      '<rootDir>/tests/**/*.test.{ts,tsx}'
    ],
    // ... 其他配置
    }
    

任务4: 创建API客户端 (AC: API客户端集成)

  • 4.1 为每个UI包创建src/api/<rencai>Client.ts
  • [ ] 4.2 使用简单的RPC客户端导出模式,参照yongren-statistics-ui/src/api/enterpriseStatisticsClient.ts:

    // src/api/<rencai>Client.ts
    import type { <rencaiRoutes> } from '@d8d/<rencai>-module'
    import { rpcClient } from '@d8d/mini-shared-ui-components/utils/rpc/rpc-client'
    
    // 人才小程序API路径前缀: /api/v1/rencai
    export const <rencai>Client = rpcClient<typeof <rencaiRoutes>>('/api/v1/rencai')
    
  • [ ] 4.3 创建src/api/index.ts导出API客户端

  • [ ] 4.4 集成史诗015提供的RPC路由定义

  • [ ] 4.5 确保API路径使用/api/v1/rencai前缀

任务5: 创建基础布局组件 (AC: 项目集成, 基础布局组件)

  • 5.1 在@d8d/rencai-shared-ui中创建基础布局组件:
    • StatusBar - 状态栏组件
    • TabBarLayout - 底部导航布局组件 (参照yongren-shared-ui/src/components/YongrenTabBarLayout.tsx)
    • PageContainer - 页面容器组件
    • Navbar - 导航栏组件 (支持带/不带返回按钮)
  • 5.2 TabBarLayout组件应包含:
    • TabBarItems配置: 首页、考勤、我的、更多 (4个标签)
    • 图标使用heroicons图标库
    • 导航路由映射到rencai页面路径
    • 使用@d8d/mini-shared-ui-components/components/tab-bar作为基础
  • 5.3 参照原型设计docs/小程序原型/rencai.html的UI样式
  • 5.4 使用Tailwind CSS实现移动端友好的设计
  • 5.5 确保组件符合小程序的尺寸规范 (375px宽度参考)

任务6: 建立人才用户认证框架 (AC: 人才用户认证框架)

  • 6.1 在@d8d/rencai-auth-ui中创建认证基础框架
  • 6.2 集成史诗015提供的人才用户认证API
  • 6.3 创建认证上下文 (AuthContext) 管理登录状态
  • 6.4 实现token存储和验证逻辑
  • 6.5 创建登录页面基础结构 (页面组件占位)
  • 6.6 支持身份证号/残疾证号密码登录模式

任务7: 配置mini-talent项目的路由结构 (AC: 项目集成)

  • [ ] 7.1 删除旧的yongren页面: 删除mini-talent/src/pages/yongren/目录及其所有子目录

    rm -rf mini-talent/src/pages/yongren
    
  • [ ] 7.2 更新app.config.ts配置:

    • 删除所有yongren相关的页面路由
    • 删除yongren相关的TabBar配置
    • 更新窗口标题为"人才小程序"
    • 添加rencai系列页面路由和TabBar配置
  • [ ] 7.3 创建rencai系列页面目录结构:

    mkdir -p mini-talent/src/pages/login
    mkdir -p mini-talent/src/pages/index
    mkdir -p mini-talent/src/pages/attendance
    mkdir -p mini-talent/src/pages/personal-info
    mkdir -p mini-talent/src/pages/employment
    mkdir -p mini-talent/src/pages/settings
    
  • [ ] 7.4 配置底部TabBar导航 (首页、考勤、我的、更多)

  • [ ] 7.5 使用TabBarLayout组件包装TabBar页面

  • [ ] 7.6 确保路由配置与原型设计一致

任务8: 编写基础测试 (AC: 测试验证)

  • 8.1 为每个UI包编写基础测试,验证包结构正确性
  • 8.2 测试API客户端的导入和导出
  • 8.3 测试页面组件的导入路径
  • 8.4 验证mini-talent项目现有功能不受影响
  • 8.5 运行pnpm typecheck确保类型检查通过

任务9: 配置开发服务器并行启动 (AC: 项目集成)

  • [ ] 9.1 在根目录package.jsonscripts中添加rencai系列UI包的开发脚本:

    "dev:rencai-dashboard-ui": "pnpm --filter \"@d8d/rencai-dashboard-ui\" run dev",
    "dev:rencai-auth-ui": "pnpm --filter \"@d8d/rencai-auth-ui\" run dev",
    "dev:rencai-personal-info-ui": "pnpm --filter \"@d8d/rencai-personal-info-ui\" run dev",
    "dev:rencai-attendance-ui": "pnpm --filter \"@d8d/rencai-attendance-ui\" run dev",
    "dev:rencai-employment-ui": "pnpm --filter \"@d8d/rencai-employment-ui\" run dev",
    "dev:rencai-settings-ui": "pnpm --filter \"@d8d/rencai-settings-ui\" run dev",
    "dev:rencai-shared-ui": "pnpm --filter \"@d8d/rencai-shared-ui\" run dev"
    
  • [ ] 9.2 更新dev:mini-ui-packages脚本,将rencai系列UI包添加到concurrently命令中:

    "dev:mini-ui-packages": "concurrently \
    \"pnpm run dev:dev:allin-enums\" \
    \"pnpm run dev:mini-enterprise-auth-ui\" \
    \"pnpm run dev:mini-shared-ui-components\" \
    \"pnpm run dev:yongren-shared-ui\" \
    \"pnpm run dev:yongren-dashboard-ui\" \
    \"pnpm run dev:yongren-order-management-ui\" \
    \"pnpm run dev:yongren-settings-ui\" \
    \"pnpm run dev:yongren-statistics-ui\" \
    \"pnpm run dev:yongren-talent-management-ui\" \
    \"pnpm run dev:mini-charts\" \
    \"pnpm run dev:rencai-shared-ui\" \
    \"pnpm run dev:rencai-dashboard-ui\" \
    \"pnpm run dev:rencai-auth-ui\" \
    \"pnpm run dev:rencai-personal-info-ui\" \
    \"pnpm run dev:rencai-attendance-ui\" \
    \"pnpm run dev:rencai-employment-ui\" \
    \"pnpm run dev:rencai-settings-ui\""
    
  • [ ] 9.3 验证pnpm run dev命令能够正常启动所有服务,包括rencai系列UI包的编译监视

  • [ ] 9.4 确认rencai系列UI包的TypeScript编译输出正确,无编译错误

开发者笔记

前置故事见解

史诗016完成状态:

  • ✅ mini-charts图表组件包已完成 (故事016.001-016.013)
  • ✅ 提供了可复用的UI组件开发经验

史诗015完成状态 (2025-12-25):

  • ✅ 人才用户认证API已完成 (故事015-02)
  • ✅ 个人信息查询API已完成 (故事015-03)
  • ⚠️ 就业信息API进行中 (故事015-05)
  • ⚠️ 帮助与支持API进行中 (故事015-06)
  • ⚠️ 通知与消息API进行中 (故事015-07)
  • 🚀 启动建议: 史诗017可以立即开始,与史诗015并行开发

技术栈要求

来源: architecture/tech-stack.md

运行时和框架:

  • Node.js: 20.18.3
  • Hono: 4.8.5 (RPC客户端)
  • 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小程序测试工具,提供统一的mock配置)

包管理:

  • pnpm: workspace管理

UI包开发规范

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

关键规范要求:

1. 包结构规范

mini-ui-packages/<package-name>/
├── package.json              # 包配置 (必须包含exports字段)
├── tsconfig.json             # TypeScript配置
├── jest.config.cjs           # Jest测试配置
├── src/
│   ├── index.ts              # 主入口文件 (保持为空,采用细粒度导出)
│   ├── api/                  # API客户端
│   │   └── index.ts          # API导出
│   ├── pages/                # 页面组件
│   │   └── <PageName>/
│   │       ├── <PageName>.tsx
│   │       └── index.ts
│   ├── components/           # UI组件
│   ├── types/                # TypeScript类型定义
│   └── utils/                # 工具函数
└── tests/                    # 测试文件

src/index.ts规范 (参照yongren-statistics-ui/src/index.ts):

// 采用细粒度路径导出方式
// 不再导出任何内容,所有工具和组件通过具体路径导入

重要: 主入口文件src/index.ts保持为空(仅包含注释),所有导出通过package.json的exports字段配置的具体路径进行。

2. UI包内部导入规范

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

正确示例 (参照yongren-dashboard-ui/src/pages/Dashboard/Dashboard.tsx):

// ✅ 正确: 使用相对路径导入同一包内的模块
import { enterpriseCompanyClient } from '../../api'
import { SomeComponent } from '../components/SomeComponent'
import { utilFunction } from '../../utils/helper'

错误示例:

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

说明:

  • UI包内部导入(同一包内的文件)必须使用相对路径
  • @/~/别名仅在Jest配置中用于测试路径映射,不在源代码中使用
  • 只有跨包导入才使用workspace包名(如@d8d/mini-shared-ui-components)

3. package.json exports配置规范

{
  "exports": {
    ".": {
      "types": "./dist/src/index.d.ts",
      "import": "./dist/src/index.js",
      "require": "./dist/src/index.js"
    },
    "./api": {
      "types": "./src/api/index.ts",
      "import": "./src/api/index.ts",
      "require": "./src/api/index.ts"
    },
    "./pages/<PageName>/<PageName>": {
      "types": "./dist/src/pages/<PageName>/<PageName>.d.ts",
      "import": "./dist/src/pages/<PageName>/<PageName>.js",
      "require": "./dist/src/pages/<PageName>/<PageName>.js"
    }
  }
}

重要: 页面组件的导出路径必须与实际文件路径匹配,便于mini-talent导入:

// mini-talent中的导入方式
import LoginPage from '@d8d/rencai-auth-ui/pages/LoginPage/LoginPage'

4. Jest配置规范

每个UI包必须创建jest.config.cjs配置文件,参照yongren-dashboard-ui/jest.config.cjs:

module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'jsdom',
  setupFilesAfterEnv: ['@d8d/mini-testing-utils/setup'],
  moduleNameMapper: {
    '^@/(.*)$': '<rootDir>/src/$1',
    '^~/(.*)$': '<rootDir>/tests/$1',
    '^@tarojs/taro$': '@d8d/mini-testing-utils/testing/taro-api-mock.ts',
    '\\.(css|less|scss|sass)$': '@d8d/mini-testing-utils/testing/style-mock.js',
    '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
      '@d8d/mini-testing-utils/testing/file-mock.js'
  },
  testMatch: [
    '<rootDir>/tests/**/*.spec.{ts,tsx}',
    '<rootDir>/tests/**/*.test.{ts,tsx}'
  ],
  collectCoverageFrom: [
    'src/**/*.{ts,tsx}',
    '!src/**/*.d.ts',
    '!src/**/index.{ts,tsx}',
    '!src/**/*.stories.{ts,tsx}'
  ],
  coverageDirectory: 'coverage',
  coverageReporters: ['text', 'lcov', 'html'],
  testPathIgnorePatterns: [
    '/node_modules/',
    '/dist/',
    '/coverage/'
  ],
  transform: {
    '^.+\\.(ts|tsx)$': 'ts-jest',
    '^.+\\.(js|jsx)$': 'babel-jest'
  },
  transformIgnorePatterns: [
    '/node_modules/(?!(swiper|@tarojs)/)'
  ],
  moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json']
}

关键配置说明:

  • setupFilesAfterEnv: 使用@d8d/mini-testing-utils/setup进行测试环境初始化
  • moduleNameMapper:
    • ^@/(.*)$^~/(.*)$: 仅用于测试文件的路径映射,不在源代码中使用
    • ^@tarojs/taro$: 映射Taro API到mock
    • 样式和文件映射: 将样式文件和静态文件映射到mock
  • 重要: 源代码中不使用@/~/别名,只使用相对路径
  • testMatch: 支持.spec.{ts,tsx}.test.{ts,tsx}两种测试文件格式

5. RPC客户端实现规范

每个UI包使用简单的RPC客户端导出模式 (参照yongren-statistics-ui/src/api/enterpriseStatisticsClient.ts):

// src/api/<rencai>Client.ts
import type { <rencaiRoutes> } from '@d8d/<rencai>-module'
import { rpcClient } from '@d8d/mini-shared-ui-components/utils/rpc/rpc-client'

// 人才小程序API路径前缀: /api/v1/rencai
export const <rencai>Client = rpcClient<typeof <rencaiRoutes>>('/api/v1/rencai')

src/api/index.ts导出:

export { <rencai>Client } from './<rencai>Client'

6. 类型定义规范

必须使用RPC推断类型,避免直接导入schema类型:

// ✅ 正确:使用RPC推断类型 + 相对路径导入
import type { InferResponseType } from 'hono'
import { <rencai>Client } from '../api/<rencai>Client'

export type <Rencai>InfoResponse = InferResponseType<typeof <rencai>Client.personal.info.$get, 200>

// ❌ 错误:直接导入schema类型 (可能导致Date/string不匹配)
import type { <Rencai> } from '@d8d/<rencai>-module/schemas'

// ❌ 错误:使用别名导入UI包内部模块
import { <rencai>Client } from '@/api/<rencai>Client'

项目结构指南

来源: architecture/source-tree.md

mini-talent项目结构:

mini-talent/                   # 人才小程序项目
├── src/
│   ├── app.tsx                # 小程序入口
│   ├── app.config.ts          # 小程序配置 (需替换为rencai页面路由)
│   ├── app.css                # 全局样式
│   ├── index.html             # HTML模板
│   └── pages/                 # 页面目录
│       ├── login/             # 登录页 (从UI包导入)
│       │   └── index.tsx
│       ├── index/             # 首页/个人主页 (从UI包导入)
│       │   └── index.tsx
│       ├── attendance/        # 考勤记录 (从UI包导入)
│       │   └── index.tsx
│       ├── personal-info/     # 个人信息 (从UI包导入)
│       │   └── index.tsx
│       ├── employment/        # 就业信息 (从UI包导入)
│       │   └── index.tsx
│       └── settings/          # 设置页 (从UI包导入)
│           └── index.tsx
├── config/                    # 配置文件
├── package.json
├── jest.config.js             # Jest配置
└── tsconfig.json

说明:

  • mini-talent项目结构简洁,主要包含页面路由配置
  • API客户端、布局组件(如TabBarLayout)由UI包管理
  • TabBarLayout参考: mini-ui-packages/yongren-shared-ui/src/components/YongrenTabBarLayout.tsx
  • 页面组件从rencai系列UI包导入,作为薄包装层

mini-talent/src/app.config.ts配置 (新):

完全替换现有的yongren配置为rencai配置:

export default defineAppConfig({
  pages: [
    'pages/login/index',           // 登录页
    'pages/index/index',           // 首页/个人主页
    'pages/attendance/index',      // 考勤记录
    'pages/personal-info/index',   // 个人信息
    'pages/employment/index',      // 就业信息
    'pages/settings/index',        // 设置页
  ],
  window: {
    backgroundTextStyle: 'light',
    navigationBarBackgroundColor: '#3b82f6',
    navigationBarTitleText: '人才小程序',
    navigationBarTextStyle: 'white',
    navigationStyle: 'custom'
  },
  tabBar: {
    custom: true,
    color: "#6b7280",
    selectedColor: "#3b82f6",
    backgroundColor: "#ffffff",
    list: [
      {
        pagePath: 'pages/index/index',
        text: '首页'
      },
      {
        pagePath: 'pages/attendance/index',
        text: '考勤'
      },
      {
        pagePath: 'pages/personal-info/index',
        text: '我的'
      },
      {
        pagePath: 'pages/settings/index',
        text: '更多'
      }
    ]
  },
  usingComponents: {}
})

重要变更:

  • ✅ 删除所有yongren相关页面路由
  • ✅ 更新导航栏标题为"人才小程序"
  • ✅ TabBar配置: 首页、考勤、我的、更多 (4个标签)
  • ✅ 页面组件从rencai系列UI包导入

mini-ui-packages目录结构:

mini-ui-packages/
├── yongren-dashboard-ui/      # 参考实现 (用人方仪表板)
├── yongren-auth-ui/           # 参考实现 (用人方认证)
├── yongren-shared-ui/         # 参考实现 (用人方共享组件)
├── mini-shared-ui-components/ # 通用小程序UI组件
├── rencai-dashboard-ui/       # [待创建] 人才仪表板
├── rencai-auth-ui/            # [待创建] 人才认证
├── rencai-personal-info-ui/   # [待创建] 人才个人信息
├── rencai-attendance-ui/      # [待创建] 人才考勤记录
├── rencai-employment-ui/      # [待创建] 人才就业信息
├── rencai-settings-ui/        # [待创建] 人才设置
└── rencai-shared-ui/          # [待创建] 人才共享组件

根目录package.json脚本配置:

开发服务器启动使用concurrently并行运行所有服务的编译监视:

{
  "scripts": {
    "dev": "concurrently \
      \"pnpm run dev:mini\" \
      \"pnpm run dev:mini-talent\" \
      \"pnpm run dev:web\" \
      \"pnpm run dev:weapp\" \
      \"pnpm run dev:weapp-talent\" \
      \"pnpm run dev:mini-ui-packages\" ",

    "dev:mini-ui-packages": "concurrently \
      [... existing yongren packages ...] \
      \"pnpm run dev:rencai-shared-ui\" \
      \"pnpm run dev:rencai-dashboard-ui\" \
      \"pnpm run dev:rencai-auth-ui\" \
      \"pnpm run dev:rencai-personal-info-ui\" \
      \"pnpm run dev:rencai-attendance-ui\" \
      \"pnpm run dev:rencai-employment-ui\" \
      \"pnpm run dev:rencai-settings-ui\"",

    "dev:rencai-dashboard-ui": "pnpm --filter \"@d8d/rencai-dashboard-ui\" run dev",
    "dev:rencai-auth-ui": "pnpm --filter \"@d8d/rencai-auth-ui\" run dev",
    // ... 其他rencai UI包
  }
}

重要: 每个UI包的dev脚本使用tsc --watch,在开发时监视TypeScript文件变化并自动编译到dist/目录。

原型设计参考

来源: docs/小程序原型/rencai.html

原型包含6个完整页面:

  1. 登录页 (原型行115-158)

    • 身份证号/残疾证号输入框
    • 密码输入框
    • 登录按钮
    • 忘记密码链接
    • 注册入口
  2. 首页/个人主页 (原型行160-301)

    • 顶部个人信息卡片 (姓名、残疾类型、出勤统计、本月薪资)
    • 打卡模块 (打卡状态、上班/下班打卡时间、远程打卡按钮)
    • 功能入口网格 (个人信息、考勤记录、薪资查询、企业信息)
    • 最新通知列表
  3. 考勤记录页 (原型行303-481)

    • 月份选择器
    • 考勤统计卡片 (出勤率、正常出勤天数、迟到/早退/缺勤次数)
    • 考勤日历视图 (标记已打卡日期)
    • 打卡明细列表 (按日期倒序)
  4. 个人信息页 (原型行483-628)

    • 顶部个人信息摘要
    • 基本信息列表 (姓名、性别、年龄、身份证号、残疾证号、残疾类型、联系电话、联系地址)
    • 银行卡信息列表 (银行名称、卡号脱敏、卡类型、是否默认)
    • 证件照片网格 (身份证、残疾证、体检报告、征信报告)
  5. 就业信息页 (原型行630-768)

    • 当前就业状态卡片 (企业名称、岗位名称、入职日期、工作状态、订单编号、薪资水平)
    • 薪资记录列表 (按月份查询)
    • 就业历史时间线 (按时间倒序)
  6. 设置页 (原型行770-906)

    • 个人信息摘要 (姓名、残疾类型、出勤统计、本月薪资)
    • 功能入口列表 (修改个人信息、账号与安全、消息通知设置)
    • 帮助与支持入口 (帮助中心、用户协议、隐私政策)
    • 退出登录按钮

移动端设计规范:

  • 宽度参考: 375px
  • 状态栏高度: 44px
  • 底部导航高度: 60px
  • 圆角规范: 12px (卡片)、40px (移动框架)
  • 颜色主题: 蓝色渐变 (#3b82f6 → #1e40af)
  • 字体规范: 标题18-24px, 正文14px, 小字12px

史诗015 API集成要点

来源: docs/prd/epic-015-talent-mini-program-api-support.md

API路径约定: 所有人才小程序API使用 api/v1/rencai 前缀:

  • 人才用户登录: POST /api/v1/rencai/auth/login
  • 人才个人信息: GET /api/v1/rencai/personal/info
  • 银行卡信息查询: GET /api/v1/rencai/personal/bank-cards
  • 证件照片查询: GET /api/v1/rencai/personal/photos
  • 考勤记录查询: GET /api/v1/rencai/attendance/records (P2延期,前端模拟)
  • 就业信息查询: GET /api/v1/rencai/employment/info
  • 薪资记录查询: GET /api/v1/rencai/salary/records
  • 就业历史查询: GET /api/v1/rencai/employment/history

已完成的API (可直接集成):

  • ✅ 人才用户认证API (故事015-02)
  • ✅ 个人信息查询API (故事015-03)

进行中的API (后续集成):

  • ⚠️ 就业信息API (故事015-05)
  • ⚠️ 帮助与支持API (故事015-06)
  • ⚠️ 通知与消息API (故事015-07)

只读设计原则: 遵循与用人方小程序相同的设计原则,人才小程序API以查询功能为主。所有数据修改操作由管理员在管理后台统一处理。人才用户仅有的写入操作包括: 登录认证、通知标记已读。

测试策略

来源: architecture/testing-strategy.md

测试框架选择:

  • mini项目使用Jest (不是Vitest!)
  • 测试命令: pnpm test (在mini目录下运行)
  • 测试配置: jest.config.js

测试文件位置:

mini-ui-packages/<package-name>/
└── tests/
    ├── unit/              # 单元测试
    │   └── *.test.tsx
    └── integration/       # 集成测试
        └── *.test.tsx

测试要求:

  1. 为每个UI包编写基础测试,验证包结构正确性
  2. 测试API客户端的导入和导出
  3. 测试页面组件的导入路径
  4. 验证mini-talent项目现有功能不受影响
  5. 运行pnpm typecheck确保类型检查通过

Mock响应工具函数 (参考):

const createMockResponse = (status: number, data?: any) => ({
  status,
  ok: status >= 200 && status < 300,
  body: null,
  bodyUsed: false,
  statusText: status === 200 ? 'OK' : 'Error',
  headers: new Headers(),
  url: '',
  redirected: false,
  type: 'basic' as ResponseType,
  json: async () => data || {},
  text: async () => '',
  blob: async () => new Blob(),
  arrayBuffer: async () => new ArrayBuffer(0),
  formData: async () => new FormData(),
  clone: function() { return this; }
})

编码标准

来源: architecture/coding-standards.md

关键编码规范:

1. 必须遵循UI包开发规范

开发UI包时,必须参考并遵循UI包开发规范,该规范基于史诗008(AllIn UI模块移植)的经验总结。

2. 关键检查点 (基于史诗008经验)

  • API路径映射验证: 开发前必须验证故事中的API路径映射与实际后端路由定义的一致性
  • 类型推断最佳实践: 必须使用RPC推断类型,而不是直接导入schema类型
  • 测试选择器优化: 必须为关键交互元素添加data-testid属性
  • 表单组件模式: 必须使用条件渲染两个独立的Form组件
  • API调用一致性: 必须根据实际路由名称修正API调用

3. 常见错误避免

  • ❌ 不要直接导入schema类型 (可能导致Date/string类型不匹配)
  • ❌ 不要使用getByText()查找可能重复的文本元素
  • ❌ 不要在单个Form组件上动态切换props
  • ❌ 不要使用故事中描述但实际不存在的路由名称
  • 不要在UI包内部导入中使用别名 (@/, ~/等),必须使用相对路径

路径使用示例:

// ✅ 正确: UI包内部使用相对路径
import { apiClient } from '../../api'
import { MyComponent } from '../components'

// ✅ 正确: 跨包导入使用workspace包名
import { SharedComponent } from '@d8d/mini-shared-ui-components'

// ❌ 错误: UI包内部使用别名
import { apiClient } from '@/api'
import { MyComponent } from '~/pages/Dashboard/components'

4. 参考实现

  • 用人方统计UI包: mini-ui-packages/yongren-statistics-ui

    • API客户端: src/api/enterpriseStatisticsClient.ts (简单RPC客户端导出模式)
    • 主入口文件: src/index.ts (保持为空,采用细粒度导出)
    • 参照此文件实现rencai UI包的API客户端和导出方式
  • 用人方仪表板UI包: mini-ui-packages/yongren-dashboard-ui

    • 组件: src/pages/Dashboard/Dashboard.tsx
    • package.json exports配置
    • 目录结构参考
    • Jest配置: jest.config.cjs

数据模型参考

来源: architecture/data-model-schema-changes.md

相关数据表 (基于allin数据库):

  • users2 - 用户表 (已扩展支持talent用户类型)
  • disabled_person - 残疾人信息表
  • disabled_bank_card - 银行卡信息表
  • disabled_person_photo - 证件照片表
  • employment_order - 就业订单表
  • order_person - 订单人员关联表

数据库schema扩展 (故事015-01已完成):

  • users2表新增talent用户类型
  • users2表新增person_id字段 (外键引用disabled_person.person_id)

技术约束

  1. 向后兼容: 不影响现有mini-talent项目功能
  2. 类型安全: 使用TypeScript严格模式,所有API调用必须有类型定义
  3. 模块独立性: 每个UI包独立管理自己的API客户端和类型定义
  4. 测试覆盖: 所有新增代码必须有测试覆盖
  5. 代码规范: 遵循项目编码标准和UI包开发规范

风险和缓解措施

主要风险:

  1. API集成风险: 史诗015的API可能尚未全部完成,需要并行开发
  2. UI组件复用风险: rencai系列UI包可能与现有yongren系列UI包存在差异
  3. 兼容性风险: 不同小程序平台可能存在兼容性问题

缓解措施:

  1. 分阶段集成: 先集成已完成的API (人才用户认证、个人信息查询)
  2. UI组件规范统一: 参照yongren系列UI包的结构和命名规范
  3. 类型安全: 使用RPC推断类型,避免类型不匹配问题
  4. 测试驱动: 编写完整的测试,确保功能正确性

变更日志

日期 版本 描述 作者
2025-12-25 1.0 创建故事文档 Bob (Scrum Master)

开发者记录

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

使用的代理模型

Claude Sonnet 4 (claude-sonnet-4-20250514)

调试日志引用

完成说明列表

  1. API客户端导入修正: 初始实现时错误地从@d8d/server导入路由类型,已修正为从相应的后端模块包导入:

    • rencaiAuthRoutes@d8d/core-module/auth-module
    • talentPersonalInfoRoutes@d8d/allin-disability-module
    • talentEmploymentRoutes@d8d/allin-order-module
  2. mini-talent页面简化: 页面文件采用"薄包装层"设计,仅从UI包导入并导出组件,不做额外包装

  3. 复用现有共享组件: StatusBar、PageContainer、Navbar等通用组件使用@d8d/mini-shared-ui-components中的实现,避免重复创建

  4. 简化导出结构: 页面组件不需要额外的index.ts文件,直接通过package.json的exports字段导出

  5. 待实现功能: 以下功能已创建基础框架,待后续故事实现:

    • 各UI包的具体页面组件实现
    • API客户端集成真实API调用(当前为占位实现)
    • 完整的测试覆盖

文件列表

新增/修改的UI包配置文件 (21个):

  • mini-ui-packages/rencai-dashboard-ui/package.json
  • mini-ui-packages/rencai-dashboard-ui/jest.config.cjs
  • mini-ui-packages/rencai-dashboard-ui/tsconfig.json
  • mini-ui-packages/rencai-dashboard-ui/src/index.ts
  • mini-ui-packages/rencai-auth-ui/package.json
  • mini-ui-packages/rencai-auth-ui/jest.config.cjs
  • mini-ui-packages/rencai-auth-ui/tsconfig.json
  • mini-ui-packages/rencai-auth-ui/src/index.ts
  • mini-ui-packages/rencai-personal-info-ui/package.json
  • mini-ui-packages/rencai-personal-info-ui/jest.config.cjs
  • mini-ui-packages/rencai-personal-info-ui/tsconfig.json
  • mini-ui-packages/rencai-personal-info-ui/src/index.ts
  • mini-ui-packages/rencai-attendance-ui/package.json
  • mini-ui-packages/rencai-attendance-ui/jest.config.cjs
  • mini-ui-packages/rencai-attendance-ui/tsconfig.json
  • mini-ui-packages/rencai-attendance-ui/src/index.ts
  • mini-ui-packages/rencai-employment-ui/package.json
  • mini-ui-packages/rencai-employment-ui/jest.config.cjs
  • mini-ui-packages/rencai-employment-ui/tsconfig.json
  • mini-ui-packages/rencai-employment-ui/src/index.ts
  • mini-ui-packages/rencai-settings-ui/package.json
  • mini-ui-packages/rencai-settings-ui/jest.config.cjs
  • mini-ui-packages/rencai-settings-ui/tsconfig.json
  • mini-ui-packages/rencai-settings-ui/src/index.ts
  • mini-ui-packages/rencai-shared-ui/package.json
  • mini-ui-packages/rencai-shared-ui/jest.config.cjs
  • mini-ui-packages/rencai-shared-ui/tsconfig.json
  • mini-ui-packages/rencai-shared-ui/src/index.ts

API客户端文件 (13个):

  • mini-ui-packages/rencai-auth-ui/src/api/talentAuthClient.ts
  • mini-ui-packages/rencai-auth-ui/src/api/index.ts
  • mini-ui-packages/rencai-dashboard-ui/src/api/talentDashboardClient.ts
  • mini-ui-packages/rencai-dashboard-ui/src/api/index.ts
  • mini-ui-packages/rencai-personal-info-ui/src/api/talentPersonalInfoClient.ts
  • mini-ui-packages/rencai-personal-info-ui/src/api/index.ts
  • mini-ui-packages/rencai-employment-ui/src/api/talentEmploymentClient.ts
  • mini-ui-packages/rencai-employment-ui/src/api/index.ts
  • mini-ui-packages/rencai-attendance-ui/src/api/talentAttendanceClient.ts
  • mini-ui-packages/rencai-attendance-ui/src/api/index.ts
  • mini-ui-packages/rencai-settings-ui/src/api/talentSettingsClient.ts
  • mini-ui-packages/rencai-settings-ui/src/api/index.ts

基础布局组件 (1个):

  • mini-ui-packages/rencai-shared-ui/src/components/RencaiTabBarLayout.tsx
    • 注: StatusBar、PageContainer、Navbar等通用组件使用@d8d/mini-shared-ui-components中的实现

认证框架 (2个):

  • mini-ui-packages/rencai-auth-ui/src/utils/AuthContext.tsx
  • mini-ui-packages/rencai-auth-ui/src/pages/LoginPage/LoginPage.tsx
    • 注: 不需要index.ts,直接通过package.json的exports导出

mini-talent页面文件 (7个):

  • mini-talent/src/app.config.ts (更新)
  • mini-talent/src/pages/login/index.tsx (更新)
  • mini-talent/src/pages/index/index.tsx (新建)
  • mini-talent/src/pages/attendance/index.tsx (新建)
  • mini-talent/src/pages/personal-info/index.tsx (新建)
  • mini-talent/src/pages/employment/index.tsx (新建)
  • mini-talent/src/pages/settings/index.tsx (新建)

根目录配置 (1个):

  • package.json (更新,添加rencai UI包开发脚本)

总计: 45个文件

故事草稿检查清单结果

执行日期: 2025-12-25 执行者: Bob (Scrum Master)

验证结果

类别 状态 问题
1. 目标与上下文清晰度 PASS -
2. 技术实现指导 PASS -
3. 参考文档有效性 PASS -
4. 自包含性评估 PASS -
5. 测试指导 PASS -

详细检查结果

1. 目标与上下文清晰度 ✅ PASS

  • ✅ 故事目标/目的清晰陈述: 搭建rencai系列mini ui包的基础框架
  • ✅ 与史诗目标的关系明确: 史诗017人才小程序功能实现的基础故事
  • ✅ 在整体系统流程中的位置已解释: 参照史诗011成功模式,建立技术基础
  • ✅ 对前置故事的依赖已识别: 依赖史诗015已完成的API模块
  • ✅ 业务上下文和价值清晰: 为残疾人用户提供完整的人才小程序功能

2. 技术实现指导 ✅ PASS

  • ✅ 关键文件已识别:
    • 7个UI包的目录结构
    • package.json配置文件
    • API客户端文件 (src/api/Client.ts)
    • 页面组件文件结构
  • ✅ 所需技术已明确指定:
    • TypeScript, React, Taro, Hono RPC, Tailwind CSS
    • Jest测试框架 (mini项目使用Jest,不是Vitest)
  • ✅ 关键API和接口已充分描述:
    • API路径约定 (/api/v1/rencai 前缀)
    • RPC客户端实现模式 (简单导出模式,参照yongren-statistics-ui)
    • package.json exports配置规范 (包含完整示例)
  • ✅ 必要的数据模型或结构已引用:
    • 史诗015的API模块
    • 原型设计文档
    • 数据库表结构
  • ✅ 环境变量已列出 (不适用,使用默认配置)
  • ✅ 标准编码模式的例外已注明:
    • mini项目使用Jest而非Vitest
    • 页面组件导出路径的完整格式
    • 类型推断必须使用RPC推断类型
    • RPC客户端使用简单导出模式而非管理器模式
  • 3. 参考文档有效性 ✅ PASS

    4. 自包含性评估 ✅ PASS

    • ✅ 核心信息包含在故事中:
      • 完整的UI包结构规范
      • 详细的package.json配置示例
      • 完整的RPC客户端实现代码
      • 原型设计的详细描述 (包含行号引用)
      • 史诗015 API集成要点总结
    • ✅ 隐含假设已明确:
      • 史诗015的API可能尚未全部完成,需要并行开发
      • 考勤记录API为P2延期功能,当前为前端模拟实现
    • ✅ 领域特定术语已解释:
      • RPC客户端模式
      • API客户端管理器
      • 页面组件导出路径
      • 类型推断最佳实践
    • ✅ 边界情况或错误场景已处理:
      • 风险和缓解措施章节
      • 史诗015 API延期情况的处理策略

    5. 测试指导 ✅ PASS

    • ✅ 测试方法已概述:
      • 单元测试 (Jest)
      • 集成测试
      • 类型检查 (pnpm typecheck)
    • ✅ 关键测试场景已识别:
      • UI包结构正确性验证
      • API客户端导入导出测试
      • 页面组件导入路径测试
      • 现有功能回归测试
    • ✅ 成功标准已定义:
      • 7个UI包基础结构创建完成
      • package.json exports配置正确
      • API客户端集成完成
      • 路由结构配置完成
      • 基础布局组件可用
      • 认证框架就绪
      • 现有功能不受影响
      • 类型检查通过
    • ✅ 特殊测试考虑已注明:
      • mini项目使用Jest而非Vitest
      • Mock响应工具函数示例
      • 测试文件位置规范

    最终评估

    故事准备状态: ✅ READY

    清晰度评分: 9/10

    主要优点:

    1. 上下文完整: 提供了史诗015完成状态、原型设计、技术规范的完整上下文
    2. 技术指导详细: 包含完整的代码示例 (package.json配置、RPC客户端实现、类型推断示例)
    3. 参考文档精确: 所有引用都指向具体的文档章节,并提供了详细的行号引用
    4. 风险缓解充分: 明确识别了API集成风险,并提供了分阶段集成策略
    5. 测试指导清晰: 明确了测试框架选择 (Jest),并提供了具体的测试场景

    建议改进:

    1. 考虑在任务2中明确说明每个UI包具体需要创建的文件清单 (当前已足够详细,非必需)
    2. 可以在任务4中添加史诗015 API路由的具体导入路径示例 (当前已有足够指导,非必需)

    开发者视角:

    • ✅ 可以根据当前故事文档实施
    • ✅ 所有关键技术决策已明确 (测试框架选择、API客户端模式、类型推断方法)
    • ✅ 参考实现已提供 (yongren-dashboard-ui)
    • ✅ 原型设计详细描述提供了完整的UI指导
    • ✅ 可能的疑问: 史诗015的具体API路由导入路径 (可通过查看史诗015文档解决,非阻塞)

    结论: 故事提供了充分的实施上下文,开发者可以基于此文档成功实施UI包基础框架搭建工作。

    QA结果

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