# 注册表单性别选项动态切换
## 问题描述
在 `src/pages/patient/components/register.form.tsx` 文件中,性别选项(genderOptions)目前硬编码为宠物性别选项:
```typescript
const genderOptions = [
{
value: 'male_pet',
label: (
),
},
{
value: 'female_pet',
label: (
),
},
// ... 其他宠物性别选项
];
```
**问题**:
1. 硬编码为宠物性别选项,无法适应人类患者
2. 没有根据产品类型(DROS/VETDROS)动态切换
3. 代码复用性差
## 需求分析
### 业务需求
系统支持两种产品类型:
- **DROS**: 人类医疗设备
- **VETDROS**: 宠物医疗设备
性别选项需要根据产品类型动态切换:
- **人类患者**: 使用标准性别选项(男/女/其他/未知)
- **宠物患者**: 使用宠物性别选项(公/母/其他)
### 技术需求
1. **动态切换**: 根据 `productName` 自动选择合适的性别选项
2. **国际化支持**: 所有选项都支持多语言
3. **类型安全**: 使用 TypeScript 枚举确保类型安全
4. **向后兼容**: 不影响现有功能
## 解决方案设计
### 1. 创建性别选项配置
**文件**: `src/domain/patient/genderOptions.ts`
```typescript
import { FormattedMessage } from 'react-intl';
/**
* 人类性别枚举
*/
export enum HumanGender {
MALE = 'male',
FEMALE = 'female',
OTHER = 'other',
UNKNOWN = 'unknown',
}
/**
* 宠物性别枚举
*/
export enum PetGender {
MALE_PET = 'male_pet',
FEMALE_PET = 'female_pet',
NEUTERED_MALE = 'neutered_male',
NEUTERED_FEMALE = 'neutered_female',
UNKNOWN_PET = 'unknown_pet',
}
/**
* 性别选项接口
*/
export interface GenderOption {
value: string;
label: React.ReactNode;
}
/**
* 人类性别选项
*/
export const humanGenderOptions: GenderOption[] = [
{
value: HumanGender.MALE,
label: (
),
},
{
value: HumanGender.FEMALE,
label: (
),
},
{
value: HumanGender.OTHER,
label: (
),
},
{
value: HumanGender.UNKNOWN,
label: (
),
},
];
/**
* 宠物性别选项
*/
export const petGenderOptions: GenderOption[] = [
{
value: PetGender.MALE_PET,
label: (
),
},
{
value: PetGender.FEMALE_PET,
label: (
),
},
{
value: PetGender.NEUTERED_MALE,
label: (
),
},
{
value: PetGender.NEUTERED_FEMALE,
label: (
),
},
{
value: PetGender.UNKNOWN_PET,
label: (
),
},
];
/**
* 根据产品类型获取性别选项
* @param productName 产品名称 ('DROS' | 'VETDROS')
* @returns 性别选项数组
*/
export function getGenderOptions(productName: string): GenderOption[] {
switch (productName) {
case 'DROS':
return humanGenderOptions;
case 'VETDROS':
return petGenderOptions;
default:
// 默认使用人类性别选项
console.warn(`Unknown product name: ${productName}, using human gender options`);
return humanGenderOptions;
}
}
```
### 2. 修改注册表单组件
**文件**: `src/pages/patient/components/register.form.tsx`
```typescript
// 导入性别选项配置
import { getGenderOptions } from '@/domain/patient/genderOptions';
// 获取产品类型
const productName = useSelector((state: RootState) => state.product.productName);
// 动态获取性别选项
const genderOptions = useMemo(() => {
return getGenderOptions(productName);
}, [productName]);
// 替换原有的硬编码 genderOptions
// 原代码:
// const genderOptions = [/* 硬编码的宠物性别选项 */];
// 使用动态获取的性别选项
// genderOptions 变量已在上面定义
```
### 3. 更新国际化文件
**文件**: `src/assets/i18n/messages/en.js`
添加人类性别选项的英文翻译:
```javascript
{
// ... 现有翻译
// 人类性别选项
"register.gender.male": "Male",
"register.gender.female": "Female",
"register.gender.other": "Other",
"register.gender.unknown": "Unknown",
// 宠物性别选项(如果需要更新)
"register.gender.male_pet": "Male",
"register.gender.female_pet": "Female",
"register.gender.neutered_male": "Neutered Male",
"register.gender.neutered_female": "Neutered Female",
"register.gender.unknown_pet": "Unknown",
}
```
**文件**: `src/assets/i18n/messages/zh.js`
添加中文翻译:
```javascript
{
// ... 现有翻译
// 人类性别选项
"register.gender.male": "男",
"register.gender.female": "女",
"register.gender.other": "其他",
"register.gender.unknown": "未知",
// 宠物性别选项(如果需要更新)
"register.gender.male_pet": "公",
"register.gender.female_pet": "母",
"register.gender.neutered_male": "已绝育公",
"register.gender.neutered_female": "已绝育母",
"register.gender.unknown_pet": "未知",
}
```
## 实现步骤
### 步骤 1: 创建性别选项配置文件
1. 创建 `src/domain/patient/genderOptions.ts` 文件
2. 定义人类和宠物性别枚举
3. 实现性别选项配置
4. 实现 `getGenderOptions` 函数
### 步骤 2: 修改注册表单组件
1. 在 `register.form.tsx` 中导入 `getGenderOptions`
2. 获取 `productName` 从 Redux store
3. 使用 `useMemo` 动态计算 `genderOptions`
4. 移除原有的硬编码性别选项
### 步骤 3: 更新国际化文件
1. 在英文和中文国际化文件中添加新的性别选项翻译
2. 确保所有性别选项都有对应的翻译
### 步骤 4: 测试验证
1. 测试 DROS 产品显示人类性别选项
2. 测试 VETDROS 产品显示宠物性别选项
3. 测试国际化切换是否正常
4. 测试表单提交和数据保存
## 技术细节
### 1. 产品类型判断逻辑
```typescript
const productName = useSelector((state: RootState) => state.product.productName);
const genderOptions = useMemo(() => {
return getGenderOptions(productName);
}, [productName]);
```
- 使用 Redux selector 获取产品名称
- 使用 `useMemo` 避免不必要的重新计算
- 依赖 `productName` 变化时重新计算性别选项
### 2. 类型安全设计
```typescript
// 使用枚举确保类型安全
export enum HumanGender {
MALE = 'male',
FEMALE = 'female',
OTHER = 'other',
UNKNOWN = 'unknown',
}
// 统一的选项接口
export interface GenderOption {
value: string;
label: React.ReactNode;
}
```
- 枚举值与国际化 key 保持一致
- 接口定义确保所有选项都有统一的结构
### 3. 国际化集成
```typescript
// 使用 FormattedMessage 进行国际化
label: (
),
```
- 支持多语言切换
- 提供默认值防止 key 缺失
## 优势
### 1. 动态适应性
- 根据产品类型自动切换性别选项
- 无需手动配置,减少出错可能
### 2. 代码复用性
- 性别选项配置集中管理
- 可在其他组件中复用
### 3. 国际化支持
- 所有选项都支持多语言
- 统一的翻译管理
### 4. 类型安全
- 使用 TypeScript 枚举
- 编译时检查类型错误
### 5. 向后兼容
- 不影响现有功能
- 默认使用人类性别选项
## 测试场景
### 1. 功能测试
| 测试场景 | 前置条件 | 操作步骤 | 预期结果 |
|---------|---------|---------|---------|
| DROS 产品性别选项 | 产品类型为 DROS | 打开注册表单 | 显示男/女/其他/未知选项 |
| VETDROS 产品性别选项 | 产品类型为 VETDROS | 打开注册表单 | 显示公/母/已绝育公/已绝育母/未知选项 |
| 表单提交 | 选择性别选项 | 提交表单 | 数据正确保存到后端 |
### 2. 国际化测试
| 测试场景 | 前置条件 | 操作步骤 | 预期结果 |
|---------|---------|---------|---------|
| 英文环境 | 切换到英文语言 | 查看性别选项 | 显示 Male/Female/Other/Unknown |
| 中文环境 | 切换到中文语言 | 查看性别选项 | 显示 男/女/其他/未知 |
### 3. 边界情况测试
| 测试场景 | 前置条件 | 操作步骤 | 预期结果 |
|---------|---------|---------|---------|
| 未知产品类型 | productName 为未知值 | 打开注册表单 | 默认显示人类性别选项 |
| 产品类型为空 | productName 为空字符串 | 打开注册表单 | 默认显示人类性别选项 |
## 相关文件
### 修改文件
- `src/pages/patient/components/register.form.tsx` - 主要修改文件
- `src/assets/i18n/messages/en.js` - 添加英文翻译
- `src/assets/i18n/messages/zh.js` - 添加中文翻译
### 新增文件
- `src/domain/patient/genderOptions.ts` - 性别选项配置
### 相关文件
- `src/states/productSlice.ts` - 产品状态管理
- `src/states/patient/register/formSlice.ts` - 表单状态管理
## 总结
通过创建性别选项配置文件,实现根据产品类型动态切换性别选项的功能:
1. **解决了硬编码问题**:从硬编码宠物性别选项改为动态配置
2. **支持多产品类型**:DROS 使用人类性别,VETDROS 使用宠物性别
3. **完善国际化**:所有选项都支持多语言
4. **保证类型安全**:使用 TypeScript 枚举和接口
5. **保持向后兼容**:不影响现有功能
该方案具有良好的扩展性,未来如需添加新的产品类型或性别选项,只需在配置文件中添加即可。
---
**实现日期**: 2025-11-14
**文档版本**: v1.0
**作者**: Cline AI Assistant