useFieldDependencies.js 3.66 KB
/**
 * 字段关联系统 Composable
 *
 * @description 管理计划书字段之间的关联关系(显示/隐藏、启用/禁用)
 * @module composables/useFieldDependencies
 * @author Claude Code
 * @created 2026-02-14
 */

import { computed, reactive } from 'vue'
import { PLAN_FIELD_DEFINITIONS } from '@/config/plan-fields'

/**
 * 字段关联系统
 *
 * @description 管理字段的显示/隐藏状态,根据字段关联关系自动更新
 * @param {Object} formData - 表单数据
 * @returns {Object} 字段关联管理方法和状态
 *
 * @example
 * const { visibleFields, updateFieldValue, isFieldVisible, isFieldEnabled } = useFieldDependencies(formData)
 *
 * // 检查字段是否可见
 * if (isFieldVisible('withdrawal_mode')) {
 *   // 处理逻辑
 * }
 *
 * // 更新字段值
 * updateFieldValue('withdrawal_enabled', true)
 *
 * // 获取所有可见字段
 * const visible = visibleFields.value
 */
export function useFieldDependencies(formData) {
  // 字段显示状态映射
  const fieldVisibility = reactive({})

  // 字段启用状态映射
  const fieldEnabled = reactive({})

  /**
   * 检查字段是否应该显示
   *
   * @param {string} fieldKey - 字段键名
   * @returns {boolean} 是否显示
   */
  function isFieldVisible(fieldKey) {
    const definition = PLAN_FIELD_DEFINITIONS[fieldKey]
    if (!definition) return false

    // 检查是否有 show_when 条件
    if (definition.show_when) {
      const conditions = definition.show_when
      for (const [depKey, expectedValue] of Object.entries(conditions)) {
        const currentValue = formData[depKey]
        if (currentValue !== expectedValue) {
          return false
        }
      }
    }

    // 检查是否被依赖字段影响
    for (const [key, def] of Object.entries(PLAN_FIELD_DEFINITIONS)) {
      if (def.affects?.includes(fieldKey)) {
        // 依赖字段必须为 true 才显示
        if (formData[key] !== true) {
          return false
        }
      }
    }

    return true
  }

  /**
   * 检查字段是否启用
   *
   * @param {string} fieldKey - 字段键名
   * @returns {boolean} 是否启用
   */
  function isFieldEnabled(fieldKey) {
    const definition = PLAN_FIELD_DEFINITIONS[fieldKey]
    if (!definition) return false

    // 如果有依赖字段,检查依赖字段是否满足
    if (definition.depends_on) {
      const depValue = formData[definition.depends_on]
      return depValue === true
    }

    return true
  }

  /**
   * 更新字段值并更新关联状态
   *
   * @param {string} fieldKey - 字段键名
   * @param {*} value - 新值
   */
  function updateFieldValue(fieldKey, value) {
    formData[fieldKey] = value

    // 更新受影响字段的显示状态
    const definition = PLAN_FIELD_DEFINITIONS[fieldKey]
    if (definition?.affects) {
      for (const affectedKey of definition.affects) {
        fieldVisibility[affectedKey] = isFieldVisible(affectedKey)
        fieldEnabled[affectedKey] = isFieldEnabled(affectedKey)
      }
    }
  }

  /**
   * 获取所有可见字段列表
   *
   * @returns {string[]} 可见字段键名数组
   */
  const visibleFields = computed(() => {
    return Object.keys(PLAN_FIELD_DEFINITIONS).filter(key => isFieldVisible(key))
  })

  /**
   * 初始化所有字段的显示状态
   */
  function initFieldStates() {
    for (const key of Object.keys(PLAN_FIELD_DEFINITIONS)) {
      fieldVisibility[key] = isFieldVisible(key)
      fieldEnabled[key] = isFieldEnabled(key)
    }
  }

  // 初始化
  initFieldStates()

  return {
    // 状态
    fieldVisibility,
    fieldEnabled,
    visibleFields,

    // 方法
    isFieldVisible,
    isFieldEnabled,
    updateFieldValue,
    initFieldStates
  }
}