planFieldTransformers.js 5 KB
/**
 * 计划书字段值转换工具
 *
 * @description 提供各种数据格式的转换函数,用于表单数据提交前的格式化
 * @module utils/planFieldTransformers
 * @author Claude Code
 * @created 2026-02-14
 */

import { TRANSFORM_TYPES } from '@/config/plan-fields'

/**
 * 分转元
 * @description 将分(整数)转换为元(浮点数,保留2位小数)
 * @param {number|string} value - 分值(如 10000)
 * @returns {string|null} 元值(如 "100.00")
 *
 * @example
 * fenToYuan(10000) // "100.00"
 * fenToYuan(0) // "0.00"
 * fenToYuan(null) // null
 */
export function fenToYuan(value) {
  // 空字符串返回 null
  if (value === null || value === '') {
    return null
  }
  // undefined 保持原值(不转换)
  if (value === undefined) {
    return undefined
  }

  const numValue = parseFloat(value)
  if (Number.isNaN(numValue)) {
    return null
  }

  return (numValue / 100).toFixed(2)
}

/**
 * 元转分
 * @description 将元(浮点数)转换为分(整数)
 * @param {number|string} value - 元值(如 "100.00")
 * @returns {number|null} 分值(如 10000)
 *
 * @example
 * yuanToFen("100.00") // 10000
 * yuanToFen(0) // 0
 * yuanToFen(null) // null
 */
export function yuanToFen(value) {
  if (value === null || value === undefined || value === '') {
    return null
  }

  const numValue = parseFloat(value)
  if (Number.isNaN(numValue)) {
    return null
  }

  return Math.round(numValue * 100)
}

/**
 * 年龄格式化
 * @description 将数字年龄格式化为 "XX岁" 字符串
 * @param {number} value - 年龄数字
 * @returns {string|null} 格式化后的年龄
 *
 * @example
 * formatAge(25) // "25岁"
 * formatAge(null) // null
 */
export function formatAge(value) {
  if (value === null || value === undefined) {
    return null
  }
  return `${value}岁`
}

/**
 * 无需转换
 * @description 直接返回原值
 * @param {*} value - 任意值
 * @returns {*} 返回原值
 */
export function noneTransform(value) {
  return value
}

/**
 * 转换器映射表
 * @type {Object<string, Function>}
 */
export const FIELD_TRANSFORMERS = {
  [TRANSFORM_TYPES.FEN_TO_YUAN]: fenToYuan,
  [TRANSFORM_TYPES.YUAN_TO_FEN]: yuanToFen,
  [TRANSFORM_TYPES.NONE]: noneTransform
}

/**
 * 执行字段值转换
 * @param {*} value - 原始值
 * @param {string} transformType - 转换类型
 * @returns {*} 转换后的值
 *
 * @example
 * transformFieldValue(10000, 'fen_to_yuan') // "100.00"
 * transformFieldValue("100.00", 'none') // "100.00"
 */
export function transformFieldValue(value, transformType) {
  if (!transformType || transformType === TRANSFORM_TYPES.NONE) {
    return value
  }

  const transformer = FIELD_TRANSFORMERS[transformType]

  if (!transformer) {
    console.warn(`[planFieldTransformers] 未知的转换类型: ${transformType}`)
    return value
  }

  return transformer(value)
}

/**
 * 批量转换字段值
 * @param {Object} formData - 表单数据
 * @param {Object} fieldDefinitions - 字段定义映射
 * @returns {Object} 转换后的数据
 *
 * @example
 * batchTransformFields(
 *   { coverage: 10000, name: 'Test' },
 *   { coverage: { transform: 'fen_to_yuan' } }
 * ) // { coverage: '100.00', name: 'Test' }
 */
export function batchTransformFields(formData, fieldDefinitions) {
  const result = { ...formData }

  for (const [key, value] of Object.entries(result)) {
    const definition = fieldDefinitions[key]

    if (!definition || !definition.transform) {
      continue
    }

    result[key] = transformFieldValue(value, definition.transform)
  }

  return result
}

/**
 * 反向转换(从 API 响应转换回表单格式)
 * @param {Object} data - API 返回的数据
 * @param {Object} fieldDefinitions - 字段定义映射
 * @returns {Object} 转换后的表单数据
 *
 * @example
 * reverseTransformFields(
 *   { annual_premium: '100.00', name: 'Test' },
 *   { annual_premium: { api_field: 'annual_premium', transform: 'fen_to_yuan' } }
 * ) // { annual_premium: 10000, name: 'Test' }
 */
export function reverseTransformFields(data, fieldDefinitions) {
  const result = {}

  for (const [formKey, definition] of Object.entries(fieldDefinitions)) {
    // 跳过没有 api_field 的字段
    if (!definition.api_field) {
      continue
    }

    const apiValue = data[definition.api_field]
    if (apiValue === undefined || apiValue === null) {
      continue
    }

    // 没有转换类型,直接使用原值
    if (!definition.transform || definition.transform === TRANSFORM_TYPES.NONE) {
      result[formKey] = apiValue
      continue
    }

    // 获取反向转换器
    let reverseTransform = definition.transform

    if (reverseTransform === TRANSFORM_TYPES.FEN_TO_YUAN) {
      reverseTransform = TRANSFORM_TYPES.YUAN_TO_FEN
    } else if (reverseTransform === TRANSFORM_TYPES.YUAN_TO_FEN) {
      reverseTransform = TRANSFORM_TYPES.FEN_TO_YUAN
    } else {
      // 未知转换类型,使用原值
      result[formKey] = apiValue
      continue
    }

    result[formKey] = transformFieldValue(apiValue, reverseTransform)
  }

  return result
}