<template>
  <div class="bank-report-table" @click="closeTooltip">
    <!-- 加载遮罩层 -->
    <div v-if="loading" class="loading-overlay">
      <div class="loading-spinner">
        <div class="spinner"></div>
        <div class="loading-text">加载中...</div>
      </div>
    </div>
   
    <vxe-toolbar>
      <template #buttons>
        <div style="margin:10px">
          <span style="font-weight: bold"> 填报任务：{{ queryParam?.taskName }} </span>
          <span style="font-weight: bold;margin-left:20px"> 表格：{{ queryParam?.tplCode }} {{ queryParam?.tplName }}</span>
        </div>
      </template>
      <template #tools>
        <vxe-button status="primary" icon="vxe-icon-edit" @click="validateAndShowResults()" :disabled="loading">校验</vxe-button>
        <vxe-button status="primary"  icon="vxe-icon-save" @click="saveBatch()" :disabled="loading">保存</vxe-button>
      </template>
    </vxe-toolbar>
    <vxe-table
      border
      ref="tableRef"
      show-header-overflow
      :data="tableFormData"
      :column-config="{ resizable: true }"
      :row-config="{ resizable: true }"
      height="auto"
      class="custom-table"
      :merge-cells="mergeCells"
      :loading="loading" 
    >
      <vxe-column field="serialNumber" title="序号" width="50"></vxe-column>
      <vxe-column field="project" title="项目" width="40">
        <template #default="{ row }">
          <span style="font-weight: bold;size:20px">{{ row.project }}</span>
        </template>
      </vxe-column>
      <vxe-column field="project2" title="" width="120">
        <template #default="{ row }">
          <span style="font-weight: bold;size:20px">{{ row.project2 }}</span>
        </template>
      </vxe-column>
      <vxe-column field="content" title="内容" row-resize>
        <template #default="{ row }"> 
          
          <div class="content-cell">
            <template v-if="row.type === 'MultiColumnTable'">
              <MultiColumnTable
                :title="row.project"
                :records="row.datas"
                :fields="row.content"
                :ref="(el) => setMultiColumnTableRef(el, row.code)"
                style="margin:0px;padding:0px"
              />
            </template>
            <template v-else-if="row.type === 'AttachTable'">
              <AttachTable
                :disabled="!row.hasRight"
                :title="row.project"
                :records="row.datas"
                :fields="row.content"
                :pcode="row.code"
                :ref="(el) => setAttachTableRef(el, row.code)"
                style="margin:0px;padding:0px"
              />
            </template>

            <template v-else-if="row.type === 'ExportTable'">
              <ExportTable
                :disabled="!row.hasRight"
                :title="row.project"
                :records="row.datas"
                :fields="row.content"
                :pcode="row.code"
                :ref="(el) => setExportTableRef(el, row.code)"
                style="margin:0px;padding:0px"
              />
            </template>
            <template v-else>
              <template v-for="(item, index) in row.content" :key="index">
                <span v-if="item.type === 'text'" v-html="item.value"></span>
                <span v-else-if="item.type === 'br'"><br></span>
                <span v-else-if="item.type === 'brspace'">
                  <br>
                  <template v-for="i in item.value||1" :key="i">
                    &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
                  </template>
                </span>
                
                <span v-else-if="item.type === 'radio-group'" class="radio-group">
                  <vxe-radio-group v-model="formData[row.code +'_'+ item.field]" :disabled="!item.hasRight">
                    <vxe-radio
                      v-for="(opt, optIndex) in item.options"
                      :key="optIndex"
                      :label="opt"
                      >{{ opt }}</vxe-radio
                    >
                  </vxe-radio-group>
                </span>
                <div v-else-if="item.type === 'checkbox-group'" class="checkbox-group">
        
                  <span class="checkbox-group">
                      <vxe-checkbox-group v-model="formData[row.code+'_'+item.field]" :disabled="!item.hasRight">
                        <vxe-checkbox v-for="(opt, optIndex) in item.options" :key="optIndex" :label="opt">
                          {{ opt }} 
                        </vxe-checkbox>
                        <template v-if="item.otereField">
                          <vxe-checkbox style="margin:0px" label="其他">
                            其他：
                          </vxe-checkbox>
                          <vxe-input v-model="formData[row.code + '_'+ item.otereField]"  style="width: 100px;">
                          </vxe-input>
                        </template>
                      </vxe-checkbox-group>
                    </span> 
                </div>

                <template v-else-if="item.type === 'textarea'">
                  <vxe-textarea 
                    :disabled="!item.hasRight"
                    v-model="formData[row.code +'_'+ item.field]"
                    size="mini"
                    class="table-input"
                    rows="1"
                    style="width:300px"
                  >
                  </vxe-textarea>
                  
                </template>

                <template v-else>
                  <div class="input-wrapper">
                    <vxe-input 
                      :disabled="!item.hasRight"
                      :type="item.type"
                      v-model="formData[row.code +'_'+ item.field]"
                      size="mini"
                      class="table-input"
                      :style="{width:item.width}"
                      :status="getInputStatus(row.code, item.field)"
                      @input="handleInputChange(row.code, item.field)"
                    >
                    </vxe-input>
                    <span class="unit"> {{ item.unit }}</span>
                    <span v-if="item.hasValidFormula" class="help-icon" @click.stop="toggleTooltip(row.code, item.field)">?</span>
                    <div v-if="getInputStatus(row.code, item.field) === 'error'" class="error-tip">
                      {{ getErrorMessage(row.code, item.field) }}
                    </div>
                    <div v-if="showTooltip && hoveredKey === row.code +'_'+ item.field" class="tooltip" @click.stop>
                      {{ getValidationRule(row.code, item.field) }}
                    </div>
                  </div>
                </template>
              </template>
            </template>
          </div>
        </template>
      </vxe-column>
      <vxe-column field="remarks" title="备注" width="60">
        <template #default="{ row }"> 
            <vxe-textarea  :disabled="row.remarks.hasRight" :rows="row.remarks.rows" v-model="formData[row.code+'_'+row.remarks.field]">
            </vxe-textarea>
        </template>
      </vxe-column>
    </vxe-table>

    <!-- 校验结果抽屉 -->
    <vxe-drawer
      v-model="drawerVisible"
      placement="right"
      @show="onDrawerShow"
      title="校验结果"
      width="40%"
      :footer="{ show: true }"
    >
      <template #default>
        <div class="validation-results">
          <div class="result-summary">
            <div class="summary-item">
              <span class="summary-label">校验字段数：</span>
              <span class="summary-value">{{ validationResultsList.length }}</span>
            </div>
            <div class="summary-item">
              <span class="summary-label">通过：</span>
              <span class="summary-value success">{{ validationResultsList.filter(item => item.isValid).length }}</span>
            </div>
            <div class="summary-item">
              <span class="summary-label">失败：</span>
              <span class="summary-value error">{{ validationResultsList.filter(item => !item.isValid).length }}</span>
            </div>
          </div>

          <div class="result-list">
            <div
              v-for="(item, index) in validationResultsList"
              :key="index"
              class="result-item"
              :class="{ success: item.isValid, error: !item.isValid }"
            >
              <div class="result-item-header">
                <span class="result-item-name">{{ item.fieldTitle || item.fieldName }}</span>
                <span class="result-item-status" :class="{ success: item.isValid, error: !item.isValid }">
                  {{ item.isValid ? '通过' : '失败' }}
                </span>
              </div>
              <div class="result-item-content">
                <div class="result-item-formula">
                  <span class="formula-label">验证公式：</span>
                  <span class="formula-value">{{ item.formula }}</span>
                </div>
                <div class="result-item-result">
                  <span class="result-label">验证结果：</span>
                  <span class="result-value">{{ item.resultMessage }}</span>
                </div>
                <div class="result-item-values" v-if="item.fieldValues">
                  <span class="values-label">字段值：</span>
                  <pre class="values-value">{{ formatJSON(item.fieldValues) }}</pre>
                </div>
                <div class="result-item-process" v-if="item.process">
                  <span class="process-label">校验过程：</span>
                  <div class="process-content">
                    <div v-for="(step, stepIndex) in item.process" :key="stepIndex" class="process-step">
                      <span class="step-number">{{ stepIndex + 1 }}</span>
                      <span class="step-text">{{ step }}</span>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </div>
        </div>
      </template>
    </vxe-drawer>
  </div>
