# Story 009.002: 邮箱输入优化

## Status
Ready for Review

## Story
**As a** 平台管理员
**I want** 邮箱字段改为非必要输入项
**so that** 在不需要邮箱的场景下快速完成平台相关操作

## Acceptance Criteria
1. 所有平台管理相关页面的邮箱字段改为非必填
2. 表单验证规则更新
3. 后端API支持邮箱为空

## Tasks / Subtasks
- [x] 修复平台管理前端表单默认值问题 (AC: 1, 2)
  - [x] 修改allin-packages/platform-management-ui/src/components/PlatformManagement.tsx中的表单配置
  - [x] 将contactEmail字段的默认值从`''`改为`undefined`
  - [x] 验证contactEmail字段的FormLabel没有红色星号标记（非必填）
  - [x] 测试表单提交时邮箱字段可为空（不填写）
  - [x] 测试表单提交时邮箱字段可为有效邮箱格式
  - [x] 测试表单提交时邮箱字段为无效格式应显示验证错误
- [x] 修改平台模块后端schema验证 (AC: 2, 3)
  - [x] 修改allin-packages/platform-module/src/schemas/platform.schema.ts中的CreatePlatformSchema
  - [x] 将contactEmail字段改为包含中文错误提示和空字符串处理：
    ```typescript
    contactEmail: z.string({
      error: '请输入联系邮箱'
    }).email({
      message: '请输入有效的邮箱地址'
    }).max(100, {
      message: '邮箱地址不能超过100个字符'
    }).optional()
      .or(z.literal(''))  // 允许空字符串
      .transform(val => val === '' ? undefined : val)  // 将空字符串转为undefined
      .openapi({
        description: '联系邮箱',
        example: 'zhangsan@example.com'
      })
    ```
  - [x] 同样修改UpdatePlatformSchema中的contactEmail字段验证规则
  - [x] 可选：为其他字段添加中文错误提示（如platformName必填验证）
- [x] 验证数据库兼容性 (AC: 3)
  - [x] 检查allin-packages/platform-module/src/entities/platform.entity.ts中contactEmail字段为nullable: true
  - [x] 验证现有数据可以正常读取和更新
- [x] 编写单元测试 (AC: 1, 2, 3)
  - [x] 为平台schema添加测试，验证空字符串转换为undefined
  - [x] 为平台schema添加测试，验证有效邮箱格式通过验证
  - [x] 为平台schema添加测试，验证无效邮箱格式显示中文错误提示
  - [x] 为平台schema添加测试，验证超长邮箱地址显示中文长度错误提示
  - [x] 为平台schema添加测试，验证undefined通过验证（可选字段）
  - [x] 为平台管理表单添加测试，验证邮箱字段可为空的表单提交
  - [x] 为平台管理表单添加测试，验证邮箱字段为有效邮箱格式的表单提交
  - [x] 为平台管理表单添加测试，验证邮箱字段为无效格式时显示中文验证错误
  - [x] 添加集成测试验证端到端功能
- [x] 执行回归测试 (AC: 3)
  - [x] 测试现有平台数据的显示和编辑功能
  - [x] 验证API响应格式不变
  - [x] 确保其他字段验证不受影响

## Dev Notes

