<template>
  <div class="bank-report-table" style="height:80vh;" @click="closeAllTooltips">
    <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="checkData()">校验</vxe-button> -->
        <vxe-button status="primary" icon="vxe-icon-save" @click="saveBatch()">保存</vxe-button>
      </template>
    </vxe-toolbar>
    <vxe-table
      border
      ref="tableRef"
      show-header-overflow
      :data="tableFormData"
      :column-config="{ resizable: true }"
      :row-config="{ resizable: true }"
      class="custom-table"
      height="auto"
    >
      <vxe-column field="serialNumber" title="序号" width="80"></vxe-column>
      <vxe-column field="project" title="项目" width="200">
        <template #default="{ row }">
          <span style="font-weight: bold;size:20px">{{ row.project }}</span>
        </template>
      </vxe-column>
      <vxe-column field="content" title="内容" row-resize>
        <template #default="{ row }"> 
          <div class="content-cell">
            <template v-if="row.type === 'AttachTable'">
              <AttachTable
                :title="row.project"
                :records="row.datas"
                :fields="row.content"
                :pcode="row.code"
                :calcSum="row.calcSum"
                :showFooter="row.showFooter"
                :ref="(el) => setAttachTableRef(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>
                
                <template v-else-if="item.type === 'yesno'">
                  <vxe-radio-group v-model="formData[row.code +'_'+ item.field]">
                    <vxe-radio label="是" content="是">  
                    </vxe-radio>
                    <vxe-radio label="否" content="否"></vxe-radio>
                  </vxe-radio-group>
                </template>
                <template v-else-if="item.type === 'textarea'">
                  <vxe-textarea
                    v-model="formData[row.code +'_'+ item.field]"
                    size="mini"
                    class="table-textarea"
                    :rows="2"
                    :autosize="{ minRows: 2, maxRows: 4 }"
                  />
                </template>
                <template v-else>
                  <div class="input-wrapper" v-if="item.hasRight !== false">
                    <vxe-input
                      v-if="item.type !== 'checkbox'"
                      :type="item.type === 'date' ? 'date' : 'text'"
                      v-model="formData[row.code +'_'+ item.field]"
                      size="mini"
                      class="table-input"
                      :disabled="!item.hasRight"
                      @blur="handleInputBlur(row.code, item.field, item.matchedFormula?.formula)"
                    />
                    <vxe-checkbox-group
                      v-else-if="item.type === 'checkbox'"
                      v-model="formData[row.code +'_'+ item.field]"
                    >
                      <vxe-checkbox 
                        v-for="option in item.options || []" 
                        :key="option.value" 
                        :label="option.label" 
                        :value="option.value"
                      />
                    </vxe-checkbox-group>
                    <span
                      v-if="showHelpIcon(row.code, item.field, item)"
                      class="help-icon"
                      @click.stop="toggleTooltip(row.code, item.field)"
                      title="点击查看校验规则"
                    >
                      ?
                    </span>
                    <span
                      v-if="inputErrors[getFieldKey(row.code, item.field)]"
                      class="error-icon"
                      @click.stop="toggleErrorTooltip(row.code, item.field)"
                      title="点击查看错误详情"
                    >
                      <i class="vxe-icon-error">✗</i>
                    </span>
                    <div
                      v-if="showTooltip && hoveredKey === getFieldKey(row.code, item.field)"
                      class="tooltip"
                      @click.stop
                    >
                      {{ item.matchedFormula?.des || '暂无校验规则' }}
                    </div>
                    <div
                      v-if="showErrorTooltip && hoveredErrorKey === getFieldKey(row.code, item.field)"
                      class="error-tooltip"
                      @click.stop
                    >
                      {{ inputErrors[getFieldKey(row.code, item.field)]?.message || '未知错误' }}
                      <br v-if="inputErrors[getFieldKey(row.code, item.field)]?.formula">
                      <span v-if="inputErrors[getFieldKey(row.code, item.field)]?.formula" style="color: #ffcccc;">
                        公式: {{ inputErrors[getFieldKey(row.code, item.field)]?.formula }}
                      </span>
                      <template v-if="inputErrors[getFieldKey(row.code, item.field)]?.error">
                        <br>
                        <span style="color: #ff9999; font-size: 11px;">
                          错误: {{ inputErrors[getFieldKey(row.code, item.field)]?.error }}
                        </span>
                      </template>
                    </div>
                  </div>
                  <span v-else style="color: #999; font-style: italic;">无权限</span>
                </template>
              </template>
            </template>
          </div>
        </template>
      </vxe-column>
      <vxe-column field="remarks" title="备注" width="200">
        <template #default="{ row }"> 
            <vxe-textarea 
              :rows="row.remarks?.rows || 2" 
              v-model="formData[row.code+'_'+(row.remarks?.field || 'remarks')]"
              :disabled="!row.remarks?.hasRight"
            >
            </vxe-textarea>
        </template>
      </vxe-column>
    </vxe-table>
    
    <ValidationDrawer 
      ref="validationDrawerRef" 
      v-model="drawerVisible" 
      :tableFormData="tableFormData" 
      @validationResultClick="handleValidationResultClick"
    />
  </div>
