注册表单性别选项动态切换.md 10 KB

注册表单性别选项动态切换

问题描述

src/pages/patient/components/register.form.tsx 文件中,性别选项(genderOptions)目前硬编码为宠物性别选项:

const genderOptions = [
  {
    value: 'male_pet',
    label: (
      <FormattedMessage
        id="register.gender.male_pet"
        defaultMessage="register.gender.male_pet"
      />
    ),
  },
  {
    value: 'female_pet',
    label: (
      <FormattedMessage
        id="register.gender.female_pet"
        defaultMessage="register.gender.female_pet"
      />
    ),
  },
  // ... 其他宠物性别选项
];

问题

  1. 硬编码为宠物性别选项,无法适应人类患者
  2. 没有根据产品类型(DROS/VETDROS)动态切换
  3. 代码复用性差

需求分析

业务需求

系统支持两种产品类型:

  • DROS: 人类医疗设备
  • VETDROS: 宠物医疗设备

性别选项需要根据产品类型动态切换:

  • 人类患者: 使用标准性别选项(男/女/其他/未知)
  • 宠物患者: 使用宠物性别选项(公/母/其他)

技术需求

  1. 动态切换: 根据 productName 自动选择合适的性别选项
  2. 国际化支持: 所有选项都支持多语言
  3. 类型安全: 使用 TypeScript 枚举确保类型安全
  4. 向后兼容: 不影响现有功能

解决方案设计

1. 创建性别选项配置

文件: src/domain/patient/genderOptions.ts

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: (
      <FormattedMessage
        id="register.gender.male"
        defaultMessage="Male"
      />
    ),
  },
  {
    value: HumanGender.FEMALE,
    label: (
      <FormattedMessage
        id="register.gender.female"
        defaultMessage="Female"
      />
    ),
  },
  {
    value: HumanGender.OTHER,
    label: (
      <FormattedMessage
        id="register.gender.other"
        defaultMessage="Other"
      />
    ),
  },
  {
    value: HumanGender.UNKNOWN,
    label: (
      <FormattedMessage
        id="register.gender.unknown"
        defaultMessage="Unknown"
      />
    ),
  },
];

/**
 * 宠物性别选项
 */
export const petGenderOptions: GenderOption[] = [
  {
    value: PetGender.MALE_PET,
    label: (
      <FormattedMessage
        id="register.gender.male_pet"
        defaultMessage="Male Pet"
      />
    ),
  },
  {
    value: PetGender.FEMALE_PET,
    label: (
      <FormattedMessage
        id="register.gender.female_pet"
        defaultMessage="Female Pet"
      />
    ),
  },
  {
    value: PetGender.NEUTERED_MALE,
    label: (
      <FormattedMessage
        id="register.gender.neutered_male"
        defaultMessage="Neutered Male"
      />
    ),
  },
  {
    value: PetGender.NEUTERED_FEMALE,
    label: (
      <FormattedMessage
        id="register.gender.neutered_female"
        defaultMessage="Neutered Female"
      />
    ),
  },
  {
    value: PetGender.UNKNOWN_PET,
    label: (
      <FormattedMessage
        id="register.gender.unknown_pet"
        defaultMessage="Unknown Pet"
      />
    ),
  },
];

/**
 * 根据产品类型获取性别选项
 * @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

// 导入性别选项配置
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

添加人类性别选项的英文翻译:

{
  // ... 现有翻译

  // 人类性别选项
  "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

添加中文翻译:

{
  // ... 现有翻译

  // 人类性别选项
  "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. 产品类型判断逻辑

const productName = useSelector((state: RootState) => state.product.productName);

const genderOptions = useMemo(() => {
  return getGenderOptions(productName);
}, [productName]);
  • 使用 Redux selector 获取产品名称
  • 使用 useMemo 避免不必要的重新计算
  • 依赖 productName 变化时重新计算性别选项

2. 类型安全设计

// 使用枚举确保类型安全
export enum HumanGender {
  MALE = 'male',
  FEMALE = 'female',
  OTHER = 'other',
  UNKNOWN = 'unknown',
}

// 统一的选项接口
export interface GenderOption {
  value: string;
  label: React.ReactNode;
}
  • 枚举值与国际化 key 保持一致
  • 接口定义确保所有选项都有统一的结构

3. 国际化集成

// 使用 FormattedMessage 进行国际化
label: (
  <FormattedMessage
    id="register.gender.male"
    defaultMessage="Male"
  />
),
  • 支持多语言切换
  • 提供默认值防止 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