<script setup lang="ts">
import type { FieldType } from 'vant'
import type { Numeric } from 'vant/es/utils'
import ImageUploader from '@af-mobile-client-vue3/components/core/ImageUploader/index.vue'
import AdaptiveSignatureField from '@af-mobile-client-vue3/components/core/Signature/AdaptiveSignatureField.vue'
import XDatePicker from '@af-mobile-client-vue3/components/core/XDatePicker/index.vue'
import XGridDropOption from '@af-mobile-client-vue3/components/core/XGridDropOption/index.vue'
import XMultiSelect from '@af-mobile-client-vue3/components/core/XMultiSelect/index.vue'
import XSelect from '@af-mobile-client-vue3/components/core/XSelect/index.vue'
import XLocationPicker from '@af-mobile-client-vue3/components/data/XOlMap/XLocationPicker/index.vue'
import { createSelectValueTypeHandler } from '@af-mobile-client-vue3/plugins/selectValueTypeHelper'
import { getConfigByNameAsync, runLogic } from '@af-mobile-client-vue3/services/api/common'
import { post } from '@af-mobile-client-vue3/services/restTools'
import { searchToListOption, searchToOption } from '@af-mobile-client-vue3/services/v3Api'
import { useUserStore } from '@af-mobile-client-vue3/stores/modules/user'
import { getDict } from '@af-mobile-client-vue3/utils/dictUtil'
import { mobileUtil } from '@af-mobile-client-vue3/utils/mobileUtil'
import { executeStrFunctionByContext } from '@af-mobile-client-vue3/utils/runEvalFunction'
import * as util from '@af-mobile-client-vue3/utils/util'
import { areaList } from '@vant/area-data'
import dayjs from 'dayjs/esm/index'
import { debounce } from 'lodash-es'
import {
  showToast,
  Area as VanArea,
  Button as VanButton,
  Calendar as VanCalendar,
  Cascader as VanCascader,
  Checkbox as VanCheckbox,
  CheckboxGroup as vanCheckboxGroup,
  Field as VanField,
  Picker as VanPicker,
  Popup as VanPopup,
  Radio as VanRadio,
  RadioGroup as VanRadioGroup,
  Rate as VanRate,
  Slider as VanSlider,
  Stepper as VanStepper,
  Switch as VanSwitch,
  TimePicker as VanTimePicker,
} from 'vant'
import {
  computed,
  getCurrentInstance,
  nextTick,
  onBeforeMount,
  onBeforeUnmount,
  ref,
  watch,
} from 'vue'

const props = withDefaults(defineProps<{
  attr?: Record<string, any>
  form?: object
  // 整表只读：来自 XForm，统一控制交互
  formReadonly?: boolean
  datePickerFilter?: (type: string, val: string) => boolean
  datePickerFormatter?: (type: string, val: string) => string
  mode?: string
  serviceName?: string
  // 调用logic获取数据源的追加参数
  getDataParams?: object
  disabled?: boolean
  rules?: object
  // 用 defineModel 替代 modelValue/emit
  modelValue?: string | number | boolean | any[] | Record<string, any>
  showLabel?: boolean
  // radio/checkbox/select/mul-select 选项数据结构
  columnsField?: Record<string, any>
  isAsyncUpload?: boolean
  labelAlign?: string
  inputAlign?: string
}>(), {
  attr: undefined,
  form: undefined,
  formReadonly: false,
  datePickerFilter: () => true,
  datePickerFormatter: (type, val) => val,
  mode: '查询',
  serviceName: undefined,
  getDataParams: undefined,
  disabled: false,
  rules: () => ({}),
  modelValue: undefined,
  showLabel: true,
  columnsField: () => ({ text: 'label', value: 'value' }),
  isAsyncUpload: false,
  labelAlign: undefined,
  inputAlign: undefined,
})

const emits = defineEmits(['setForm', 'xFormItemEmitFunc', 'scanCodeOrNfc', 'validateError', 'photoQualityChange'])

// 用 defineModel 替代 modelValue/emit
const modelData = defineModel<string | number | boolean | any[] | Record<string, any>>()
const fileList = ref<Array<any>>()

// 获取字典
interface OptionItem {
  label: string
  value: any
  children?: OptionItem[]
}

// 判断并初始化防抖函数
let debouncedUserLinkFunc: (() => void) | null = null
let debouncedDepLinkFunc: (() => void) | null = null
let debouncedUpdateOptions: (() => void) | null = null

const selectValueTypeHandler = createSelectValueTypeHandler()

const { attr, form, mode, serviceName, getDataParams, columnsField } = props
const calendarShow = ref(false)
const option = ref([])
const pickerValue = ref(undefined)
const timePickerValue = ref(undefined)
const area = ref<any>(undefined)
const showPicker = ref(false)
const showTimePicker = ref(false)
const showArea = ref(false)
const errorMessage = ref('')
const showTreeSelect = ref(false)
const treeValue = ref('')
// 懒加载 最后检索版本
const lastFetchId = ref(0)
const customizeReadOnly = ref(false)

// 登录信息 (可以在配置的动态函数中使用 this.setupState 获取到当前组件内的全部函数和变量 例：this.setupState.userState)
const userState = useUserStore().getLogin()
const currUser = computed(() => userState.f.resources.id)
const userInfo = computed(() => ({
  orgId: userState.f.resources.orgid,
  userId: userState.f.resources.id,
}))

// 是否展示当前项
const showItem = ref(true)

// 当前组件实例（不推荐使用，可能会在后续的版本更迭中调整，暂时用来绑定函数的上下文）

