You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
cz-hjjc-budget/模板元素显示条件说明.md

9.2 KiB

模板元素显示条件说明文档

概述

在直接支付页面(/payment/direct-payment)中,模板元素的显示/隐藏受"合同总金额"和"本次支付金额"两个金额字段控制。本文档详细说明其作用机制。

核心函数

函数位置czemc-budget-execution-frontend/src/views/payment/CreatePayment.vue

核心函数checkFieldDisplayConditions(element) 第866-983行

使用位置模板中的动态字段渲染第310行

<el-form-item
  v-if="(element.type !== 'approval_flow' || !element.is_main_approval_process) && checkFieldDisplayConditions(element)"
  ...
>

金额字段的定义和取值逻辑

1. 本次支付金额current_payment_amount

定义:用户在表单中输入的"支付金额"字段值

取值逻辑

const currentPaymentAmount = formData.amount || 0
  • 来源:直接使用表单数据 formData.amount
  • 说明:始终为用户当前输入的支付金额,不存在时默认为 0

2. 合同总金额contract_total_amount

定义:用于条件判断的合同总金额值

取值逻辑

let contractTotalAmount
if (selectedCategory.value?.need_contract && selectedContract.value) {
  // 情况1分类需要关联合同且已选择合同
  contractTotalAmount = selectedContract.value.amount_total || 0
} else {
  // 情况2分类不需要关联合同或未选择合同
  contractTotalAmount = currentPaymentAmount  // 使用本次支付金额
}

两种取值情况

情况1分类需要关联合同且已选择合同

  • 取值来源selectedContract.value.amount_total
  • 说明:使用已选择合同的真实总金额
  • 适用场景:直接支付页面,分类配置了 need_contract: true,用户已选择合同