</template>

<script lang="ts" setup>
import MultiColumnTable from '../tableComponents/MultiColumnTable.vue'
import AttachTable from '../tableComponents/AttachTable.vue'


import { tableFormData } from '../../data/tb3.data';
import { ref, reactive,nextTick,onMounted,toRaw } from 'vue'
import { VxeUI,VxeTablePropTypes,VxeToolbarPropTypes } from 'vxe-table'
import { batchSaveOrUpdate, queryRecord,batchSaveOrUpdateBeforeDelete } from '../../record/BaosongTaskRecord.api'
import { findUserRightForTplItem } from '../../alloc/BaosongTaskAlloc.api'
import { allTplItems } from '../../tpl/BaosongTplItem.api'
import { getTblvalidFormula } from '../../tpl/BaosongDataValid.api'

import { useRoute } from 'vue-router';


const route = useRoute();
const tableRef = ref();
const tplItemMap = ref({});
const userAllocItems = ref([])
const validFormula = ref([])
const validationResults = ref<Record<string, string>>({})
const validationMessages = ref<Record<string, string>>({})

const formData = reactive({});
const formValues = ref<FormData[]>([])
const showTooltip = ref(false)
const hoveredKey = ref('')

// 校验结果抽屉相关
const drawerVisible = ref(false)
const validationResultsList = ref<any[]>([])

interface ValidationResult {
  fieldTitle: string
  fieldName: string
  formula: string
  isValid: boolean
  resultMessage: string
  process?: string[]
}

const queryParam = ref({
  taskId:-1,
  taskName:'',
  tplId:-1,
  tplName:'',
  tplCode:''
})