// 配置中心->表单项变更触发函数
async function dataChangeFunc() {
  if (attr.dataChangeFunc) {
    await executeStrFunctionByContext(getCurrentInstance(), attr.dataChangeFunc, [props.form, (formData: any) => emits('setForm', formData), attr, util, mode, runLogic, getConfigByNameAsync, userState.f.resources, dayjs, fileList, getCurrentInstance()])
  }
}
const dataChangeFuncdebounce = debounce(dataChangeFunc, 300)
// 配置中心->表单项展示函数
async function showFormItemFunc() {
  if (attr.showFormItemFunc) {
    const obj = await executeStrFunctionByContext(getCurrentInstance(), attr.showFormItemFunc, [form, attr, null, mode])
    // 判断是 bool 还是  obj  兼容
    if (typeof obj === 'boolean') {
      showItem.value = obj
    }
    else if (obj && typeof obj === 'object') {
      // obj 是一个对象，并且不是数组
      if (Object.prototype.hasOwnProperty.call(obj, 'show')) {
        showItem.value = obj?.show
      }
      if (Object.prototype.hasOwnProperty.call(obj, 'readOnly')) {
        customizeReadOnly.value = obj?.readOnly
      }
    }
  }
}
const showFormItemFuncdebounce = debounce(showFormItemFunc, 300)
/**
 * 检测是否传入了有效的值
 * @returns any
 */
function checkModel(val = props.modelValue) {
  if (val === null || val === undefined || val === '')
    return false
  if (Array.isArray(val))
    return val.length > 0
  return true
}
/**
 * 获取表单项的默认值
 * @returns any
 */
function getDefaultValue() {
  const val = props.modelValue
  if (checkModel(val)) {
    return val
  }

  // 根据类型获取默认值
  const getDefaultByType = () => {
    const def = mode !== '查询' ? attr.formDefault : attr.queryFormDefault

    if (['treeSelect', 'select', 'checkbox'].includes(attr.type) && ['curOrgId', 'curDepId', 'curUserId'].includes(def)) {
      if (def === 'curOrgId') {
        if (attr.type === 'treeSelect') {
          treeValue.value = userState.f.resources.orgs
        }
        return attr.type === 'select' ? userState.f.resources.orgid : [userState.f.resources.orgid]
      }
      if (def === 'curDepId') {
        if (attr.type === 'treeSelect') {
          treeValue.value = userState.f.resources.deps
        }
        return attr.type === 'select' ? userState.f.resources.depids : [userState.f.resources.depids]
      }
      if (def === 'curUserId') {
        if (attr.type === 'treeSelect') {
          treeValue.value = userState.f.resources.name
        }
        return attr.type === 'select' ? userState.f.resources.id : [userState.f.resources.id]
      }
    }

    // 数组类型默认值
    const arrayTypes = ['uploader', 'checkbox', 'file', 'area', 'image', 'treeSelect']
    if (arrayTypes.includes(attr.type)) {
      return def !== undefined ? def : []
    }

    // 特殊类型默认值
    const specialDefaults = {
      switch: false,
      stepper: 1,
      addressSearch: val,
    }

    if (specialDefaults[attr.type] !== undefined) {
      return specialDefaults[attr.type]
    }

    // 说明：让初始化/查询默认值同样遵循配置的格式显示
    const dateTypes = ['rangePicker', 'yearPicker', 'monthPicker', 'yearRangePicker', 'monthRangePicker', 'datePicker', 'timePicker']
    if (dateTypes.includes(attr.type)) {
      return getDateRange({
        type: attr.type,
        formDefault: attr.formDefault ?? '',
        queryFormDefault: attr.queryFormDefault ?? '',
        queryType: attr.queryType,
        queryValueFormat: attr.queryValueFormat,
        name: attr.name ?? '',
      }) ?? []
    }

    // 其他类型（字符串、数字等）
    return def ?? ''
  }

  return getDefaultByType()
}

// 初始化日期组件初始值，组件自定义格式显示值和实际值（日期相关初始化都在此函数中操作）
function getDateRange({
  type,
  formDefault: defaultValue,
  queryFormDefault,
  queryType,
  queryValueFormat: defaultFormat,
  name,
}: {
  type: string
  formDefault: string
  queryFormDefault: string
  queryType?: string
  queryValueFormat?: string
  name: string
}): string | [string, string] | undefined {
  const formatMap: Record<string, string> = {
    yearPicker: 'YYYY',
    yearRangePicker: 'YYYY',
    monthPicker: 'YYYY-MM',
    monthRangePicker: 'YYYY-MM',
    datePicker: 'YYYY-MM-DD HH:mm:ss',
    rangePicker: 'YYYY-MM-DD HH:mm:ss',
  }
  if (mode) {
    const preferFormat = defaultFormat
    const format = preferFormat || formatMap[type]
    const val = mode === '查询' ? queryFormDefault : defaultValue
    let start: string, end: string
    switch (val) {
      case 'curYear':
        start = dayjs().startOf('year').format(format)
        end = dayjs().endOf('year').format(format)
        break
      case 'curMonth':
        start = dayjs().startOf('month').format(format)
        end = dayjs().endOf('month').format(format)
        break
      case 'curDay':
        start = dayjs().startOf('day').format(format)
        end = dayjs().endOf('day').format(format)
        break
      case 'curTime':
        start = dayjs().format(format)
        end = dayjs().format(format)
        break
      default:
        return undefined
    }
    if (['monthPicker', 'yearPicker', 'datePicker'].includes(type)) {
      if (mode !== '查询') {
        if (queryType === 'BETWEEN') {
          return [start, end]
        }
        if (name.includes('开始') || name.includes('起始')) {
          return start
        }
        else {
          return end
        }
      }
      else {
        return start
      }
    }
    // rangePicker组件表单显示的值
    if (mode === '查询' && type === 'rangePicker') {
      pickerValue.value = `${start} ~ ${end}`
    }
    return mode !== '查询' ? start : [start, end]
  }
  else {
    return undefined
  }
}

// 监听 props.form 的变化
const stopWatchForm = watch(
  () => props.form,
  (newVal, oldVal) => {
    // 如果是从函数获取 options
    if (props.attr.keyName && (props.attr.keyName.toString().includes('async ') || props.attr.keyName.toString().includes('function'))) {
      debouncedUpdateOptions()
    }
    if (props.attr.showFormItemFunc) {
      showFormItemFuncdebounce()
    }
  },
  { deep: true },
)

// 监听 modelData 的变化，调用 dataChangeFunc
const stopWatchModelData = watch(
  () => modelData.value,
  (newVal, oldVal) => {
    // 避免初始化时的调用
    if (newVal !== oldVal) {
      dataChangeFuncdebounce()
    }
  },
  { deep: true },
)

