# 注册表单性别选项动态切换 ## 问题描述 在 `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