interface FormData {
  id: number | null
  taskid: number
  tplid: number
  itemid?: number
  itempid?:number
  content: string
  tplcode:string
  rind:number
}

// 初始化loading状态
const loading = ref(true)

onMounted(async ()=>{
  if (route.query.taskId) {  
    queryParam.value.taskId = Number(route.query.taskId); 
  }  
  if (route.query.taskName) {  
    queryParam.value.taskName = String(route.query.taskName);
  } 
  if (route.query.tplId) {  
    queryParam.value.tplId = Number(route.query.tplId);  
  }  
  if (route.query.tplName) {  
    queryParam.value.tplName = String(route.query.tplName); 
  } 
  if (route.query.tplCode) {  
    queryParam.value.tplCode = String(route.query.tplCode); 
  } 

  try {
    userAllocItems.value = await findUserRightForTplItem({
      tplid:queryParam.value.tplId,
      taskid:queryParam.value.taskId
    });

    validFormula.value = await getTblvalidFormula({
      tplid:queryParam.value.tplId,
    });
    
    await setFormItemRight();
    await setTplItemMap()
    await setData();
    await validateAllInputs();
  } catch (error) {
    VxeUI.modal.message({ 
      content: `初始化页面失败: ${error.message}`, 
      status: 'error' 
    });
  } finally {
    loading.value = false
  }
})

const setFormItemRight = async () => {
    tableFormData.forEach(row => {
      if (row.content && Array.isArray(row.content)) {
          row.content.forEach(item => {
              if (item.field) {
                  let tmpKey = `${row.code}_${item.field}`;
                  item["hasRight"] = userAllocItems.value.indexOf(tmpKey)>-1
                  item["hasValidFormula"] = validFormula.value?.length > 0 && 
                    validFormula.value.some((f: any) => {
                      const formulaText = (f.formula || '').toString()
                      return formulaText.includes(item.field)
                    })
              }
          });
      }
      if (row.remarks && row.remarks.field) {
          let tmpKey = `${row.code}_${row.remarks.field}`;
          row.remarks["hasRight"] = userAllocItems.value.indexOf(tmpKey)>-1
          row.remarks["hasValidFormula"] = validFormula.value?.length > 0 && 
            validFormula.value.some((f: any) => {
              const formulaText = (f.formula || '').toString()
              return formulaText.includes(row.remarks.field)
            })
      }
    });
}

const saveBatch = async () => {
  try {
    // 保存时也显示loading
    const saveLoading = ref(true)
    formValues.value = []

    for (const strKey in formData) {
      const valData = formData[strKey]
      if (valData) {
        let tmpAry = strKey.split("_")
        await setFormValues(tmpAry[0],tmpAry[1],valData,1)    
      }
    }
    await getAttachTableFormData();
    await getAllMultiTableFormData()
    if (formValues.value.length > 0) {
      await batchSaveOrUpdateBeforeDelete(formValues.value)
      VxeUI.modal.message({ content: '保存成功', status: 'success' })
      //await setData()
    } else {
      VxeUI.modal.message({ content: '没有需要保存的数据', status: 'warning' })
    }
  } catch (error) {
    VxeUI.modal.message({ content: `保存失败: ${error.message}`, status: 'error' })
  } finally {
    loading.value = false
  }
}

const childMultiTableRefs = ref({})
const setMultiColumnTableRef = (el: any, index: string) => {
  if (el) {
    childMultiTableRefs.value[index] = el;
  }
};

const getAllMultiTableFormData = async () => {
  for (const pcode in childMultiTableRefs.value) {
      const child = childMultiTableRefs.value[pcode];
      if (child) {
          const datas = child.getFormData()
          let rind = 0
          for(const obj of datas) {
            rind++
            Object.keys(obj).forEach(code => {  
              setFormValues(pcode,code,obj[code],rind)
            });
          }
      }
  }
};
const childAttachTableRefs = ref({})
const setAttachTableRef = (el: any, index: string) => {
  if (el) {
    childAttachTableRefs.value[index] = el; // 保存子组件实例
  }
};
const childExportTableRefs = ref({})
const setExportTableRef = (el: any, index: string) => {
  if (el) {
    childExportTableRefs.value[index] = el; // 保存子组件实例
  }
};
const getAttachTableFormData  = async () => {
  for (const pcode in childAttachTableRefs.value) {
      const child = childAttachTableRefs.value[pcode];
      if (child) {
          const datas = child.getFormData()
          for(const code in datas) {
            await setFormValues(pcode,code,datas[code],1)
          }
      }
  }
};
const setFormValues = async (pcode,code,valData,rind) => {
  if(!valData) return;
  let vals = Array.isArray(valData) ? valData.join(',') : valData 
  let strKey = pcode+"_"+code
  const item = tplItemMap.value[strKey];  
  const { pid, itemid } = item ?? {}; 
  let tempForm: FormData = {
    id: null,
    rind:rind,
    taskid: queryParam.value.taskId,
    tplid: queryParam.value.tplId,
    tplcode: code,
    itemid: itemid,
    itempid: pid,
    content:vals
  };
  formValues.value.push(tempForm)
}