// 监听 option.value 的变化
const stopWatchOption = watch(
  () => option.value,
  (newOption) => {
    if (attr.type === 'treeSelect' && newOption && newOption.length > 0) {
      // 你可以在这里调用 findOptionInTree 函数来查找默认值对应的 label
      const result = findOptionInTree(option.value, modelData.value)
      if (attr.type === 'treeSelect' && result)
        treeValue.value = result.label
    }
  },
)

function updateFile(...args) {
  let files, originalFiles

  if (args.length === 3) {
    [files, , originalFiles] = args
  }
  else if (args.length === 2) {
    [files, originalFiles] = args
  }

  modelData.value = files
  fileList.value = originalFiles
  emitFunc('filesChange', originalFiles, attr)
}

function signatureComplete(args) {
  modelData.value = props.isAsyncUpload ? [args.data.photo_name] : args.data.id
  fileList.value = args.data
}

// 获取文件上传的验证规则（合并 XForm 传递的 rules 和本地必填验证）
function getFileUploadRules() {
  const rules: any[] = []

  // 从 XForm 传递的 rules 中获取该字段的验证规则
  if (props.rules && props.rules[attr.model]) {
    rules.push(...props.rules[attr.model])
  }

  // 如果 XForm 中没有必填规则，则添加本地必填验证
  const isRequired = attr.rule?.required === 'true'
  const hasRequiredRule = rules.some(rule => rule.required === true)

  if (isRequired && !hasRequiredRule) {
    rules.push({
      required: true,
      message: `请上传${attr.name}`,
      validator: (value: any) => {
        if (!value || (Array.isArray(value) && value.length === 0)) {
          return false
        }
        return true
      },
    })
  }

  return rules
}

// 是否只读
const readonly = computed(() => {
  return props.formReadonly || attr.addOrEdit === 'readonly' || mode === '预览' || customizeReadOnly.value
})

// 表单校验的类型校验
function formTypeCheck(attr, value) {
  if (readonly.value)
    return
  if (mode === '查询' || mode === '预览')
    return
  // if (!attr.rule || !attr.rule.required || attr.rule.required === 'false')
  //   return
  let error = ''
  switch (attr.rule.type) {
    case 'string':
      if (value.length === 0) {
        error = `请输入${attr.name}`
      }
      break
    case 'number':
      if (!/^[+-]?(?:\d+(?:\.\d*)?|\.\d+)$/.test(value)) {
        error = `${attr.name}必须为数字`
      }
      break
    case 'boolean':
    case 'array':
    case 'regexp':
      if (value) {
        error = ''
      }
      break
    case 'integer':
      if (!/^-?\d+$/.test(value)) {
        error = `${attr.name}必须为整数`
      }
      break
    case 'float':
      if (!/^-?\d+\.\d+$/.test(value)) {
        error = `${attr.name}必须为小数`
      }
      break
    case 'email':
      if (!/^[\w.%+-]+@[a-z0-9.-]+\.[a-z]{2,}$/i.test(value)) {
        error = `请输入正确的邮箱地址`
      }
      break
    case 'idNumber':
      if (!/^(?:\d{15}|\d{17}[0-9X])$/.test(value)) {
        error = `请输入正确的身份证号码`
      }
      break
    case 'userPhone':
      if (!/^1[3-9]\d{9}$/.test(value)) {
        error = `请输入正确的手机号码`
      }
      break
    case 'landlineNumber':
      if (!/^0\d{2,3}[-\s]?\d{7,8}$/.test(value)) {
        error = `请输入正确的座机号码`
      }
      break
    case 'greaterThanZero':
      if (!/^(?:[1-9]\d*(?:\.\d*)?|\.\d+)(?:e[+-]?\d+)?$/i.test(value)) {
        error = `请输入一个大于0的数字`
      }
      break
    case 'greaterThanOrEqualZero':
      if (!/^(?:\d+|\d*\.\d+)$/.test(value)) {
        error = `请输入一个大于等于0的数字`
      }
      break
    case 'stringLength':
      if (!(value.length >= attr.rule.minLen && value.length < attr.rule.maxLen)) {
        error = `长度必须在${attr.rule.minLen}~${attr.rule.maxLen}之间`
      }
      break
    case 'customJs':
      // eslint-disable-next-line no-case-declarations
      const funcStr = attr.rule.customValidatorFunc
      // 输入的数据是否符合条件

      // const status = ref(true)
      // 提取函数体部分
      // eslint-disable-next-line no-case-declarations
      const funcBodyMatch = funcStr.match(/function\s*\(.*?\)\s*\{([\s\S]*)\}/)
      if (!funcBodyMatch)
        throw new Error('自定义校验函数不合法')
      // eslint-disable-next-line no-case-declarations
      const funcBody = funcBodyMatch[1].trim() // 提取函数体
      // 使用 new Function 创建函数
      // eslint-disable-next-line no-new-func,no-case-declarations
      const customValidatorFunc = new Function('rule', 'value', 'callback', 'form', 'attr', 'util', funcBody)
      // 定义 callback 函数
      // eslint-disable-next-line no-case-declarations
      const callback = (errorMsg) => {
        if (errorMsg) {
          error = `${errorMsg}`
          // status.value = false // 表示有错误发生
        }
      }
      // 调用自定义校验函数
      customValidatorFunc(
        attr.rule,
        value,
        callback,
        form,
        attr,
        {}, // util 对象（可以根据需要传递）
      )
      // if (!status.value)
      //   return
      break
    default:
      error = ''
      break
  }

  errorMessage.value = error
  emits('validateError', attr.model, errorMessage.value)
}

onBeforeMount(() => {
  init()
  modelData.value = getDefaultValue()
  showFormItemFunc()
  dataChangeFunc()
  if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动人员'))
    debouncedUserLinkFunc = debounce(() => updateResOptions('人员'), 200)

  if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString().endsWith(']联动部门'))
    debouncedDepLinkFunc = debounce(() => updateResOptions('部门'), 200)

  if (attr.keyName && (attr?.keyName?.toString().indexOf('async ') !== -1 || attr?.keyName?.toString()?.indexOf('function') !== -1)) {
    debouncedUpdateOptions = debounce(updateOptions, 200)
  }
})
// 是否展示表单左侧label文字
const labelData = computed(() => {
  return props.showLabel ? attr.name : null
})
// 是否展示表单左侧label文字
const labelAlign = computed(() => {
  return props.labelAlign || attr.labelAlign || 'left'
})