</template>

<script lang="ts" setup>
import AttachTable from '../tableComponents/AttachTable.vue'
import ValidationDrawer from './check/ValidationDrawer.vue'
import { tableFormData } from '../../data/tb11.data';
import { ref, reactive, onMounted, nextTick, watch } from 'vue'
import { VxeUI } from 'vxe-table'
import { batchSaveOrUpdateBeforeDelete, queryRecord } from '../../record/BaosongTaskRecord.api'
import { allTplItems } from '../../tpl/BaosongTplItem.api'
import { findUserRightForTplItem } from '../../alloc/BaosongTaskAlloc.api'
import { getTblvalidFormula } from '../../tpl/BaosongDataValid.api'
import { useRoute } from 'vue-router';

const route = useRoute();
const tableRef = ref();
const tplItemMap = ref<Record<string, any>>({});
const validationDrawerRef = ref();
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
}

interface FormulaItem {
  formula: string
  des: string
  [key: string]: any
}

interface InputError {
  message: string
  formula: string
  error?: string
}

const loading = ref(false)
const formData = reactive<Record<string, any>>({});
const formValues = ref<FormData[]>([])
const userAllocItems = ref<string[]>([])
const validFormula = ref<any[]>([])
const drawerVisible = ref(false)
const showTooltip = ref(false)
const hoveredKey = ref('')
const showErrorTooltip = ref(false)
const hoveredErrorKey = ref('')
const inputErrors = ref<Record<string, InputError>>({})
const isInitialized = ref(false)

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 {
    if (queryParam.value.tplId > 0 && queryParam.value.taskId > 0) {
      userAllocItems.value = await findUserRightForTplItem({
        tplid: queryParam.value.tplId,
        taskid: queryParam.value.taskId
      })

      validFormula.value = await getTblvalidFormula({
        tplid: queryParam.value.tplId,
      })
    }
  } catch (error) {
    console.error('获取权限或验证公式失败:', error)
    VxeUI.modal.message({ content: '获取表单权限或校验规则失败，部分功能可能受限', status: 'warning' })
  }

  await setTplItemMap()
  setFormItemRight()
  await setData()
  
  isInitialized.value = true
  
  await nextTick()
  refreshHelpIcons()
})

const saveBatch = async () => {
  try {
    loading.value = true
    formValues.value = []

    // 检查必填项
    const requiredErrors: string[] = []
    tableFormData.forEach((row: any) => {
      if (row.content && Array.isArray(row.content)) {
        row.content.forEach((item: any) => {
          if (item.field && item.required && item.hasRight !== false) {
            const key = getFieldKey(row.code, item.field)
            const value = formData[key]
            if (!value || (Array.isArray(value) && value.length === 0) || value === '') {
              requiredErrors.push(`${row.project || ''} - ${item.label || item.field}`)
            }
          }
        })
      }
    })

    if (requiredErrors.length > 0) {
      VxeUI.modal.message({ 
        content: `以下必填项未填写：\n${requiredErrors.join('\n')}`, 
        status: 'error',
        duration: 5000
      })
      return
    }

    for (const strKey in formData) {
      const valData = formData[strKey]
      if (valData !== undefined && valData !== null && valData !== '') {
        const tmpAry = strKey.split("_")
        if (tmpAry.length >= 2) {
          await setFormValues(tmpAry[0], tmpAry[1], valData, 1)
        }
      }
    }

    await getAttachTableFormData();

    if (formValues.value.length > 0) {
      await batchSaveOrUpdateBeforeDelete(formValues.value)
      VxeUI.modal.message({ content: '保存成功', status: 'success' })
    } else {
      VxeUI.modal.message({ content: '没有需要保存的数据', status: 'warning' })
    }
  } catch (error: any) {
    console.error('保存失败:', error)
    VxeUI.modal.message({ 
      content: `保存失败: ${error.message || '未知错误'}`, 
      status: 'error',
      duration: 5000
    })
  } finally {
    loading.value = false
  }
}

const childAttachTableRefs = ref<Record<string, any>>({})
const setAttachTableRef = (el: any, index: string) => {
  if (el) {
    childAttachTableRefs.value[index] = el;
  }
};