async function setData() {
  try {
    loading.value = true;  // 开始加载
    const taskId = queryParam.value.taskId;
    const tplid = queryParam.value.tplId;
    Object.keys(formData).forEach(key => delete formData[key]);
    await setTplItemMap();
    const recordData = await queryRecord({ taskid: taskId, tplid: tplid });
    const valueObj = {};
    for (const data of recordData) {
      const key = `${data.itempid}_${data.itemid}_${data.rind}`;
      valueObj[key] = data.content;
    }
    for (const row of tableFormData) {

      if(!row.type&&row.content) {
        for (const cdata of row.content) {
          if(cdata.field&&cdata.field.length>0) {
            
            const strKey = `${row.code}_${cdata.field}`;           
            const item = tplItemMap.value[strKey];

            if (!item) continue;
            const { pid, itemid, formTp } = item;
            const dataVal = valueObj[`${pid}_${itemid}_1`];
            if (!dataVal) continue;
            if (formTp === 'checkbox') {
              formData[strKey] = dataVal?.split(",") || [];
            } else {
              formData[strKey] = dataVal || "";
            }
            if(cdata.type&&cdata.type=="checkboxAndInput"){
              for (const itemField of cdata.optionItemField) {
                const strItemKey = `${row.code}_${itemField}`;   
                const item2 = tplItemMap.value[strItemKey];
                if (!item2) continue;
                const { pid:pid2, itemid:itemid2 } = item2;
                const dataVal2 = valueObj[`${pid2}_${itemid2}_1`];
                formData[strItemKey] = dataVal2 || "";
              }
            }
          }
        }
      } else if(row.type=="AttachTable"&& row.datas) {
        const curAttachTable = childAttachTableRefs.value[row.code];
        const attachTableData = {};
        for (const cdata of row.datas) {
          Object.keys(cdata).forEach(key => {
            if(cdata[key]["field"]){
              const strKey = `${row.code}_${cdata[key]["field"]}`;           
              const item = tplItemMap.value[strKey];
              if (item) {
                const { pid, itemid, formTp, code } = item;
                const dataVal = valueObj[`${pid}_${itemid}_1`];
                if (dataVal) {
                  if (formTp === 'checkbox') {
                    attachTableData[code] = dataVal?.split(",") || [];
                  } else {
                    attachTableData[code] = dataVal || "";
                  }
                }
              }
            }
          });
        }
        curAttachTable.setFormData(attachTableData);
      } else if(row.type=="MultiColumnTable"&& row.content) {
          const curMultiTable = childMultiTableRefs.value[row.code];
          const rowsMap = {};
          for (const cdata of row.content) {
            if(cdata.field&&cdata.field.length>0) {
              const strKey = `${row.code}_${cdata.field}`;    
              const tmpData = tplItemMap.value[strKey];
              if (!tmpData) continue;
              const { pid, itemid, code } = tmpData;
              const valKeys = Object.keys(valueObj).filter(k => 
                k.startsWith(`${pid}_${itemid}_`)
              );
              for (const valKey of valKeys) {
                const parts = valKey.split('_');
                const rind = parts[2];
                if (!rowsMap[rind]) {
                  rowsMap[rind] = {};
                }
                rowsMap[rind][code] = valueObj[valKey];
              }
            }
          }
          const tableDatas = Object.values(rowsMap);
          curMultiTable.setFormData(tableDatas);
        } 
    }
  } catch (error) {
    console.log(error)
    VxeUI.modal.message({ 
      content: `加载数据失败:`, 
      status: 'error' 
    });
  } finally {
    loading.value = false;  // 结束加载
  }
}
async function setTplItemMap() {
  try {
    loading.value = true;
    const tplid =  queryParam.value.tplId
    const tplItem = await allTplItems({
      tplid: tplid,
    })
    tplItem.forEach(item => {
      let strKey = item.pcode + "_" + item.xmlcode;
      tplItemMap.value[strKey] = {
        pid:item.pid,
        itemid:item.id,
        formTp:item.formTp,
        code:item.xmlcode,
        isDisable:!userAllocItems.value.some(itemid=>itemid==item.id)
      }
    })

  } catch (error) {
    VxeUI.modal.message({ content: `加载数据失败: ${error.message}`, status: 'error' })
  } finally {
    loading.value = false;  // 结束加载
  }
}


const mergeCells = ref<VxeTablePropTypes.MergeCells>([
  { row: 0, col: 1, rowspan: 9, colspan: 1 },
  { row: 9, col: 1, rowspan: 1, colspan: 2 },
  { row: 10, col: 1, rowspan: 1, colspan: 2 },
  { row: 11, col: 1, rowspan: 2, colspan: 1 },
  { row: 11, col: 3, rowspan: 1, colspan: 2 },
  { row: 10, col: 3, rowspan: 1, colspan: 2 },
  { row: 9, col: 3, rowspan: 1, colspan: 2 },
])