情况2分类不需要关联合同或未选择合同

  • 取值来源formData.amount(本次支付金额)
  • 说明:将本次支付金额作为"合同总金额"用于条件判断
  • 适用场景
    • 分类未配置需要关联合同(need_contract: false
    • 分类需要关联合同,但用户尚未选择合同
    • 非直接支付场景

显示条件的判断逻辑

条件配置格式

每个模板元素(element)可以配置 display_conditions 数组,格式如下:

{
  display_conditions: [
    {
      field: 'contract_total_amount' | 'current_payment_amount',  // 要判断的字段
      op: 'lt' | 'lte' | 'gt' | 'gte' | 'eq',                    // 操作符
      value: 10000                                                 // 比较值(数字)
    },
    // ... 可以有多个条件所有条件必须同时满足AND逻辑
  ]
}

支持的操作符

操作符 含义 示例 说明
lt 小于 { field: 'current_payment_amount', op: 'lt', value: 10000 } 本次支付金额 < 10000
lte 小于等于 { field: 'contract_total_amount', op: 'lte', value: 50000 } 合同总金额 ≤ 50000
gt 大于 { field: 'current_payment_amount', op: 'gt', value: 5000 } 本次支付金额 > 5000
gte 大于等于 { field: 'contract_total_amount', op: 'gte', value: 100000 } 合同总金额 ≥ 100000
eq 等于 { field: 'current_payment_amount', op: 'eq', value: 8888 } 本次支付金额 = 8888

判断流程

  1. 无显示条件:如果元素没有 display_conditions 或为空数组,默认显示
  2. 有显示条件:遍历 display_conditions 数组,所有条件必须同时满足AND逻辑
  3. 条件匹配
    • 根据 condition.field 确定要比较的值(contract_total_amountcurrent_payment_amount
    • 根据 condition.op 执行比较操作
    • 将比较值与 condition.value 进行比较
  4. 返回结果
    • 所有条件都满足 → 显示字段
    • 任一条件不满足 → 隐藏字段

实际应用示例

示例1基于本次支付金额的条件

场景:当本次支付金额大于 50000 时,显示"大额支付说明"字段

配置

{
  id: 'field_001',
  name: '大额支付说明',
  display_conditions: [
    {
      field: 'current_payment_amount',
      op: 'gt',
      value: 50000
    }
  ]
}

效果

  • 用户输入 60000 → 显示该字段
  • 用户输入 30000 → 隐藏该字段

示例2基于合同总金额的条件已选择合同

场景:当合同总金额小于等于 100000 时,显示"小额合同附件"字段

前提条件

  • 分类配置了 need_contract: true
  • 用户已选择合同,合同总金额为 80000

配置

{
  id: 'field_002',
  name: '小额合同附件',
  display_conditions: [
    {
      field: 'contract_total_amount',
      op: 'lte',
      value: 100000
    }
  ]
}

效果

  • 合同总金额 = 80000使用 selectedContract.amount_total
  • 80000 ≤ 100000 → 显示该字段

示例3基于合同总金额的条件未选择合同

场景:当合同总金额大于 200000 时,显示"大额合同审批"字段

前提条件

  • 分类配置了 need_contract: true
  • 用户尚未选择合同

配置

{
  id: 'field_003',
  name: '大额合同审批',
  display_conditions: [
    {
      field: 'contract_total_amount',
      op: 'gt',
      value: 200000
    }
  ]
}

效果

  • 由于未选择合同,contract_total_amount = formData.amount(本次支付金额)
  • 如果用户输入 250000 → 250000 > 200000 → 显示该字段
  • 如果用户输入 150000 → 150000 ≤ 200000 → 隐藏该字段

示例4多条件组合AND逻辑

场景:当本次支付金额大于 10000 合同总金额小于等于 500000 时,显示"中等金额说明"字段

配置

{
  id: 'field_004',
  name: '中等金额说明',
  display_conditions: [
    {
      field: 'current_payment_amount',
      op: 'gt',
      value: 10000
    },
    {
      field: 'contract_total_amount',
      op: 'lte',
      value: 500000
    }
  ]
}

效果

  • 本次支付金额 = 20000合同总金额 = 400000 → 两个条件都满足 → 显示
  • 本次支付金额 = 5000合同总金额 = 400000 → 第一个条件不满足 → 隐藏
  • 本次支付金额 = 20000合同总金额 = 600000 → 第二个条件不满足 → 隐藏

实时响应机制

当金额字段或合同选择发生变化时,会触发字段显示/隐藏的重新计算:

监听逻辑第2071-2095行

watch(
  () => [formData.amount, selectedContract.value],
  () => {
    // 当金额字段或合同选择变化时,清除隐藏字段的验证错误
    if (formRef.value && templateElements.value) {
      nextTick(() => {
        templateElements.value.forEach(element => {
          if (!checkFieldDisplayConditions(element)) {
            // 字段不满足显示条件,清除验证错误
            formRef.value?.clearValidate(`fields.${element.id}`)
          }
        })
      })
    }
  },
  { deep: true }
)

触发时机

  • 用户修改"支付金额"时
  • 用户选择/清除合同时
  • 合同信息变化时(通过 deep: true 深度监听)

响应效果

  • 隐藏不满足条件的字段,并清除其验证错误
  • 显示满足条件的字段

关键代码位置汇总

功能 文件位置 行号范围
显示条件判断核心函数 CreatePayment.vue 866-983
模板中使用显示条件 CreatePayment.vue 310
金额变化监听 CreatePayment.vue 2071-2095
表单验证规则生成(考虑显示条件) CreatePayment.vue 986-1024

注意事项

  1. 合同总金额的取值逻辑

    • 如果分类需要关联合同但用户未选择合同,contract_total_amount 会回退为本次支付金额
    • 这可能导致某些基于合同总金额的条件判断不够准确,建议在配置条件时考虑这种情况
  2. 条件判断的默认行为

    • 无效条件、未知字段、无效数值等情况,函数会返回 true(默认显示)
    • 这保证了向后兼容性,但可能在某些异常情况下导致字段意外显示
  3. 验证规则的同步

    • 表单验证规则只在字段满足显示条件时才添加第998行
    • 当字段被隐藏时,会自动清除其验证错误,避免用户看到隐藏字段的错误提示
  4. 性能考虑

    • checkFieldDisplayConditions 函数在每次字段渲染时都会被调用
    • 函数中包含大量 console.log,生产环境建议移除以提高性能

总结

  • 本次支付金额current_payment_amount:始终为用户输入的支付金额,用于判断当前支付规模
  • 合同总金额contract_total_amount
    • 优先使用已选择合同的真实总金额(如果分类需要关联合同且已选择)
    • 否则回退为本次支付金额
    • 用于判断合同规模
  • 显示逻辑所有条件必须同时满足AND逻辑条件不满足时字段自动隐藏并清除验证错误