const getAttachTableFormData = async () => {
  for (const pcode in childAttachTableRefs.value) {
      const child = childAttachTableRefs.value[pcode];
      if (child && typeof child.getFormData === 'function') {
          try {
            const datas = child.getFormData()
            if (datas && typeof datas === 'object') {
              for(const code in datas) {
                await setFormValues(pcode, code, datas[code], 1)
              }
            }
          } catch (error) {
            console.error(`获取附件表格 ${pcode} 数据失败:`, error)
          }
      }
  }
};

const setFormValues = async (pcode: string, code: string, valData: any, rind: number) => {
  if (valData === undefined || valData === null) return;
  
  let vals: string;
  if (Array.isArray(valData)) {
    vals = valData.filter(item => item !== null && item !== undefined && item !== '').join(',')
  } else {
    vals = String(valData).trim()
  }
  
  if (!vals) return;
  
  const 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();
    
    if (taskId <= 0 || tplid <= 0) {
      console.warn('taskId 或 tplId 无效，跳过数据加载')
      return
    }
    
    const recordData = await queryRecord({taskid: taskId, tplid: tplid})
    let valueObj: Record<string, string> = {}
    
    if (recordData && Array.isArray(recordData)) {
      for(let data of recordData) {
        const key = `${data.itempid}_${data.itemid}_${data.rind}`
        valueObj[key] = data.content || ''
      }
    }

    // 加载主表数据
    Object.keys(tplItemMap.value).forEach(strKey => {  
      const item = tplItemMap.value[strKey];  
      const { pid, itemid, formTp } = item || {}; 
      const dataVal = valueObj[`${pid}_${itemid}_1`]
      
      if (dataVal !== undefined) {
        if(formTp == 'checkbox') {
          formData[strKey] = dataVal ? dataVal.split(",").filter(Boolean) : []
        } else {
          formData[strKey] = dataVal
        }
      }
    });

    // 加载附件表格数据
    Object.keys(childAttachTableRefs.value).forEach(pcode => { 
      const child = childAttachTableRefs.value[pcode];
      if (child && typeof child.setFormData === 'function') {
        const matchingKeys = Object.keys(tplItemMap.value).filter(key => key.startsWith(pcode + '_'));  
        const matchingObjects = matchingKeys.map(key => tplItemMap.value[key]);  
        let attachTableData: Record<string, any> = {}
        
        for(let tmpData of matchingObjects) {
          const { pid, itemid, formTp, code } = tmpData || {}; 
          const dataVal = valueObj[`${pid}_${itemid}_1`]
          
          if (dataVal !== undefined) {
            if(formTp == 'checkbox') {
              attachTableData[code] = dataVal ? dataVal.split(",").filter(Boolean) : []
            } else {
              attachTableData[code] = dataVal
            }
          }
        }
        
        if (Object.keys(attachTableData).length > 0) {
          child.setFormData(attachTableData)
        }
      }
    })
  } catch (error: any) {
    console.error('加载数据失败:', error)
    VxeUI.modal.message({ 
      content: `加载数据失败: ${error.message || '未知错误'}`, 
      status: 'error',
      duration: 3000
    })
  } finally {
    loading.value = false
  }
}

async function setTplItemMap() {
  try {
    const tplid = queryParam.value.tplId
    if (tplid <= 0) {
      console.warn('tplId 无效，跳过加载模板项')
      return
    }
    
    const tplItem = await allTplItems({
      tplid: tplid,
    })

    tplItemMap.value = {}
    tplItem.forEach(item => {
      let strKey = item.pcode + "_" + item.xmlcode;
      tplItemMap.value[strKey] = {
        pid: item.pid, 
        itemid: item.id, 
        formTp: item.formTp, 
        code: item.xmlcode,
        label: item.label
      };
    })
    
    console.log('tplItemMap 加载完成，数量:', Object.keys(tplItemMap.value).length)
  } catch (error: any) {
    console.error('加载模板项失败:', error)
    VxeUI.modal.message({ 
      content: `加载模板配置失败: ${error.message || '未知错误'}`, 
      status: 'error',
      duration: 3000
    })
  }
}

const checkData = () => {
  drawerVisible.value = true
  validationDrawerRef.value?.setValidateData(validFormula.value, formData)
}

const handleInputBlur = (rowCode: string, field: string, formula?: string) => {
  if (!formula) return;
  
  const key = getFieldKey(rowCode, field);
  const value = formData[key];
  
  if (!value || value === '') {
    delete inputErrors.value[key];
    return;
  }
  
  validateFieldFormula(rowCode, field, formula);
};