// 判断是否显示空提示（只读且值为空）
const showEmptyTip = computed(() => {
  if ((attr.type === 'image' || attr.type === 'file') && props.formReadonly) {
    const value = modelData.value
    return !value || (Array.isArray(value) && value.length === 0)
  }
  return false
})

// 提示内容
const placeholder = computed(() => {
  if (attr.addOrEdit === 'readonly' || mode === '预览' || props.formReadonly) {
    // 根据类型返回更具体的空状态提示
    if (attr.type === 'image') {
      return '暂无图片'
    }
    else if (attr.type === 'file') {
      return '暂无文件'
    }
    return '暂无内容'
  }
  else
    if (attr.placeholder) {
      return attr.placeholder
    }
    else {
      switch (attr.type) {
        case 'datePicker':
        case 'timePicker':
        case 'rangePicker':
        case 'radio':
        case 'select':
        case 'treeSelect':
        case 'area':
        case 'citySelect':
        case 'picker':
          return `请选择${attr.name}`
        case 'addressSearch':
        case 'input':
        case 'textarea':
        case 'intervalPicker':
          return `请输入${attr.name}`
        default:
          return `请选择${attr.name}`
      }
    }
})

const formatDate = date => `${date.getFullYear()}-${date.getMonth() + 1}-${date.getDate()}`

function onCalendarConfirm(values) {
  modelData.value = [formatDate(values[0]), formatDate(values[1])]
  pickerValue.value = `${formatDate(values[0])} ~ ${formatDate(values[1])}`
  calendarShow.value = false
}

// js 函数作为数据源
async function updateOptions() {
  if (attr.keyName && (attr.keyName.toString().includes('async ') || attr.keyName.toString().includes('function '))) {
    const res = await executeStrFunctionByContext(getCurrentInstance(), attr.keyName, [props.form, runLogic, props.mode, getConfigByNameAsync, post, userState.f.resources])
    option.value = selectValueTypeHandler.processOptions(res, attr.selectValueType)
  }
}

function init() {
  if (attr.keyName && typeof attr.keyName === 'string') {
    if (attr.keyName && attr.keyName.includes('logic@')) {
      getData({}, (res) => {
        option.value = selectValueTypeHandler.processOptions(res, attr.selectValueType)
        initRadioValue()
      })
    }
    else if (attr.keyName && attr.keyName.includes('config@')) {
      const configName = attr.keyName.substring(7)
      getDict(configName, (result) => {
        if (result)
          option.value = selectValueTypeHandler.processOptions(result, attr.selectValueType)
      }, serviceName)
    }
    else if (attr.keyName && attr.keyName.includes('search@')) {
      let source = attr.keyName.substring(7)
      const userid = currUser.value
      let roleName = 'roleName'
      if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
        const startIndex = source.indexOf('[') + 1
        const endIndex = source.indexOf(']', startIndex)
        roleName = source.substring(startIndex, endIndex)
        source = '根据角色获取人员'
      }
      const searchData = { source, userid, roleName }
      if (source.startsWith('根据表单项[') && source.endsWith(']联动人员'))
        updateResOptions('人员')
      else if (source.startsWith('根据表单项[') && source.endsWith(']联动部门'))
        updateResOptions('部门')
      else if (attr.type === 'select' || attr.type === 'checkbox')
        searchToListOption(searchData, res => getDataCallback(res))
      else
        searchToOption(searchData, res => getDataCallback(res))
    }
    else if (attr.keyName.toString().includes('async ') || attr.keyName.toString().includes('function ')) {
      updateOptions()
    }
    else {
      initRadioValue()
    }
  }
  else if (attr.keys && Array.isArray(attr.keys)) {
    option.value = attr.keys
    if (attr.type === 'radio')
      initRadioValue()
  }
}

// 根据selectValueType预处理options数据
function processOptionsForValueType(options) {
  return selectValueTypeHandler.processOptions(options, attr.selectValueType)
}

function getDataCallback(res) {
  // 预处理options数据
  option.value = processOptionsForValueType(res)
  if (attr.type === 'radio')
    initRadioValue()
}

async function updateResOptions(type) {
  if (attr?.keyName?.toString()?.startsWith('search@根据表单项[') && attr?.keyName?.toString()?.endsWith(`]联动${type}`)) {
    const searchData = { source: `获取${type}`, userid: currUser.value }
    const startIndex = attr.keyName.indexOf('[') + 1
    const endIndex = attr.keyName.indexOf(']', startIndex)
    const formModel = attr.keyName.substring(startIndex, endIndex).replace('.', '_')
    const formModelData = form[formModel]
    if (formModel?.length && formModelData?.length) {
      await searchToListOption(searchData, (res) => {
        getDataCallback(res.filter((h) => {
          return formModelData['0'] === h.f_organization_id || formModelData['0'] === h.f_department_id || formModelData['0'] === h.parentid
          // if (formModel.indexOf('org') > -1) {
          //   return formModelData?.includes(h.orgid || h.f_organization_id || h.parentid)
          // } else {
          //   return formModelData?.includes(h?.parentid)
          // }
        }))
      })
    }
  }
}

function initRadioValue() {
  if ((mode === '新增' || mode === '修改') && attr.type === 'radio' && !props.modelValue) {
    if (attr.keys && attr.keys.length > 0)
      modelData.value = attr.keys[0].value
    else if (option.value && option.value.length > 0)
      modelData.value = option.value[0].value
  }
}

function getData(value, callback) {
  if (value !== '') {
    const logicName = attr.keyName
    const logic = logicName.substring(6)
    // 调用logic前设置参数
    if (getDataParams && getDataParams[attr.model])
      Object.assign(value, getDataParams[attr.model])
    Object.assign(value, userInfo.value)
    runLogic(logic, value, serviceName).then((res) => {
      callback(res)
    })
  }
}