const handleInputChange = (rowCode: string, itemField: string) => {
  const key = `${rowCode}_${itemField}`
  validateInput(key)
}

const getInputStatus = (rowCode: string, itemField: string): 'default' | 'error' => {
  const key = `${rowCode}_${itemField}`
  return validationResults.value[key] || ''
}

const getErrorMessage = (rowCode: string, itemField: string): string => {
  const key = `${rowCode}_${itemField}`
  return validationMessages.value[key] || ''
}

const toggleTooltip = (rowCode: string, itemField: string) => {
  const key = `${rowCode}_${itemField}`
  if (hoveredKey.value === key) {
    showTooltip.value = false
    hoveredKey.value = ''
  } else {
    showTooltip.value = true
    hoveredKey.value = key
  }
}

const getValidationRule = (rowCode: string, itemField: string): string => {
  if (!validFormula.value || validFormula.value.length === 0) {
    return ''
  }
  
  try {
    const formulaItems = validFormula.value
    const field = itemField
    
    const targetFormula = formulaItems.find((f: any) => {
      const formulaText = (f.formula || '').toString()
      const regex = new RegExp(`\\b${field}\\b`, 'gi')
      return regex.test(formulaText)
    })
    
    if (targetFormula) {
      return targetFormula.des || `验证规则: ${targetFormula.formula}`
    }
    
    return ''
  } catch (error) {
    console.error('获取验证规则失败:', error)
    return '获取验证规则失败'
  }
}

const closeTooltip = (event: Event) => {
  const target = event.target as HTMLElement
  if (!target.closest('.help-icon')) {
    showTooltip.value = false
    hoveredKey.value = ''
  }
}

const formatJSON = (obj: any): string => {
  if (!obj) {
    return ''
  }
  try {
    return JSON.stringify(obj, null, 2)
  } catch (error) {
    return JSON.stringify({ error: '序列化失败' })
  }
}

const onDrawerShow = () => {
  // 抽屉显示时，设置容器高度为屏幕高度
  setTimeout(() => {
    const drawer = document.querySelector('.vxe-drawer--body')
    if (drawer) {
      const availableHeight = window.innerHeight - 280 // 减去顶部和底部的空间
      const resultList = drawer.querySelector('.result-list')
      if (resultList) {
        resultList.classList.add('result-list--scrolling')
        resultList.style.maxHeight = `${availableHeight}px`
      }
    }
  }, 100)
}

const validateAndShowResults = async () => {
  if (!validFormula.value || validFormula.value.length === 0) {
    VxeUI.modal.message({ content: '没有配置验证规则', status: 'warning' })
    return
  }

  try {
    loading.value = true
    validationResultsList.value = []

    const codeVal = await buildCodeValueMap()
    const formulaItems = validFormula.value

    for (const strKey in formData) {
      const val = formData[strKey]
      if (val === undefined || val === null || val === '') {
        continue
      }

      const field = strKey.split('_')[1]
      const targetFormula = formulaItems.find((f: any) => {
        const formulaText = (f.formula || '').toString()
        const regex = new RegExp(`\\b${field}\\b`, 'gi')
        return regex.test(formulaText)
      })

      if (targetFormula) {
        const formulaText = (targetFormula.formula || '').toString()
        let isValid = false
        let resultMessage = ''
        let process: string[] = []
        let fieldTitle = ''
        // 获取字段标题
        for (const key in tplItemMap.value) {
          if (key.endsWith(`_${field}`)) {
            const item = tplItemMap.value[key]
            if (item && item.name) {
              fieldTitle = item.name
              break
            }
          }
        }

        try {
          process.push(`开始校验字段: ${field}`)
          process.push(`验证公式: ${formulaText}`)
          process.push(`字段值: ${JSON.stringify(codeVal)}`)

          const result = await evaluateFormulaWithProcess(formulaText, codeVal, process)
          isValid = result.isValid
          resultMessage = result.message

          if (isValid) {
            process.push(`校验结果: 通过`)
          } else {
            process.push(`校验结果: 失败 - ${resultMessage}`)
          }
        } catch (error) {
          isValid = true
          resultMessage = `校验跳过: ${error.message}`
          process.push(`校验异常: ${error.message}`)
        }

        validationResultsList.value.push({
          fieldTitle: fieldTitle,
          fieldName: field,
          formula: formulaText,
          isValid,
          resultMessage,
          process,
          fieldValues: codeVal
        })
      }
    }

    if (validationResultsList.value.length > 0) {
      drawerVisible.value = true
    } else {
      VxeUI.modal.message({ content: '没有找到需要校验的字段', status: 'warning' })
    }
  } catch (error) {
    console.error('校验失败:', error)
    VxeUI.modal.message({ content: `校验失败: ${error.message}`, status: 'error' })
  } finally {
    loading.value = false
  }
}