const validateFieldFormula = (rowCode: string, field: string, formula: string) => {
  const key = getFieldKey(rowCode, field);
  
  try {
    const expression = buildExpression(formula, rowCode);
    const isValid = eval(expression);
    if (!isValid) {
      inputErrors.value[key] = {
        message: "公式校验失败，请检查填写内容",
        formula
      };
    } else {
      delete inputErrors.value[key];
    }
  } catch (error: any) {
    inputErrors.value[key] = {
      message: "公式校验失败，请检查填写内容",
      formula,
      error: error.message
    };
  }
};

const buildExpression = (formula: string, rowCode: string): string => {
  const fieldNames = formula.match(/\b[A-Za-z][A-Za-z0-9_]*\b/g) || [];
  const uniqueFields = [...new Set(fieldNames.filter(f => 
    !['and', 'or', 'not', 'equal', 'less', 'greater', 'if', 'else', 'true', 'false']
      .includes(f.toLowerCase())
  ))];
  
  uniqueFields.sort((a, b) => b.length - a.length);
  
  let expression = formula;
  for (const fieldName of uniqueFields) {
    const key = getFieldKey(rowCode, fieldName);
    const value = formData[key];
    if (value !== undefined && value !== null && value !== '') {
      const numValue = Number(value);
      if (!isNaN(numValue)) {
        expression = expression.replace(
          new RegExp(`\\b${fieldName}\\b`, 'g'), 
          numValue.toString()
        );
      }
    }
  }
  
  return expression;
};

const toggleTooltip = (rowCode: string, field: string) => {
  const key = getFieldKey(rowCode, field);
  if (hoveredKey.value === key) {
    showTooltip.value = false;
    hoveredKey.value = '';
  } else {
    showTooltip.value = true;
    hoveredKey.value = key;
    showErrorTooltip.value = false;
    hoveredErrorKey.value = '';
  }
};

const toggleErrorTooltip = (rowCode: string, field: string) => {
  const key = getFieldKey(rowCode, field);
  if (hoveredErrorKey.value === key) {
    showErrorTooltip.value = false;
    hoveredErrorKey.value = '';
  } else {
    showErrorTooltip.value = true;
    hoveredErrorKey.value = key;
    showTooltip.value = false;
    hoveredKey.value = '';
  }
};

const closeAllTooltips = () => {
  showTooltip.value = false;
  hoveredKey.value = '';
  showErrorTooltip.value = false;
  hoveredErrorKey.value = '';
};

const showHelpIcon = (rowCode: string, field: string, item: any): boolean => {
  if (!item || item.hasRight === false) {
    return false;
  }
  
  if (item.hasValidFormula !== undefined) {
    return item.hasValidFormula === true;
  }
  
  const key = getFieldKey(rowCode, field);
  const hasRight = userAllocItems.value.includes(key);
  
  if (!hasRight) return false;
  
  const formulaResult = findEarliestFormulaForField(validFormula.value, field);
  return !!formulaResult.formula;
};

const setFormItemRight = () => {
  console.log('开始设置表单权限...')
  console.log('userAllocItems 数量:', userAllocItems.value?.length || 0)
  console.log('validFormula 数量:', validFormula.value?.length || 0)
  
  if (!tableFormData || !Array.isArray(tableFormData)) {
    console.warn('tableFormData 不存在或不是数组')
    return
  }
  
  tableFormData.forEach((row: any) => {
    if (row.content && Array.isArray(row.content)) {
      row.content.forEach((item: any) => {
        if (item && item.field) {
          const key = getFieldKey(row.code, item.field)
          item.hasRight = userAllocItems.value.includes(key)
          
          if (item.hasRight) {
            const formulaResult = findEarliestFormulaForField(validFormula.value, item.field)
            
            item.hasValidFormula = !!formulaResult.formula
            item.matchedFormula = formulaResult.formula || null
          } else {
            item.hasValidFormula = false
            item.matchedFormula = null
          }
        }
      })
    }
    
    // 设置备注权限
    if (row.remarks && row.remarks.field) {
      const remarksKey = getFieldKey(row.code, row.remarks.field)
      row.remarks.hasRight = userAllocItems.value.includes(remarksKey)
    }
  })
  
  console.log('表单权限设置完成')
}

const findEarliestFormulaForField = (
  formulas: FormulaItem[], 
  field: string
): { formula: FormulaItem | null, index: number } => {
  let result = { formula: null, index: Infinity }
  
  if (!formulas || !Array.isArray(formulas)) {
    return result
  }
  
  formulas.forEach((f: FormulaItem, idx: number) => {
    if (f && f.formula) {
      const text = f.formula
      const escapedField = field.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
      const regex = new RegExp(`\\b${escapedField}\\b(?!\\w)`, 'g')
      const match = regex.exec(text)
      
      if (match && match.index < result.index) {
        result = { formula: f, index: match.index }
      }
    }
  })
  
  return result
}