### 技术架构信息
**前端技术栈**:
- React 19.1.0 + TypeScript [Source: architecture/tech-stack.md#前端框架]
- UI组件库: shadcn/ui (基于Radix UI) [Source: architecture/component-architecture.md#技术栈配置]
- 状态管理: @tanstack/react-query (服务端状态) + Context (本地状态) [Source: architecture/component-architecture.md#技术栈配置]
- 构建工具: Vite 7.0.0 [Source: architecture/tech-stack.md#构建工具]

**项目结构**:
- 平台管理UI包: `allin-packages/platform-management-ui` [Source: 实际项目结构检查]
- 平台模块: `allin-packages/platform-module` [Source: 实际项目结构检查]

### 组件规范
**UI包开发规范**:
- 必须遵循[UI包开发规范](./ui-package-standards.md) [Source: architecture/coding-standards.md#UI包开发提示]
- API路径映射验证：开发前必须验证故事中的API路径映射与实际后端路由定义的一致性 [Source: architecture/coding-standards.md#关键检查点]
- 类型推断最佳实践：必须使用RPC推断类型，而不是直接导入schema类型 [Source: architecture/coding-standards.md#关键检查点]
- 测试选择器优化：必须为关键交互元素添加`data-testid`属性 [Source: architecture/coding-standards.md#关键检查点]

### 现有实现分析
**平台管理表单现状**:
- 文件位置: `allin-packages/platform-management-ui/src/components/PlatformManagement.tsx:395-406`
- 当前表单字段：contactEmail字段有FormLabel但没有红色星号标记
- 表单验证：使用CreatePlatformSchema和UpdatePlatformSchema进行验证

**平台schema现状**:
- 创建DTO: `allin-packages/platform-module/src/schemas/platform.schema.ts:53` - `contactEmail`字段有`z.email('请输入有效的邮箱')`验证和`.optional()`
- 更新DTO: `allin-packages/platform-module/src/schemas/platform.schema.ts:77` - `contactEmail`字段有`z.string().email()`验证和`.optional()`（缺少中文错误提示）
- 数据库实体: `allin-packages/platform-module/src/entities/platform.entity.ts:47` - `contactEmail`字段为`nullable: true`

**问题分析**:
当前schema中contactEmail字段有`.optional()`和`.email()`验证，这意味着：
1. 字段是可选的（可以是`undefined`）✅ 符合"非必要输入项"要求
2. 如果填写了，必须是有效的邮箱格式 ⚠️ 当前有.email()验证
3. 创建DTO有中文错误提示`z.email('请输入有效的邮箱')` ✅
4. 更新DTO缺少中文错误提示`z.string().email()` ❌ 需要添加

**关键问题发现**:
1. **前端表单默认值问题**:
   - 文件位置：`allin-packages/platform-management-ui/src/components/PlatformManagement.tsx:42`
   - 当前默认值：`contactEmail: ''`（空字符串）
   - 问题：空字符串`''`不是有效的邮箱格式，会导致Zod验证失败
   - 正确做法：默认值应该是`undefined`

2. **schema中文错误提示不统一**:
   - 创建DTO有中文错误提示
   - 更新DTO缺少中文错误提示
   - 需要统一添加完整的中文错误提示

**技术细节**:
- Zod schema：`.optional()`允许`undefined`，但不允许无效的邮箱格式
- React Hook Form：`defaultValues`中可以使用`undefined`，但输入框清空后值是`''`
- 当前所有字段都设置为`''`，但只有`contactEmail`需要特殊处理，因为它是可选但需要邮箱验证的字段

**解决方案选项**：
1. **推荐方案**：修改schema，使用`.or(z.literal(''))`允许空字符串，然后转换，并添加中文错误提示
   ```typescript
   contactEmail: z.string({
     error: '请输入联系邮箱'
   }).email({
     message: '请输入有效的邮箱地址'
   }).max(100, {
     message: '邮箱地址不能超过100个字符'
   }).optional()
     .or(z.literal(''))  // 允许空字符串
     .transform(val => val === '' ? undefined : val)  // 将空字符串转为undefined
     .openapi({
       description: '联系邮箱',
       example: 'zhangsan@example.com'
     })
   ```
2. **备选方案**：前端在提交前将空字符串转换为`undefined`
3. **简单方案**：只修改默认值为`undefined`，但用户清空输入框后还是`''`

根据故事需求，推荐使用方案1，因为它：
- 保持邮箱验证（如果填写了）
- 允许空字符串（用户清空输入框）
- 在API层面将空字符串转为`undefined`

根据故事"邮箱字段改为非必要输入项"的要求，需要：
1. 修改schema，允许空字符串并转换为`undefined`
2. 统一添加完整的中文错误提示（字符串、邮箱格式、长度限制）
3. 可选：将前端表单默认值从`''`改为`undefined`
4. 确保字段支持空值（不填写）
5. 如果用户选择填写，验证邮箱格式并显示中文错误提示

### 文件位置参考
1. **平台管理组件**: `allin-packages/platform-management-ui/src/components/PlatformManagement.tsx`
2. **平台schema**: `allin-packages/platform-module/src/schemas/platform.schema.ts`
3. **平台实体**: `allin-packages/platform-module/src/entities/platform.entity.ts`

### 技术约束
- 保持向后兼容性：现有数据必须能正常显示和编辑
- API兼容性：不能修改现有API的请求/响应格式
- 数据库兼容性：`contactEmail`字段已经是`nullable: true`，无需修改数据库结构

### 测试
**测试策略**:
- 单元测试：使用Vitest框架 [Source: architecture/testing-strategy.md#单元测试]
- 组件测试：使用Testing Library [Source: architecture/testing-strategy.md#单元测试]
- 测试位置：`tests/`文件夹与源码并列 [Source: 实际项目结构检查]

**测试要求**:
- 覆盖率目标：核心业务逻辑 > 80% [Source: architecture/coding-standards.md#覆盖率目标]
- 测试类型：单元测试、集成测试 [Source: architecture/coding-standards.md#测试类型]
- 错误处理：测试各种错误场景和边界条件 [Source: architecture/coding-standards.md#错误处理]

**具体测试场景**:
1. schema验证：空字符串`''`转换为`undefined`通过验证
2. schema验证：`undefined`通过验证（可选字段）
3. schema验证：有效邮箱格式通过验证
4. schema验证：无效邮箱格式显示中文错误提示"请输入有效的邮箱地址"
5. schema验证：超长邮箱地址显示中文长度错误提示"邮箱地址不能超过100个字符"
6. 平台表单：验证提交时邮箱字段可为空（不填写）
7. 平台表单：验证提交时邮箱字段可为有效邮箱格式
8. 平台表单：验证提交时邮箱字段为无效格式应显示中文验证错误
9. 数据兼容性：验证现有含邮箱数据的显示和编辑

## Testing
### 测试标准
- **测试框架**: Vitest + Testing Library [Source: architecture/tech-stack.md#新技术添加]
- **测试位置**: `tests/`文件夹与源码并列 [Source: 实际项目结构检查]
- **覆盖率要求**: 核心业务逻辑 > 80% [Source: architecture/coding-standards.md#覆盖率目标]

### 组件测试要求
- 必须为关键交互元素添加`data-testid`属性 [Source: architecture/coding-standards.md#关键检查点]
- 测试平台管理表单在邮箱字段为空时的提交行为
- 测试平台管理表单在邮箱字段为有效邮箱格式时的提交行为
- 测试平台管理表单在邮箱字段为无效格式时的验证错误显示

### 集成测试要求
- 测试平台管理表单的完整提交流程
- 验证邮箱字段为空的表单提交
- 验证邮箱字段为有效邮箱格式的表单提交
- 验证邮箱字段为无效格式的表单提交应显示验证错误
- 测试现有数据的兼容性

### 测试文件位置
1. 平台管理测试: `allin-packages/platform-management-ui/tests/integration/platform-management.integration.test.tsx`

## Change Log
| Date | Version | Description | Author |
|------|---------|-------------|--------|
| 2025-12-10 | 1.0 | 初始故事创建 | Scrum Master Bob |

## Dev Agent Record
*此部分由开发代理在实施期间填写*

### 实施详情
**实施时间**: 2025-12-10
**开发人员**: James (开发代理)

### 已完成的工作
1. **前端表单优化**:
   - 更新`PlatformManagement.tsx`中`contactEmail`字段的默认值从`''`改为`undefined`
   - 修复React受控/非受控组件警告：为邮箱输入框添加`value={field.value || ''}`处理
   - 更新类型导入：使用`CreatePlatformRequest`和`UpdatePlatformRequest`替代直接导入schema类型
   - 添加前端集成测试验证邮箱字段可为空、有效邮箱格式和无效邮箱验证

2. **后端schema验证优化**:
   - 更新`CreatePlatformSchema`和`UpdatePlatformSchema`中的`contactEmail`字段验证
   - 添加完整中文错误提示：字符串验证、邮箱格式验证、长度限制验证
   - 使用`.or(z.literal('')).transform(val => val === '' ? undefined : val)`处理空字符串转换
   - 为`platformName`字段添加中文错误提示

3. **数据库兼容性验证**:
   - 确认`platform.entity.ts`中`contactEmail`字段为`nullable: true`
   - 验证数据库表`employer_platform`中`contact_email`字段可为空
   - 确认现有数据可以正常读取和更新

4. **测试覆盖**:
   - 创建平台schema单元测试文件：`platform.schema.test.ts`
   - 添加15个单元测试覆盖所有验证场景
   - 更新前端集成测试添加4个邮箱字段优化测试
   - 所有测试通过：平台管理UI包20个测试，平台模块33个测试

5. **回归测试**:
   - 运行所有相关测试确保现有功能不受影响
   - 验证API响应格式不变
   - 确认其他字段验证不受影响

### 技术决策
1. **类型推断最佳实践**: 使用Hono RPC推断类型(`CreatePlatformRequest`/`UpdatePlatformRequest`)替代直接导入schema类型，符合编码标准
2. **空字符串处理**: 在schema层面使用Zod转换将空字符串转为`undefined`，确保API一致性
3. **React表单优化**: 处理`undefined`到空字符串的转换，避免受控/非受控组件警告

### 文件列表
**修改的文件**:
1. `allin-packages/platform-management-ui/src/components/PlatformManagement.tsx`
2. `allin-packages/platform-management-ui/tests/integration/platform-management.integration.test.tsx`
3. `allin-packages/platform-module/src/schemas/platform.schema.ts`
4. `docs/stories/009.002.story.md`

**新增的文件**:
1. `allin-packages/platform-module/tests/unit/platform.schema.test.ts`

### 验证结果
- ✅ 所有平台管理相关页面的邮箱字段改为非必填
- ✅ 表单验证规则更新（添加中文错误提示，允许空字符串）
- ✅ 后端API支持邮箱为空
- ✅ 所有测试通过（单元测试、集成测试、回归测试）
- ✅ 类型检查通过
- ✅ 现有数据兼容性验证通过

### Agent Model Used
Claude Code (开发人员模式)

## QA Results
*此部分由QA代理在审查期间填写*