const evaluateFormulaWithProcess = async (
  formula: string,
  codeVal: Record<string, string>,
  process: string[]
): Promise<{ isValid: boolean; message: string }> => {
  try {
    process.push('检查公式中用到的字段...')
    const fieldPattern = /\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g
    const fieldsInFormula = new Set<string>()
    let match

    while ((match = fieldPattern.exec(formula)) !== null) {
      fieldsInFormula.add(match[1])
    }

    process.push(`公式中用到的字段: ${Array.from(fieldsInFormula).join(', ')}`)

    for (const field of fieldsInFormula) {
      if (!codeVal.hasOwnProperty(field) ||
          codeVal[field] === undefined ||
          codeVal[field] === null ||
          codeVal[field] === '' ||
          codeVal[field] === 'undefined' ||
          codeVal[field] === 'null') {
        process.push(`字段 ${field} 为空，跳过校验`)
        return { isValid: true, message: `字段 ${field} 为空，跳过校验` }
      }
    }

    process.push('所有字段都有值，开始执行公式计算...')
    let processedFormula = formula

    for (const [key, value] of Object.entries(codeVal)) {
      const paramRegex = new RegExp(`\\b${key}\\b`, 'g')
      processedFormula = processedFormula.replace(paramRegex, value)
    }

    process.push(`处理后的公式: ${processedFormula}`)

    const result = eval(processedFormula)
    const resultStr = String(result)

    if (resultStr === 'true' || resultStr === 'True' || resultStr === '1' || result === true) {
      process.push(`公式计算结果: ${resultStr} (通过)`)
      return { isValid: true, message: `通过 (${resultStr})` }
    } else {
      process.push(`公式计算结果: ${resultStr} (失败)`)
      return { isValid: false, message: `不通过 (${resultStr})` }
    }
  } catch (error) {
    process.push(`公式计算失败: ${error.message}`)
    return { isValid: true, message: `校验跳过 - ${error.message}` }
  }
}

const validateInput = async (key: string) => {
  if (!validFormula.value || validFormula.value.length === 0) {
    validationResults.value[key] = 'default'
    validationMessages.value[key] = ''
    return
  }

  try {
    const formulaItems = validFormula.value
    const field = key.split('_')[1]
    
    const targetFormula = formulaItems.find((f: any) => {
      const formulaText = (f.formula || '').toString()
      const regex = new RegExp(`\\b${field}\\b`, 'gi')
      return regex.test(formulaText)
    })
    
    if (targetFormula) {
      const codeVal = await buildCodeValueMap()
      const formulaText = (targetFormula.formula || '').toString()
      const isValid = await evaluateFormula(formulaText, codeVal)
      
      if (isValid) {
        validationResults.value[key] = 'default'
        validationMessages.value[key] = ''
      } else {
        validationResults.value[key] = 'error'
        validationMessages.value[key] = targetFormula.des || `验证失败: ${formulaText}`
      }
    } else {
      validationResults.value[key] = 'default'
      validationMessages.value[key] = ''
    }
  } catch (error) {
    console.error('验证失败:', error)
    validationResults.value[key] = 'error'
    validationMessages.value[key] = '验证计算失败'
  }
}

const buildCodeValueMap = async (): Promise<Record<string, string>> => {
  const codeVal: Record<string, string> = {}
  
  for (const strKey in formData) {
    const val = formData[strKey]
    if (val !== undefined && val !== null && val !== '') {
      const parts = strKey.split('_')
      if (parts.length >= 2) {
        const field = parts[1]
        codeVal[field] = Array.isArray(val) ? val.join(',') : String(val)
      }
    }
  }
  
  return codeVal
}

const evaluateFormula = async (formula: string, codeVal: Record<string, string>): Promise<boolean> => {
  try {
    // 提取公式中用到的所有字段名（假设字段名是字母数字下划线组合）
    const fieldPattern = /\b([a-zA-Z_][a-zA-Z0-9_]*)\b/g
    const fieldsInFormula = new Set<string>()
    let match
    
    while ((match = fieldPattern.exec(formula)) !== null) {
      fieldsInFormula.add(match[1])
    }
    
    // 检查所有用到的字段是否都有值
    for (const field of fieldsInFormula) {
      // 如果字段在 codeVal 中但值为空，或者不在 codeVal 中，都认为是空
      if (!codeVal.hasOwnProperty(field) || 
          codeVal[field] === undefined || 
          codeVal[field] === null || 
          codeVal[field] === '' || 
          codeVal[field] === 'undefined' || 
          codeVal[field] === 'null') {
        return true  // 有字段为空，不进行校验，默认通过
      }
    }
    
    let processedFormula = formula
    
    for (const [key, value] of Object.entries(codeVal)) {
      const paramRegex = new RegExp(`\\b${key}\\b`, 'g')
      processedFormula = processedFormula.replace(paramRegex, value)
    }
    
    const result = eval(processedFormula)
    return Boolean(result)
  } catch (error) {
    console.error('公式计算失败:', error, '公式:', formula)
    return true  // 计算失败时也通过，避免因为计算错误导致验证失败
  }
}

