useFieldValueTransform.js 5.17 KB
/**
 * 字段值转换 Composable
 *
 * @description 封装字段值转换逻辑,提供统一的转换 API
 * @module composables/useFieldValueTransform
 * @author Claude Code
 * @created 2026-02-14
 * @version 1.1.0 - 简化转换逻辑,减少重复代码
 */

import { computed, isRef } from 'vue'
import { PLAN_FIELD_DEFINITIONS, TRANSFORM_TYPES } from '@/config/plan-fields'
import { transformFieldValue, batchTransformFields } from '@/utils/planFieldTransformers'

/**
 * 使用字段值转换
 *
 * @description 提供字段值的双向转换能力
 * @param {Object} formData - 表单数据
 * @returns {Object} 转换方法和计算属性
 *
 * @example
 * const { yuanFormData, fenFormData, toYuan, toFen, reset } = useFieldValueTransform(formData)
 *
 * // 转换为分值用于显示
 * toYuan('coverage', 10000) // '100.00'
 *
 * // 转换为元值用于提交
 * toFen('coverage', '100.00') // 10000
 */
// eslint-disable-next-line react-hooks/rules-of-hooks
export function useFieldValueTransform(formData, fieldDefinitions = PLAN_FIELD_DEFINITIONS) {
  const getFieldDefinitions = () => {
    const definitions = isRef(fieldDefinitions) ? fieldDefinitions.value : fieldDefinitions
    return definitions || {}
  }

  const getReverseTransform = (transform) => {
    if (!transform || transform === TRANSFORM_TYPES.NONE) return TRANSFORM_TYPES.NONE
    if (transform === TRANSFORM_TYPES.FEN_TO_YUAN) return TRANSFORM_TYPES.YUAN_TO_FEN
    if (transform === TRANSFORM_TYPES.YUAN_TO_FEN) return TRANSFORM_TYPES.FEN_TO_YUAN
    return TRANSFORM_TYPES.NONE
  }

  const getReverseFieldDefinitions = () => {
    return Object.entries(getFieldDefinitions()).reduce((result, [key, definition]) => {
      if (!definition || typeof definition === 'string') {
        result[key] = { transform: TRANSFORM_TYPES.NONE }
        return result
      }
      const reverseTransform = getReverseTransform(definition.transform)
      result[key] = {
        ...definition,
        transform: reverseTransform
      }
      return result
    }, {})
  }

  /**
   * 转换为分值(用于显示)
   *
   * @description 将表单中的值统一转换为分值显示
   * @param {string} fieldKey - 字段名称
   * @param {*} value - 原始值(可能是元或分)
   * @returns {*} 转换后的分值
   *
   * @example
   * toYuan('annual_premium', 10000) // '100.00' (分转元显示)
   * toYuan('coverage', '100.00') // '100.00' (元值直接显示)
   */
  const toYuan = (fieldKey, value) => {
    if (value === undefined) return undefined
    if (value === null) return null
    const definition = getFieldDefinitions()[fieldKey]
    if (!definition || typeof definition === 'string') return value

    if (!definition.transform || definition.transform === TRANSFORM_TYPES.NONE) {
      return value
    }

    return transformFieldValue(value, definition.transform)
  }

  /**
   * 转换为分值(用于提交)
   *
   * @description 将表单中的值统一转换为分值提交
   * @param {string} fieldKey - 字段名称
   * @param {*} value - 原始值(可能是元或分)
   * @returns {*} 转换后的分值
   *
   * @example
   * toFen('annual_premium', '100.00') // 10000 (元转分提交:×100)
   * toFen('coverage', 10000) // 10000 (元值,转为分值:×100)
   * toFen('withdrawal_period', 3) // 3 (无转换,直接返回)
   */
  const toFen = (fieldKey, value) => {
    if (value === undefined) return undefined
    if (value === null) return null
    const definition = getFieldDefinitions()[fieldKey]
    if (!definition || typeof definition === 'string') return value

    const reverseTransform = getReverseTransform(definition.transform)
    if (!reverseTransform || reverseTransform === TRANSFORM_TYPES.NONE) {
      return value
    }

    return transformFieldValue(value, reverseTransform)
  }

  /**
   * 批量转换为分值(用于初始化表单显示)
   *
   * @description 将表单数据(元值)转换为分值格式(带两位小数)用于显示
   * @param {Object} formData - 表单数据
   * @returns {Object} 分值格式的数据
   *
   * @example
   * batchToYuan({ coverage: 10000, name: 'Test' })
   * // { coverage: '100.00', name: 'Test' }
   */
  const batchToYuan = (sourceData) => {
    return batchTransformFields(sourceData, getFieldDefinitions())
  }

  /**
   * 批量转换为分值(用于提交 API)
   *
   * @description 将表单的元值数据批量转换为分值整数
   * @param {Object} yuanData - 元值数据
   * @returns {Object} 分值数据
   *
   * @example
   * batchToFen({ coverage: '100.00', name: 'Test' })
   * // { coverage: 10000, name: 'Test' }
   */
  const batchToFen = (yuanData) => {
    return batchTransformFields(yuanData, getReverseFieldDefinitions())
  }

  // 计算属性:表单显示数据(元值转分值显示)
  const displayData = computed(() => batchToYuan(formData.value))

  // 计算属性:API 提交数据(元值转分值提交)
  const submitData = computed(() => batchToFen(formData.value))

  return {
    toYuan,
    toFen,
    batchToYuan,
    batchToFen,
    displayData, // 计算属性:表单显示数据(元值转分值显示)
    submitData  // 计算属性:API 提交数据(元值转分值提交)
  }
}