// 已废弃 不进行维护
function onPickerConfirm({ selectedOptions }) {
  showPicker.value = false
  modelData.value = selectedOptions[0].text
}

// 已废弃 不进行维护
function onTimePickerConfirm({ selectedValues }) {
  showTimePicker.value = false
  timePickerValue.value = selectedValues.join(':')
  modelData.value = timePickerValue.value
}

// 没人用到本次先不动。后续需要看这个组件需要怎么使用
function onAreaConfirm({ selectedOptions }) {
  area.value = `${selectedOptions[0].text}-${selectedOptions[1].text}-${selectedOptions[2].text}`
  showArea.value = false
  modelData.value = [{
    province: selectedOptions[0].text,
    city: selectedOptions[1].text,
    district: selectedOptions[2].text,
  }]
}

const showAddressPicker = ref(false)
const addressValue = ref('')

// XLocationPicker 默认加载的中心点
const defaultMapCenter = computed(() => {
  const lonLat = form[`${attr.model}_lon_lat`] || form[`${attr.model}_lng_lat`]
  if (lonLat && typeof lonLat === 'string' && lonLat.includes(',')) {
    const [lon, lat] = lonLat.split(',').map(Number)
    if (!Number.isNaN(lon) && !Number.isNaN(lat)) {
      return [lon, lat] as [number, number]
    }
  }
  return undefined
})

// 处理地址选择器确认
function handleAddressConfirm(location) {
  // 构造新的数据格式
  const formData = {
    [`${attr.model}_lon_lat`]: `${location.longitude},${location.latitude}`,
    [`${attr.model}_lng_lat`]: `${location.longitude},${location.latitude}`,
    [attr.model]: location.address,
  }
  // 更新表单数据
  emits('setForm', formData)
  showAddressPicker.value = false
}

// 重置方法，供父组件调用
function reset() {
  modelData.value = getDefaultValue()
  errorMessage.value = ''
  treeValue.value = null
  area.value = null
  pickerValue.value = null
}

defineExpose({
  reset,
})

// 数据处理
function cleanEmptyChildren(options, fieldNames = { text: 'label', value: 'value', children: 'children' }) {
  if (!Array.isArray(options))
    return options

  const childrenKey = fieldNames.children || 'children'

  return options.map((option) => {
    // 深拷贝选项，避免修改原始数据
    const newOption = { ...option }

    // 如果存在children属性且是空数组
    if (newOption[childrenKey] && Array.isArray(newOption[childrenKey]) && newOption[childrenKey].length === 0) {
      delete newOption[childrenKey]
    }
    // 如果存在children属性且非空，则递归处理
    else if (newOption[childrenKey] && Array.isArray(newOption[childrenKey])) {
      newOption[childrenKey] = cleanEmptyChildren(newOption[childrenKey], fieldNames)
    }
    return newOption
  })
}

// 级联选择完成事件
function onTreeSelectFinish({ selectedOptions }) {
  const index = selectedOptions.length - 1
  treeValue.value = selectedOptions[index].label
  if (mode === '查询') {
    modelData.value = [selectedOptions[index].value]
  }
  else {
    modelData.value = selectedOptions[index].value
  }
  commChange()
  showTreeSelect.value = false
}

function emitFunc(func, data, attr) {
  emits('xFormItemEmitFunc', func, data, data?.model ? form[data.model] : form, attr)
}

function findOptionInTree(options, value) {
  // 在当前层级查找
  const foundItem = options.find(item => item[columnsField.value] === value)
  if (foundItem) {
    return foundItem
  }
  // 递归查找子级
  for (const item of options) {
    if (item.children?.length) {
      const foundInChildren = findOptionInTree(item.children, value)
      if (foundInChildren)
        return foundInChildren
    }
  }

  return null
}

// 懒加载搜索函数
async function handleLazySearch(searchText: string) {
  if (!attr.keyName || typeof attr.keyName !== 'string') {
    return []
  }

  try {
    // 如果是 search@ 类型的数据源
    if (attr.keyName.includes('search@')) {
      let source = attr.keyName.substring(7)
      const userid = currUser.value
      let roleName = 'roleName'

      if (source.startsWith('根据角色[') && source.endsWith(']获取人员')) {
        const startIndex = source.indexOf('[') + 1
        const endIndex = source.indexOf(']', startIndex)
        roleName = source.substring(startIndex, endIndex)
        source = '根据角色获取人员'
      }

      const searchData = {
        source,
        userid,
        roleName,
        searchText, // 添加搜索关键词
      }

      return new Promise((resolve) => {
        if (attr.type === 'select' || attr.type === 'checkbox') {
          searchToListOption(searchData, (res) => {
            // 根据搜索关键词过滤结果
            const filtered = res.filter((item) => {
              const text = item[columnsField.value.text] || item.label || ''
              return text.toString().toLowerCase().includes(searchText.toLowerCase())
            })
            resolve(filtered)
          })
        }
        else {
          searchToOption(searchData, (res) => {
            const filtered = res.filter((item) => {
              const text = item[columnsField.value.text] || item.label || ''
              return text.toString().toLowerCase().includes(searchText.toLowerCase())
            })
            resolve(filtered)
          })
        }
      })
    }

    // logic 数据源
    if (attr.keyName.includes('logic@')) {
      const logicName = attr.keyName.substring(6)
      const value = { word: searchText, ...userInfo.value }

      // 调用logic前设置参数
      if (getDataParams && getDataParams[attr.model]) {
        Object.assign(value, getDataParams[attr.model])
      }

      lastFetchId.value++
      const fetchId = lastFetchId.value
      // 根据搜索关键词过滤结果
      const results = await runLogic(logicName, value, serviceName) as any
      if (fetchId !== lastFetchId.value) {
        return
      }
      if (searchText) {
        return results.filter((item) => {
          const text = item[columnsField.value.text] || item.label || ''
          return text.toString().toLowerCase().includes(searchText.toLowerCase())
        })
      }
      return results
    }

    // 自定义 js 函数
    if (attr.keyName.includes('async ') || attr.keyName.includes('function ')) {
      const results = await executeStrFunctionByContext(getCurrentInstance(), attr.keyName, [
        { ...props.form, searchText },
        runLogic,
        props.mode,
        getConfigByNameAsync,
        post,
        userState,
      ])
      // 根据搜索关键词过滤结果
      return results.filter((item) => {
        const text = item[columnsField.value.text] || item.label || ''
        return text.toString().toLowerCase().includes(searchText.toLowerCase())
      })
    }

    return []
  }
  catch (error) {
    console.error('懒加载搜索失败:', error)
    return []
  }
}