const validateAllInputs = async () => {
  if (!validFormula.value || validFormula.value.length === 0) {
    return
  }
  
  try {
    const formulaItems = validFormula.value
    const codeVal = await buildCodeValueMap()
    
    validationResults.value = {}
    validationMessages.value = {}
    
    for (const strKey in formData) {
      const val = formData[strKey]
      if (val !== undefined && val !== null && val !== '') {
        const field = strKey.split('_')[1]
        const targetFormula = formulaItems.find((f: any) => {
          const formulaText = (f.formula || '').toString()
          const regex = new RegExp(`\\b${field}\\b`, 'gi')
          return regex.test(formulaText)
        })
        
        if (targetFormula) {
          const formulaText = (targetFormula.formula || '').toString()
          const isValid = await evaluateFormula(formulaText, codeVal)
          
          if (isValid) {
            validationResults.value[strKey] = 'default'
            validationMessages.value[strKey] = ''
          } else {
            validationResults.value[strKey] = 'error'
            validationMessages.value[strKey] = targetFormula.des || `验证失败: ${formulaText}`
          }
        }
      }
    }
  } catch (error) {
    console.error('全量验证失败:', error)
  }
}



</script>
<style lang="less" scoped>
.bank-report-table {
  font-family: "SimSun", "宋体", serif;
  font-size: 12px;
  color: #000;
  margin: 5px auto;
  width: 60%;
  height:80vh;
  position: relative; /* 为loading遮罩层定位 */
}

/* 加载遮罩层样式 */
.loading-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(255, 255, 255, 0.8);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 9999;
}

.loading-spinner {
  text-align: center;
}