const refreshHelpIcons = () => {
  console.log('刷新帮助图标...')
  if (!tableFormData || !Array.isArray(tableFormData)) return
  
  tableFormData.forEach((row: any) => {
    if (row.content && Array.isArray(row.content)) {
      row.content.forEach((item: any) => {
        if (item && item.field) {
          const key = getFieldKey(row.code, item.field)
          const hasRight = userAllocItems.value.includes(key)
          
          if (hasRight) {
            const formulaResult = findEarliestFormulaForField(validFormula.value, item.field)
            item.hasValidFormula = !!formulaResult.formula
            item.matchedFormula = formulaResult.formula || null
          } else {
            item.hasValidFormula = false
            item.matchedFormula = null
          }
        }
      })
    }
  })
}

const getFieldKey = (pcode: string | undefined, field: string): string => {
  return pcode ? `${pcode}_${field}` : field
}

const handleValidationResultClick = (result: any) => {
  if (!result) return
  
  const message = `字段 ${result.field || '未知'} 的校验结果: ${result.isValid ? '通过' : '失败'}`
  const status = result.isValid ? 'success' : 'error'
  
  VxeUI.modal.message({ content: message, status })
}

// 监听数据变化，自动校验
watch(formData, (newVal, oldVal) => {
  if (!isInitialized.value) return
  
  // 找到变化的字段
  const changedKeys: string[] = []
  Object.keys(newVal).forEach(key => {
    if (newVal[key] !== oldVal[key]) {
      changedKeys.push(key)
    }
  })
  
  // 对新字段进行校验
  changedKeys.forEach(key => {
    const [rowCode, field] = key.split('_')
    if (rowCode && field) {
      // 查找对应的校验规则
      const row = tableFormData.find((r: any) => r.code === rowCode)
      if (row && row.content) {
        const item = row.content.find((c: any) => c.field === field)
        if (item && item.matchedFormula?.formula) {
          handleInputBlur(rowCode, field, item.matchedFormula.formula)
        }
      }
    }
  })
}, { deep: true })
</script>

<style lang="less" scoped>
.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: 120px;
  margin: 0 2px;
}

.table-textarea {
  width: 200px;
  margin: 0 2px;
}

.vxe-input {
  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: 1.5;
}

.vxe-textarea {
  font-size: 12px;
}

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

.help-icon {
  margin-left: 5px;
  cursor: pointer;
  color: #1890ff;
  font-weight: bold;
  font-size: 14px;
  display: inline-block;
  width: 20px;
  height: 20px;
  line-height: 20px;
  text-align: center;
  background: #e6f7ff;
  border-radius: 50%;
  transition: all 0.3s;
  opacity: 0;
  animation: fadeIn 0.5s forwards;
  animation-delay: 0.3s;
  
  &:hover {
    background: #bae7ff;
    transform: scale(1.1);
  }
}

@keyframes fadeIn {
  from {
    opacity: 0;
    transform: scale(0.8);
  }
  to {
    opacity: 1;
    transform: scale(1);
  }
}

.error-icon {
  margin-left: 5px;
  cursor: pointer;
  color: #ff4d4f;
  font-size: 16px;
  display: inline-block;
  width: 20px;
  height: 20px;
  line-height: 20px;
  text-align: center;
  transition: all 0.3s;
  
  &:hover {
    transform: scale(1.1);
  }
}

.tooltip, .error-tooltip {
  position: absolute;
  top: 100%;
  left: 0;
  margin-top: 5px;
  padding: 10px;
  font-size: 12px;
  border-radius: 4px;
  z-index: 1000;
  white-space: pre-wrap;
  max-width: 300px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
  pointer-events: none;
}

.tooltip {
  background: #333;
  color: #fff;
  
  &::before {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 10px;
    border-width: 5px;
    border-style: solid;
    border-color: transparent transparent #333 transparent;
  }
}

.error-tooltip {
  background: #8b0000;
  color: #fff;
  
  &::before {
    content: '';
    position: absolute;
    bottom: 100%;
    left: 10px;
    border-width: 5px;
    border-style: solid;
    border-color: transparent transparent #8b0000 transparent;
  }
}

// 添加必填项标识
.input-wrapper.required::before {
  content: '*';
  color: #ff4d4f;
  position: absolute;
  left: -8px;
  top: 0;
  font-size: 14px;
}
</style>