// 扫码/NFC
function scanCodeOrNfc(attr) {
  if (attr.type === 'scanCode') {
    // 扫码逻辑
    mobileUtil.execute({
      funcName: 'scanBarcode',
      param: {},
      callbackFunc: (res: any) => {
        console.log('扫码结果:------', res)
        if (res && res.status === 'success') {
          if (res.data.status && res.data.status === 'cancelled') {
            showToast(res.data?.message || '扫码已取消')
            return
          }
          modelData.value = res.data?.rawValue
          showToast('扫码成功')
          emitFunc('xFormItemEmitFunc', res, attr)
        }
        else {
          showToast('扫码失败')
        }
      },
    })
  }
  else if (attr.type === 'nfc') {
    // NFC逻辑
    mobileUtil.execute({
      funcName: 'startNfcScan',
      param: {},
      callbackFunc: (res: any) => {
        console.log('nfc结果:------', res)
        if (res && res.status === 'success') {
          modelData.value = res.data?.id
          showToast('NFC 检测成功')
          emitFunc('xFormItemEmitFunc', res, attr)
        }
        else {
          showToast(res?.message || 'NFC 功能不可用')
        }
      },
    })
  }
}
// 统一的表单项change处理逻辑
function handleFormItemChange() {
  // 处理both模式
  const options = option.value
  if (attr.selectValueType === 'both') {
    nextTick(() => {
      selectValueTypeHandler.processBothMode(
        form,
        attr.model,
        form[attr.model],
        options,
      )
    })
  }
  // 处理label模式
  if (attr.selectValueType === 'label') {
    nextTick(() => {
      selectValueTypeHandler.processLabelMode(
        form,
        attr.model,
        form[attr.model],
        options,
      )
    })
  }
  // 处理原有的dataChangeFunc
  if (attr.dataChangeFunc) {
    // this.debouncedDataChangeFunc()
    dataChangeFuncdebounce()
  }
  emits('setForm', form)
}

// 需要选择的表单项变化时触发
function commChange() {
  handleFormItemChange()
}

// 组件卸载时清理：取消所有防抖函数、清除实例引用、关闭弹窗
onBeforeUnmount(() => {
  // 关闭所有弹窗，确保 teleport 到 body 的 DOM 被正确销毁
  showPicker.value = false
  showTimePicker.value = false
  showArea.value = false
  showAddressPicker.value = false
  showTreeSelect.value = false
  calendarShow.value = false
  // 停止所有 watch，防止内存泄漏
  stopWatchForm()
  stopWatchModelData()
  stopWatchOption()
})
</script>