.spinner {
  width: 40px;
  height: 40px;
  margin: 0 auto 10px;
  border: 3px solid #f3f3f3;
  border-top: 3px solid #1890ff;
  border-radius: 50%;
  animation: spin 1s linear infinite;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.loading-text {
  font-size: 14px;
  color: #1890ff;
  font-weight: bold;
}

.custom-table {
  width: 100%;
  border: 1px solid #000;
}
.custom-table .vxe-header--column,
.custom-table .vxe-body--column {
  border-right: 1px solid #000;
  border-bottom: 1px solid #000;
  padding: 5px;
}
.custom-table .vxe-cell {
  padding: 5px;
}
.content-cell {
  line-height: 1.8;
}
.table-input {
  width: 80px;
  margin: 0 2px;
}

.radio-group {
  display: inline-block;
  margin-right: 10px;
}
.checkbox-group {
  display: inline-block;
  margin-right: 10px;
}
.vxe-radio,
.vxe-checkbox {
  margin-right: 8px;
  white-space: nowrap;
}
.vxe-input--inner {
  height: 24px;
  line-height: 24px;
  padding: 0 5px;
}
.vxe-radio--label,
.vxe-checkbox--label {
  font-size: 12px;
}
.vxe-radio--icon,
.vxe-checkbox--icon {
  font-size: 12px;
}
.vxe-radio-group,
.vxe-checkbox-group {
  display: inline-block;
}
.bank-report-table {
  font-family: "SimSun", "宋体", serif;
  font-size: 12px;
  color: #000;
  margin: 5px auto;
  width: 90%;
}
.custom-table {
  width: 100%;
  border: 1px solid #000;
}
.custom-table .vxe-header--column,
.custom-table .vxe-body--column {
  border-right: 1px solid #000;
  border-bottom: 1px solid #000;
  padding: 5px;
}
.content-cell {
  line-height: 1.8;
}
.table-input {
  width: 80px;
  margin: 0 2px;
}
.radio-group {
  display: inline-block;
  margin-right: 10px;
}
eckbox-group {
  display: inline-block;
  margin-right: 10px;
}
.vxe-radio,
.vxe-checkbox {
  margin-right: 8px;
  white-space: nowrap;
}

/* 附件样式 */
.attachments {
  margin-top: 20px;
  width: 100%;
}

.attachments h4 {
  font-size: 14px;
  font-weight: bold;
  margin-bottom: 10px;
}

.attachment-table {
  width: 100%;
  border: 1px solid #000;
}

.attachment-table .vxe-header--column,
.attachment-table .vxe-body--column {
  border-right: 1px solid #000;
  border-bottom: 1px solid #000;
  padding: 5px;
}

.vxe-input,.vxe-textarea {
  border-bottom: 1px solid #333;
  text-align: center;
  margin: 5px 3px;
  padding: 0;
  border-top: none;
  border-left: none;
  border-right: none;
  background: transparent;
  line-height: 50px;
}

blockquote {
  padding: 0px 5px;
  color: black;
  cursor: pointer;
}

.input-wrapper {
  position: relative;
  display: inline-block;
}

.input-wrapper .unit {
  margin-left: 4px;
}

.input-wrapper .error-tip {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 2px;
  padding: 4px 8px;
  background: #fff2f0;
  border: 1px solid #ffccc7;
  border-radius: 4px;
  font-size: 11px;
  color: #ff4d4f;
  line-height: 1.4;
  max-width: 200px;
  word-wrap: break-word;
  z-index: 1000;
  white-space: normal;
  box-shadow: 0 2px 8px rgba(255, 77, 79, 0.15);
}

.input-wrapper .error-tip::before {
  content: '';
  position: absolute;
  top: -5px;
  left: 10px;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 5px solid #ffccc7;
}

.vxe-input.status--error .vxe-input--inner {
  border-color: #ff4d4f !important;
  background-color: #fff2f0 !important;
}

.input-wrapper .help-icon {
  display: inline-block;
  width: 16px;
  height: 16px;
  background: #1890ff;
  color: white;
  border-radius: 50%;
  text-align: center;
  line-height: 16px;
  font-size: 12px;
  font-weight: bold;
  cursor: pointer;
  margin-left: 4px;
  user-select: none;
  transition: all 0.3s;
}

.input-wrapper .help-icon:hover {
  background: #40a9ff;
  transform: scale(1.1);
}

.input-wrapper .tooltip {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 2px;
  padding: 6px 10px;
  background: #1f1f1f;
  color: white;
  border-radius: 6px;
  font-size: 12px;
  line-height: 1.5;
  max-width: 250px;
  word-wrap: break-word;
  z-index: 1001;
  white-space: normal;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.input-wrapper .tooltip::before {
  content: '';
  position: absolute;
  top: -5px;
  left: 12px;
  width: 0;
  height: 0;
  border-left: 5px solid transparent;
  border-right: 5px solid transparent;
  border-bottom: 5px solid #1f1f1f;
}

/* 校验结果抽屉样式 */
.validation-results {
  padding: 16px;
  height: 90vh;
}

.result-summary {
  display: flex;
  gap: 16px;
  margin-bottom: 16px;
  padding: 12px;
  background: #f5f5f5;
  border-radius: 8px;
}

.summary-item {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.summary-label {
  font-size: 12px;
  color: #666;
}

.summary-value {
  font-size: 16px;
  font-weight: bold;
}

.summary-value.success {
  color: #52c41a;
}

.summary-value.error {
  color: #ff4d4f;
}

.result-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 100%;
  overflow-y: auto;

}

.result-item {
  border: 1px solid #e8e8e8;
  border-radius: 8px;
  padding: 12px;
  transition: all 0.3s;
}

.result-item.success {
  border-color: #52c41a;
  background: #f6ffed;
}

.result-item.error {
  border-color: #ff4d4f;
  background: #fff2f0;
}

.result-item-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
  padding-bottom: 8px;
  border-bottom: 1px solid #e8e8e8;
}

.result-item-name {
  font-weight: bold;
  font-size: 14px;
}

.result-item-status {
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 12px;
  font-weight: bold;
}

.result-item-status.success {
  background: #f6ffed;
  color: #52c41a;
  border: 1px solid #95de64;
}

.result-item-status.error {
  background: #fff2f0;
  color: #ff4d4f;
  border: 1px solid #ffccc7;
}

.result-item-content {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.result-item-formula,
.result-item-result,
.result-item-process {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}

.result-item-formula {
  font-family: 'Courier New', monospace;
  background: #fafafa;
  padding: 8px;
  border-radius: 4px;
  border: 1px solid #e8e8e8;
}

.formula-label,
.result-label,
.formula-label,
.result-label,
.process-label,
.values-label {
  font-weight: bold;
  font-size: 12px;
  color: #666;
  min-width: 80px;
}

.formula-value,
.result-value,
.values-value {
  font-size: 12px;
  flex: 1;
}

.result-value {
  color: #333;
}

.process-content {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.process-step {
  display: flex;
  gap: 8px;
  align-items: flex-start;
  font-size: 12px;
  color: #666;
}

.step-number {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  background: #1890ff;
  color: white;
  border-radius: 50%;
  font-size: 10px;
  font-weight: bold;
  flex-shrink: 0;
}

.step-text {
  flex: 1;
}

.result-item-process {
  border-top: 1px solid #e8e8e8;
  padding-top: 8px;
}

.result-item-values {
  display: flex;
  gap: 8px;
  align-items: flex-start;
}

.values-label {
  font-weight: bold;
  font-size: 12px;
  color: #666;
  min-width: 80px;
}

.values-value {
  font-family: 'Courier New', monospace;
  font-size: 11px;
  line-height: 1.5;
  background: #fafafa;
  padding: 8px;
  border-radius: 4px;
  border: 1px solid #e8e8e8;
  overflow-x: auto;
  max-height: 200px;
  overflow-y: auto;
  flex: 1;
  white-space: pre;
  word-break: break-all;
}

/* 抽屉样式调整 */
.vxe-drawer--right {
  width: 700px !important;
}

.vxe-drawer--header {
  border-bottom: 1px solid #e8e8e8;
  padding-bottom: 12px;
}

.vxe-drawer--title {
  font-size: 16px;
  font-weight: bold;
  color: #333;
}

.vxe-drawer--body {
  padding: 16px;
  max-height: calc(100vh - 140px);
  overflow-y: auto;
}

.result-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  max-height: 500px;
  overflow-y: auto;
}

.result-list--scrolling {
  max-height: calc(100vh - 280px) !important;
}

</style>