<template>
  <div>
    <!-- switch开关 -->
    <VanField
      v-if="attr.type === 'switch' && showItem"
      name="switch"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'right')"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      :required="attr.rule.required === 'true'"
    >
      <template #input>
        <VanSwitch v-model="modelData" />
      </template>
    </VanField>

    <!-- 复选框 -->
    <!--    <VanField
      v-if="attr.type === 'checkbox'"
      name="checkbox"
      :label="labelData"
    >
      <template #input>
        <VanCheckbox v-model="modelData" shape="square" />
      </template>
    </VanField> -->

    <!-- 多选框-checkbox-复选框组  -->
    <template v-if="attr.type === 'checkbox' && showItem">
      <!--  勾选    -->
      <VanField
        v-if="mode !== '查询'"
        name="checkboxGroup"
        :label="labelData"
        :label-align="labelAlign"
        :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
        :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
        :required="attr.rule.required === 'true'"
      >
        <template #input>
          <van-checkbox-group
            v-model="modelData as any[]"
            direction="horizontal"
            shape="square"
            :disabled="readonly"
            @change="commChange"
          >
            <VanCheckbox v-for="(item, index) in option" :key="index" style="padding: 2px" :name="item[columnsField.value]" :shape="rules?.[attr.model].shape" :value="item[columnsField.value]">
              {{ item[columnsField.text] }}
            </VanCheckbox>
          </van-checkbox-group>
        </template>
      </VanField>
      <VanField
        v-if="attr.showMode === 'checkbox' && mode === '查询'"
        name="checkboxGroup"
        :label="labelData"
        :label-align="labelAlign"
        :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
        :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      >
        <template #input>
          <XGridDropOption
            v-model="(modelData as string[])"
            :column-num="labelData ? 3 : 4"
            :multiple="true"
            :columns="option"
            @change="commChange"
          />
        </template>
      </VanField>
      <!--   下拉   -->
      <XMultiSelect
        v-if="(!attr.showMode || attr.showMode === 'select') && mode === '查询'"
        v-model="modelData"
        :label="labelData"
        :readonly="readonly"
        :placeholder="placeholder"
        :columns="option"
        :select-value="Array.isArray(modelData) ? modelData : []"
        :option="attr.option ? attr.option : columnsField"
        :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
        :required="attr.rule.required === 'true'"
        :lazy-load="attr.lazyLoad"
        :on-search="attr.lazyLoad ? handleLazySearch : null"
        @confirm="commChange"
      />
    </template>

    <!-- 单选框 -->
    <VanField
      v-if="attr.type === 'radio' && mode !== '查询' && showItem"
      name="radio"
      center
      :placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      :required="attr.rule.required === 'true'"
    >
      <template #input>
        <VanRadioGroup v-model="modelData" direction="horizontal" :disabled="readonly" @change="commChange">
          <VanRadio v-for="(item, index) in option" :key="index" style="padding: 2px" :name="item[columnsField.value]" :value="item[columnsField.value]">
            {{ item[columnsField.text] }}
          </VanRadio>
        </VanRadioGroup>
      </template>
    </VanField>

    <!-- 单选框-查询 -->
    <VanField
      v-if="attr.type === 'radio' && mode === '查询' && showItem"
      name="radio"
      :placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
    >
      <template #input>
        <XGridDropOption
          v-model="(modelData as string)"
          :column-num="labelData ? 3 : 4"
          :columns="option"
          @change="commChange"
        />
      </template>
    </VanField>

    <!-- 步进器 -->
    <VanField
      v-if="attr.type === 'stepper' && showItem"
      name="stepper"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'center')"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      :required="attr.rule.required === 'true'"
    >
      <template #input>
        <VanStepper v-model="modelData as any" :disabled="readonly" />
      </template>
    </VanField>

    <!-- 评分 -->
    <VanField
      v-if="attr.type === 'rate' && showItem"
      name="rate"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'center')"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      :required="attr.rule.required === 'true'"
    >
      <template #input>
        <VanRate v-model="modelData as number" :size="25" :count="attr.displayCount || 5" :readonly="readonly" void-color="#eee" void-icon="star" color="#ffd21e" />
      </template>
    </VanField>

    <!-- 滑块 -->
    <VanField
      v-if="attr.type === 'slider' && showItem"
      name="slider"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      :required="attr.rule.required === 'true'"
    >
      <template #input>
        <VanSlider v-model="modelData as number" :readonly="readonly" />
      </template>
    </VanField>

    <!-- 文件上传 -->
    <!-- 图片上传, 手机端拍照 -->
    <VanField
      v-if="(attr.type === 'image' || attr.type === 'file') && showItem"
      :name="attr.model"
      :label="labelData"
      center
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      :rules="getFileUploadRules()"
      :required="attr.rule?.required === 'true'"
    >
      <template #input>
        <!-- 只读且为空时显示空提示 -->
        <div v-if="showEmptyTip" class="empty-tip">
          {{ placeholder }}
        </div>
        <!-- 有值或非只读时显示上传组件 -->
        <ImageUploader
          v-else
          upload-mode="server"
          :image-list="(modelData as any[])"
          authority="admin"
          :attr="attr"
          :mode="props.mode"
          :readonly="readonly"
          :service-name="serviceName"
          :is-async-upload="isAsyncUpload"
          @update-file-list="updateFile"
          @photo-quality-change="(type) => emits('photoQualityChange', type)"
        />
      </template>
    </VanField>
    <!-- 签字：App 原生签字板，微信/浏览器 H5 在线签名 -->
    <AdaptiveSignatureField
      v-if="attr.type === 'signature' && showItem"
      :label="labelData"
      upload-mode="server"
      :image-list="(modelData as any[])"
      :required="attr.rule?.required === 'true'"
      :disabled="attr.disabled"
      :form-readonly="readonly"
      :is-async-upload="isAsyncUpload"
      :service-name="serviceName"
      @signature-complete="signatureComplete"
    />

    <!-- 选择器 琉璃中不存在,不进行维护后续将删除 -->
    <VanField
      v-if="attr.type === 'picker' && showItem"
      v-model="pickerValue"
      name="picker"
      :placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      readonly
      is-link
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      @click="readonly ? null : showPicker = true"
    />
    <VanPopup v-model:show="showPicker" round position="bottom" teleport="body" overlay-class="date-picker-overlay">
      <VanPicker
        v-model="(modelData as Numeric[])"
        :title="attr.name"
        :columns="attr.selectKey"
        :readonly="readonly"
        :columns-field-names="attr.customFieldName ? attr.customFieldName : { text: 'text', value: 'value', children: 'children' }"
        :confirm-button-text="attr.confirmButtonText || attr.confirmButtonText === '' ? attr.confirmButtonText : '确认'"
        :cancel-button-text="attr.cancelButtonText || attr.cancelButtonText === '' ? attr.cancelButtonText : '取消'"
        @cancel="showPicker = false"
        @confirm="onPickerConfirm"
      />
    </VanPopup>

    <!-- 日历选择-查询 -->
    <VanField
      v-if="attr.type === 'rangePicker' && mode === '查询' && showItem"
      v-model="(pickerValue as string | number)"
      is-link
      readonly
      name="rangePicker"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      :placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      @click="calendarShow = true"
    />
    <VanCalendar
      v-model:show="calendarShow"
      switch-mode="year-month"
      type="range"
      teleport="body"
      overlay-class="date-picker-overlay"
      :show-confirm="attr.showConfirm"
      @confirm="onCalendarConfirm"
    />

    <!-- 日期选择器 -->
    <XDatePicker
      v-if="attr.type === 'datePicker' && showItem"
      v-model="modelData"
      :attr="attr"
      :form="form"
      :mode="mode"
      :readonly="readonly"
      :placeholder="placeholder"
      :label-data="labelData"
      :label-align="labelAlign"
      :input-align="attr.inputAlign"
      :required="attr.rule.required === 'true'"
      :show-label="showLabel"
      @change="commChange"
    />

    <!-- 时间选择 --该配置未在pc找到不进行维护 后续将删除 -->
    <VanField
      v-if="attr.type === 'timePicker' && showItem"
      v-model="timePickerValue"
      name="timePicker"
      is-link
      readonly
      :placeholder="attr.placeholder"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      :rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
      @click="readonly ? null : (showTimePicker = true)"
    />
    <VanPopup v-model:show="showTimePicker" position="bottom" teleport="body" overlay-class="date-picker-overlay">
      <VanTimePicker
        v-model="modelData as string[]"
        :title="attr.name"
        :columns-type="attr.columnsType ? attr.columnsType : ['hour', 'minute', 'second']"
        :min-time="attr.minTime ? attr.minTime : '00:00:00'"
        :max-time="attr.maxTime ? attr.maxTime : '23:59:59'"
        :readonly="readonly"
        @cancel="showTimePicker = false"
        @confirm="onTimePickerConfirm"
      />
    </VanPopup>

    <!-- 省市区选择 -->
    <VanField
      v-if="(attr.type === 'area' || attr.type === 'citySelect') && showItem"
      v-model="area"
      name="area"
      :placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
      is-link
      readonly
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      :rules="[{ required: attr.rule.required === 'true', message: '请选择' }]"
      :required="attr.rule.required === 'true'"
      @click="readonly ? null : (showArea = true)"
    />
    <VanPopup v-model:show="showArea" position="bottom" teleport="body" overlay-class="date-picker-overlay">
      <VanArea
        v-model="modelData as string" :title="attr.name" :area-list="areaList"
        @confirm="onAreaConfirm"
        @cancel="showArea = false"
      />
    </VanPopup>

    <!-- 单选下拉列表 -->
    <XSelect
      v-if="attr.type === 'select' && showItem"
      v-model="modelData"
      :label="labelData"
      :label-align="labelAlign"
      :readonly="readonly"
      clearable
      :placeholder="placeholder"
      :columns="option"
      :option="attr.option ? attr.option : columnsField"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      :required="attr.rule.required === 'true'"
      :lazy-load="attr.lazyLoad"
      :on-search="attr.lazyLoad ? handleLazySearch : null"
      @confirm="commChange"
    />

    <!-- 文本区域 -->
    <VanField
      v-if="attr.type === 'textarea' && showItem"
      v-model="(modelData as string)"
      rows="3"
      autosize
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      type="textarea"
      :readonly="readonly"
      :maxlength="attr.maxlength ? attr.maxlength : 200"
      :placeholder="attr.placeholder ? attr.placeholder : `请输入${attr.name}`"
      show-word-limit
      :rules="[{ required: attr.rule.required === 'true', message: `请填写${attr.name}` }]"
      :required="attr.rule.required === 'true'"
    />

    <!-- 文本输入框 -->
    <VanField
      v-if="(attr.type === 'input' || attr.type === 'intervalPicker' || attr.type === 'scanCode' || attr.type === 'nfc') && showItem"
      v-model="(modelData as string)"
      style="align-items: center"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      :type="attr.type as FieldType"
      :readonly="readonly"
      :disabled="attr.disabled"
      :placeholder="placeholder"
      :error-message="errorMessage"
      :clearable="attr.clearable"
      :rules="[{ required: attr.rule.required === 'true', message: `请填写${attr.name}` }]"
      :required="attr.rule.required === 'true'"
      @blur="() => formTypeCheck(attr, modelData as string)"
    >
      <template #input>
        <input
          :value="modelData"
          :readonly="readonly"
          class="van-field__control"
          :placeholder="placeholder"
          style="flex: 1; min-width: 0;"
          :style="{ textAlign: props.inputAlign || attr.inputAlign || 'left' }"
          @input="e => modelData = (e.target as HTMLInputElement).value"
          @blur="() => formTypeCheck(attr, modelData as string)"
        >
        <VanButton
          v-if="(attr.type === 'input' || attr.type === 'intervalPicker') && !props.formReadonly && attr.inputOnAfterName && attr.inputOnAfterFunc && !attr.inputOnAfterName.includes('|')"
          class="action-btn"
          round
          type="primary"
          size="small"
          @click="emitFunc(attr.inputOnAfterFunc, attr, attr)"
        >
          {{ attr.inputOnAfterName }}
        </VanButton>
        <VanButton
          v-if="(attr.type === 'scanCode' || attr.type === 'nfc') && !props.formReadonly"
          class="action-btn scan-nfc"
          round
          size="small"
          @click="scanCodeOrNfc(attr)"
        >
          {{ attr.type === 'scanCode' ? '扫码' : 'NFC' }}
        </VanButton>
      </template>
    </VanField>

    <!-- 地址选择器 -->
    <VanField
      v-if="(attr.type === 'addressSearch' || attr.type === 'coordinateSearch') && showItem"
      v-model="modelData as string"
      name="addressSearch"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      readonly
      is-link
      :placeholder="placeholder"
      :rules="[{ required: attr.rule.required === 'true', message: '请选择地址' }]"
      :required="attr.rule.required === 'true'"
      @click="readonly ? null : (showAddressPicker = true)"
    />
    <VanPopup
      v-model:show="showAddressPicker"
      position="bottom"
      :style="{ height: '80vh' }"
      teleport="body"
      overlay-class="date-picker-overlay"
    >
      <XLocationPicker
        :default-center="defaultMapCenter"
        :service-name="serviceName"
        @confirm="handleAddressConfirm"
      />
    </VanPopup>

    <!--  pc的树形选择框————》 手机端采用 Cascader 级联选择  -->
    <VanField
      v-if="attr.type === 'treeSelect' && showItem"
      v-model="treeValue"
      name="treeSelect"
      :label="labelData"
      :label-align="labelAlign"
      :input-align="props.inputAlign ? props.inputAlign : (attr.inputAlign ? attr.inputAlign : 'left')"
      readonly
      is-link
      :placeholder="attr.placeholder ? attr.placeholder : `请选择${attr.name}`"
      :rules="[{ required: attr.rule.required === 'true', message: `请选择${attr.name}` }]"
      :required="attr.rule.required === 'true'"
      @click="readonly ? null : (showTreeSelect = true)"
    />
    <VanPopup
      v-model:show="showTreeSelect"
      position="bottom"
      teleport="body"
      overlay-class="date-picker-overlay"
    >
      <VanCascader
        :options="cleanEmptyChildren(option, attr.customFieldName ? attr.customFieldName : { text: 'label', value: 'value', children: 'children' })"
        :field-names="attr.customFieldName ? attr.customFieldName : { text: 'label', value: 'value', children: 'children' }"
        :title="attr.name"
        :closeable="true"
        @close="showTreeSelect = false"
        @finish="onTreeSelectFinish"
      />
    </VanPopup>
  </div>
</template>

<style scoped>
.date-picker-overlay {
  background-color: rgba(0, 0, 0, 0.2); /* 设置为半透明的黑色 */
}
.action-btn {
  border-radius: 10px;
  margin-left: 8px;
  min-width: 4rem;
  max-width: 6rem;
}

/* 扫码/NFC按钮特殊样式 */
.action-btn.scan-nfc {
  background-color: transparent;
  border: 1px dashed #aca8a8;
  color: #1989fa;
}

/* 空提示样式 */
.empty-tip {
  color: #969799;
  font-size: 14px;
  text-align: center;
  padding: 16px 0;
}
</style>
