<template>
  <basic-container class="driver-page">
    <avue-crud
      :option="option"
      :table-loading="loading"
      :data="data"
      v-model:page="page"
      v-model="form"
      ref="crud"
      :permission="permissionList"
      @search-change="searchChange"
      @search-reset="searchReset"
      @selection-change="selectionChange"
      @current-change="currentChange"
      @size-change="sizeChange"
      @refresh-change="refreshChange"
      @on-load="onLoad"
    >
      <template #menu-left>
        <el-button
          type="primary"
          icon="el-icon-plus"
          v-if="hasPermission('driver_add')"
          @click="openDriver()"
          >新增
        </el-button>
        <el-button
          type="primary"
          icon="el-icon-download"
          plain
          v-if="hasPermission('driver_export')"
          @click="handleExport"
          >导出
        </el-button>
        <el-button
          type="danger"
          icon="el-icon-delete"
          plain
          v-if="hasPermission('driver_delete')"
          @click="handleDelete"
          >批量删除
        </el-button>
      </template>
      <template #expireStatus-search>
        <div class="driver-page__expiry-tags">
          <el-check-tag
            v-for="item in expiryTagOptions"
            :key="item.value"
            :checked="query.expireStatus === item.value"
            @change="handleExpireChange(item.value)"
          >
            {{ item.label }}（{{ expiryStat[item.statKey] || 0 }}）
          </el-check-tag>
        </div>
      </template>
      <template #driverName="{ row }">
        <div class="driver-page__identity">
          <el-link type="primary" @click="openDriver(row, true)">{{ row.driverName }}</el-link>
          <span>{{ row.idCardNo || '-' }}</span>
        </div>
      </template>
      <template #status="{ row }">
        <el-tag :type="row.status === 1 ? 'primary' : 'info'">
          {{ row.status === 1 ? '启用' : '停用' }}
        </el-tag>
      </template>
      <template #drivingLicenseEndDate="{ row }">
        <span
          :class="{
            'driver-page__date-expiring': isDateExpiring(
              row,
              'drivingLicenseEndDate',
              'drivingLicenseLongTerm'
            ),
          }"
        >
          {{ formatEndDate(row.drivingLicenseEndDate, row.drivingLicenseLongTerm) }}
        </span>
      </template>
      <template #qualificationEndDate="{ row }">
        <span
          :class="{
            'driver-page__date-expiring': isDateExpiring(
              row,
              'qualificationEndDate',
              'qualificationLongTerm'
            ),
          }"
        >
          {{ formatEndDate(row.qualificationEndDate, row.qualificationLongTerm) }}
        </span>
      </template>
      <template #menu="{ row }">
        <el-link type="primary" v-if="hasPermission('driver_view')" @click="openDriver(row, true)">
          查看
        </el-link>
        <el-link type="primary" v-if="hasPermission('driver_edit')" @click="openDriver(row)">
          修改
        </el-link>
        <el-link type="primary" v-if="hasPermission('driver_status')" @click="handleStatus(row)">
          {{ row.status === 1 ? '停用' : '启用' }}
        </el-link>
      </template>
    </avue-crud>

    <el-dialog
      :title="dialogTitle"
      append-to-body
      v-model="driverBox"
      width="90%"
      top="4vh"
      class="driver-dialog"
      @closed="resetDriver"
    >
      <el-form
        ref="driverForm"
        :model="driverForm"
        :rules="formRules"
        label-position="right"
        :disabled="readonly"
        class="driver-form"
      >
        <section-card title="基础身份信息">
          <el-row :gutter="18">
            <el-col :span="8">
              <el-form-item label="司机姓名" prop="driverName">
                <el-input v-model="driverForm.driverName" maxlength="10" show-word-limit />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="身份证号" prop="idCardNo">
                <el-input
                  v-model="driverForm.idCardNo"
                  maxlength="18"
                  show-word-limit
                  @input="driverForm.idCardNo = String(driverForm.idCardNo || '').toUpperCase()"
                />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="出生年月" prop="birthday">
                <el-date-picker
                  v-model="driverForm.birthday"
                  type="date"
                  value-format="YYYY-MM-DD"
                />
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="18">
            <el-col :span="8">
              <el-form-item label="性别" prop="gender">
                <el-select v-model="driverForm.gender" clearable>
                  <el-option label="男" value="男" />
                  <el-option label="女" value="女" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="民族" prop="nation">
                <el-select v-model="driverForm.nation" clearable filterable>
                  <el-option
                    v-for="item in nationOptions"
                    :key="item"
                    :label="item"
                    :value="item"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="学历" prop="education">
                <el-select v-model="driverForm.education" clearable filterable>
                  <el-option
                    v-for="item in educationOptions"
                    :key="item"
                    :label="item"
                    :value="item"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="18">
            <el-col :span="8">
              <el-form-item label="住址" prop="addressRegion">
                <el-cascader
                  ref="addressRegionCascader"
                  v-model="driverForm.addressRegionPath"
                  :options="regionOptions"
                  :props="regionCascaderProps"
                  :placeholder="driverForm.addressRegion || '请选择省市区'"
                  clearable
                  filterable
                  @change="handleAddressRegionChange"
                />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="详细地址" prop="address">
                <el-input v-model="driverForm.address" maxlength="200" show-word-limit />
              </el-form-item>
            </el-col>
            <el-col :span="8">
              <el-form-item label="岗位" prop="postList">
                <el-checkbox-group v-model="driverForm.postList">
                  <el-checkbox label="司机" />
                  <el-checkbox label="押运员" />
                  <el-checkbox label="装卸管理员" />
                </el-checkbox-group>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="18">
            <el-col :span="8">
              <image-upload-field
                label="身份证正面照"
                prop="idCardFront"
                :value="driverForm.idCardFront"
                :readonly="readonly"
                :headers="uploadHeaders"
                large
                @success="url => handleIdCardUploadSuccess('idCardFront', url)"
              />
            </el-col>
            <el-col :span="8">
              <image-upload-field
                label="身份证反面照"
                prop="idCardBack"
                :value="driverForm.idCardBack"
                :readonly="readonly"
                :headers="uploadHeaders"
                large
                @success="url => handleIdCardUploadSuccess('idCardBack', url)"
              />
            </el-col>
            <el-col :span="8">
              <image-upload-field
                label="大头照"
                prop="headPhoto"
                :value="driverForm.headPhoto"
                :readonly="readonly"
                :headers="uploadHeaders"
                large
                @success="url => setImage('headPhoto', url)"
              />
            </el-col>
          </el-row>
        </section-card>

        <section-card title="驾驶证信息">
          <el-row :gutter="18">
            <el-col :span="6">
              <el-form-item label="准驾车型" prop="drivingType">
                <el-select
                  v-model="driverForm.drivingType"
                  clearable
                  filterable
                  allow-create
                  default-first-option
                >
                  <el-option
                    v-for="item in drivingTypeOptions"
                    :key="item"
                    :label="item"
                    :value="item"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="档案编号" prop="drivingLicenseNo">
                <el-input v-model="driverForm.drivingLicenseNo" maxlength="50" />
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="有效期" prop="drivingLicenseEndDate">
                <div class="date-range">
                  <el-date-picker
                    v-model="driverForm.drivingLicenseStartDate"
                    type="date"
                    value-format="YYYY-MM-DD"
                    placeholder="起"
                    @change="validateFormField('drivingLicenseEndDate')"
                  />
                  <el-date-picker
                    v-model="driverForm.drivingLicenseEndDate"
                    type="date"
                    value-format="YYYY-MM-DD"
                    placeholder="止"
                    :disabled="driverForm.drivingLicenseLongTerm === 1"
                    @change="validateFormField('drivingLicenseEndDate')"
                  />
                </div>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="长期有效" prop="drivingLicenseLongTerm">
                <el-checkbox
                  v-model="driverForm.drivingLicenseLongTerm"
                  :true-label="1"
                  :false-label="0"
                  @change="validateFormField('drivingLicenseEndDate')"
                >
                  是
                </el-checkbox>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="18">
            <el-col :span="12">
              <image-upload-field
                label="驾驶证主页"
                prop="drivingLicenseFront"
                :value="driverForm.drivingLicenseFront"
                :readonly="readonly"
                :headers="uploadHeaders"
                large
                @success="
                  (url, file) => handleDrivingLicenseUploadSuccess('drivingLicenseFront', url, file)
                "
              />
            </el-col>
            <el-col :span="12">
              <image-upload-field
                label="驾驶证副页"
                prop="drivingLicenseBack"
                :value="driverForm.drivingLicenseBack"
                :readonly="readonly"
                :headers="uploadHeaders"
                large
                @success="
                  (url, file) => handleDrivingLicenseUploadSuccess('drivingLicenseBack', url, file)
                "
              />
            </el-col>
          </el-row>
        </section-card>

        <section-card title="从业资格证信息">
          <el-row :gutter="18">
            <el-col :span="6">
              <el-form-item label="从业资格认证类型" prop="qualificationType">
                <el-select
                  v-model="driverForm.qualificationType"
                  clearable
                  filterable
                >
                  <el-option
                    v-for="item in qualificationTypeOptions"
                    :key="item"
                    :label="item"
                    :value="item"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="资格证号" prop="qualificationNo">
                <el-input
                  v-model="driverForm.qualificationNo"
                  maxlength="50"
                  placeholder="默认身份证号"
                />
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="有效期" prop="qualificationEndDate">
                <el-date-picker
                  v-model="driverForm.qualificationEndDate"
                  type="date"
                  value-format="YYYY-MM-DD"
                  :disabled="driverForm.qualificationLongTerm === 1"
                  @change="validateFormField('qualificationEndDate')"
                />
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="长期有效" prop="qualificationLongTerm">
                <el-checkbox
                  v-model="driverForm.qualificationLongTerm"
                  :true-label="1"
                  :false-label="0"
                  @change="validateFormField('qualificationEndDate')"
                >
                  是
                </el-checkbox>
              </el-form-item>
            </el-col>
          </el-row>
          <el-row :gutter="18">
            <el-col :span="12">
              <image-upload-field
                label="封面页"
                prop="qualificationFront"
                :value="driverForm.qualificationFront"
                :readonly="readonly"
                :headers="uploadHeaders"
                large
                @success="url => setImage('qualificationFront', url)"
              />
            </el-col>
            <el-col :span="12">
              <image-upload-field
                label="内容页"
                prop="qualificationBack"
                :value="driverForm.qualificationBack"
                :readonly="readonly"
                :headers="uploadHeaders"
                large
                @success="url => setImage('qualificationBack', url)"
              />
            </el-col>
          </el-row>
        </section-card>

        <section-card title="司机联系信息">
          <el-row :gutter="18">
            <el-col :span="6">
              <el-form-item label="司机类型" prop="driverType">
                <el-select v-model="driverForm.driverType" filterable>
                  <el-option label="自有" value="自有" />
                  <el-option label="外协" value="外协" />
                  <el-option label="承运管理员" value="承运管理员" />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="手机号" prop="mobile">
                <el-input v-model="driverForm.mobile" maxlength="20" />
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="紧急联系人姓名" prop="emergencyContactName">
                <el-input
                  v-model="driverForm.emergencyContactName"
                  maxlength="20"
                  @input="driverForm.emergencyContactName = removeDigits($event)"
                />
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="紧急联系人手机号" prop="emergencyContactMobile">
                <el-input v-model="driverForm.emergencyContactMobile" maxlength="20" />
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="与联系人关系" prop="contactRelation">
                <el-select
                  v-model="driverForm.contactRelation"
                  clearable
                  filterable
                  allow-create
                  default-first-option
                >
                  <el-option
                    v-for="item in relationOptions"
                    :key="item"
                    :label="item"
                    :value="item"
                  />
                </el-select>
              </el-form-item>
            </el-col>
            <el-col :span="6">
              <el-form-item label="所属组织" prop="organizationName">
                <el-select v-model="driverForm.organizationName" clearable filterable>
                  <el-option
                    v-for="item in organizationOptions"
                    :key="item.value"
                    :label="item.label"
                    :value="item.value"
                  />
                </el-select>
              </el-form-item>
            </el-col>
          </el-row>
        </section-card>
      </el-form>
      <template #footer>
        <el-button @click="driverBox = false">取消</el-button>
        <el-button type="primary" v-if="!readonly" :loading="submitLoading" @click="handleSubmit">
          确定
        </el-button>
      </template>
    </el-dialog>
  </basic-container>
</template>

<script>
import { mapGetters } from 'vuex';
import NProgress from 'nprogress';
import { ElLoading } from 'element-plus';
import { option } from '@/option/transportCapacity/driver';
import {
  getList,
  getDetail,
  submit,
  remove,
  changeStatus,
  getExpiryStat,
  recognitionIDCard,
  recognitionTransportCertificates,
} from '@/api/transportCapacity/driver';
import { getDeptTree } from '@/api/system/dept';
import { getDictionary } from '@/api/system/dictbiz';
import { getLazyTree } from '@/api/base/region';
import { exportBlob } from '@/api/common';
import { getToken } from '@/utils/auth';
import { getUploadHeaders } from '@/utils/upload';
import { downloadXls } from '@/utils/util';
import ImageUploadField from '@/components/image-upload-field/main.vue';

const emptyForm = () => ({
  id: '',
  driverName: '',
  idCardNo: '',
  birthday: '',
  gender: '',
  nation: '',
  education: '',
  addressRegionPath: [],
  addressRegion: '',
  address: '',
  postList: ['司机'],
  posts: '',
  idCardFront: '',
  idCardBack: '',
  headPhoto: '',
  drivingType: '',
  drivingLicenseNo: '',
  drivingLicenseStartDate: '',
  drivingLicenseEndDate: '',
  drivingLicenseLongTerm: 0,
  drivingLicenseFront: '',
  drivingLicenseBack: '',
  qualificationType: '',
  qualificationNo: '',
  qualificationEndDate: '',
  qualificationLongTerm: 0,
  qualificationFront: '',
  qualificationBack: '',
  driverType: '自有',
  mobile: '',
  contactRelation: '',
  organizationName: '',
  emergencyContactName: '',
  emergencyContactMobile: '',
  status: 1,
});

export default {
  components: {
    ImageUploadField,
  },
  data() {
    return {
      option,
      form: {},
      query: {
        expireStatus: '',
      },
      searchForm: {},
      loading: true,
      submitLoading: false,
      data: [],
      ids: '',
      selectionList: [],
      page: {
        pageSize: 10,
        currentPage: 1,
        total: 0,
      },
      expiryStat: {
        total: 0,
        within30: 0,
        expired: 0,
      },
      driverBox: false,
      readonly: false,
      driverForm: emptyForm(),
      drivingLicenseUploads: {},
      uploadHeaders: getUploadHeaders(),
      nationOptions: [
        '汉族',
        '蒙古族',
        '回族',
        '藏族',
        '维吾尔族',
        '苗族',
        '彝族',
        '壮族',
        '布依族',
        '朝鲜族',
        '满族',
        '侗族',
        '瑶族',
        '白族',
        '土家族',
        '哈尼族',
        '哈萨克族',
        '傣族',
        '黎族',
        '傈僳族',
        '佤族',
        '畲族',
        '高山族',
        '拉祜族',
        '水族',
        '东乡族',
        '纳西族',
        '景颇族',
        '柯尔克孜族',
        '土族',
        '达斡尔族',
        '仫佬族',
        '羌族',
        '布朗族',
        '撒拉族',
        '毛南族',
        '仡佬族',
        '锡伯族',
        '阿昌族',
        '普米族',
        '塔吉克族',
        '怒族',
        '乌孜别克族',
        '俄罗斯族',
        '鄂温克族',
        '德昂族',
        '保安族',
        '裕固族',
        '京族',
        '塔塔尔族',
        '独龙族',
        '鄂伦春族',
        '赫哲族',
        '门巴族',
        '珞巴族',
        '基诺族',
      ],
      educationOptions: ['初中', '高中', '中专', '大专', '本科', '硕士及以上'],
      drivingTypeOptions: ['A1', 'A2', 'A3', 'B1', 'B2', 'C1', 'C2'],
      qualificationTypeOptions: [],
      relationOptions: ['父母', '配偶', '子女', '兄弟姐妹', '朋友', '同事', '其他'],
      organizationOptions: [],
      regionOptions: [],
      formRules: {
        driverName: [{ required: true, message: '请输入司机姓名', trigger: 'blur' }],
        idCardNo: [{ required: true, message: '请输入身份证号', trigger: 'blur' }],
        gender: [{ required: true, message: '请选择性别', trigger: 'change' }],
        postList: [
          {
            type: 'array',
            required: true,
            min: 1,
            message: '请至少选择一个岗位',
            trigger: 'change',
          },
        ],
        drivingType: [{ required: true, message: '请选择准驾车型', trigger: 'change' }],
        drivingLicenseNo: [{ required: true, message: '请输入档案编号', trigger: 'blur' }],
        drivingLicenseEndDate: [
          { validator: this.validateDrivingLicenseEndDate, trigger: 'change' },
        ],
        drivingLicenseLongTerm: [
          { required: true, message: '请选择驾驶证是否长期有效', trigger: 'change' },
        ],
        qualificationType: [
          { required: true, message: '请选择从业资格认证类型', trigger: 'change' },
        ],
        qualificationNo: [{ required: true, message: '请输入资格证号', trigger: 'blur' }],
        qualificationEndDate: [{ validator: this.validateQualificationEndDate, trigger: 'change' }],
        qualificationLongTerm: [
          { required: true, message: '请选择从业资格证是否长期有效', trigger: 'change' },
        ],
        driverType: [{ required: true, message: '请选择司机类型', trigger: 'change' }],
        mobile: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
        emergencyContactName: [
          { required: true, message: '请输入紧急联系人姓名', trigger: 'blur' },
          { validator: this.validateEmergencyContactName, trigger: 'blur' },
        ],
        emergencyContactMobile: [
          { required: true, message: '请输入紧急联系人手机号', trigger: 'blur' },
        ],
        organizationName: [{ required: true, message: '请选择所属组织', trigger: 'change' }],
        idCardFront: [{ required: true, message: '请上传身份证正面照', trigger: 'change' }],
        idCardBack: [{ required: true, message: '请上传身份证反面照', trigger: 'change' }],
        drivingLicenseFront: [{ required: true, message: '请上传驾驶证主页', trigger: 'change' }],
        drivingLicenseBack: [{ required: true, message: '请上传驾驶证副页', trigger: 'change' }],
      },
    };
  },
  computed: {
    ...mapGetters(['permission', 'userInfo']),
    isAdmin() {
      const authority = this.userInfo.authority || '';
      return authority.includes('admin');
    },
    permissionList() {
      return {
        addBtn: this.hasPermission('driver_add'),
        viewBtn: this.hasPermission('driver_view'),
        delBtn: this.hasPermission('driver_delete'),
        editBtn: this.hasPermission('driver_edit'),
      };
    },
    dialogTitle() {
      if (this.readonly) {
        return '查看司机';
      }
      return this.driverForm.id ? '修改司机' : '新增司机';
    },
    regionCascaderProps() {
      return {
        value: 'id',
        label: 'title',
        children: 'children',
        emitPath: true,
      };
    },
    expiryTagOptions() {
      return [
        { label: '全部', value: '', statKey: 'total' },
        { label: '30天内到期', value: 'within30', statKey: 'within30' },
        { label: '已到期', value: 'expired', statKey: 'expired' },
      ];
    },
  },
  created() {
    this.initDeptTree();
    this.initRegionOptions();
    this.initQualificationTypeOptions();
  },
  methods: {
    hasPermission(code) {
      return this.isAdmin || this.permission?.[code] === true;
    },
    initDeptTree() {
      getDeptTree(this.userInfo.tenantId).then(res => {
        this.organizationOptions = this.formatDeptOptions(res.data.data || []);
        const column = this.findColumn(this.option.column, 'organizationName');
        column.dicData = this.organizationOptions;
        if (this.driverBox && !this.driverForm.id && !this.driverForm.organizationName) {
          this.driverForm.organizationName = this.getCurrentOrganizationName();
        }
      });
    },
    initQualificationTypeOptions() {
      getDictionary({ code: 'type_of_cert' }).then(res => {
        this.qualificationTypeOptions = (res.data.data || [])
          .map(item => item.dictValue)
          .filter(Boolean);
      });
    },
    formatDeptOptions(tree = [], level = 0) {
      const result = [];
      tree.forEach(item => {
        const label = item.title || item.deptName || item.name;
        result.push({
          label: `${'　'.repeat(level)}${label}`,
          value: label,
          rawLabel: label,
          id: item.id || item.value,
        });
        if (item.children && item.children.length) {
          result.push(...this.formatDeptOptions(item.children, level + 1));
        }
      });
      return result;
    },
    getCurrentOrganizationName() {
      const currentDeptId = this.userInfo.deptId || this.userInfo.dept_id;
      const currentDept = this.organizationOptions.find(
        item => String(item.id) === String(currentDeptId)
      );
      return currentDept?.rawLabel || this.userInfo.deptName || this.userInfo.dept_name || '';
    },
    initRegionOptions() {
      getLazyTree().then(res => {
        const regions = this.buildRegionTree(res.data.data || []);
        this.regionOptions = this.extractChinaRegionOptions(regions);
        this.syncAddressRegionPath();
      });
    },
    buildRegionTree(regions = []) {
      const flatRegions = [];
      const collectRegions = list => {
        (list || []).forEach(item => {
          flatRegions.push({
            ...item,
            children: undefined,
          });
          if (item.children?.length) collectRegions(item.children);
        });
      };
      collectRegions(regions);

      const nodeMap = new Map();
      flatRegions.forEach(item => {
        const id = item.id === undefined || item.id === null ? item.value : item.id;
        if (id === undefined || id === null) return;
        nodeMap.set(String(id), {
          ...item,
          id: String(id),
          parentId:
            item.parentId === undefined || item.parentId === null ? '' : String(item.parentId),
          children: [],
        });
      });

      const rootNodes = [];
      nodeMap.forEach(node => {
        const parent = nodeMap.get(node.parentId);
        if (parent && parent !== node) {
          parent.children.push(node);
        } else {
          rootNodes.push(node);
        }
      });
      return rootNodes.map(item => this.normalizeRegionTreeNode(item));
    },
    normalizeRegionTreeNode(region) {
      const children = (region.children || []).map(item => this.normalizeRegionTreeNode(item));
      return {
        ...region,
        children: children.length ? children : undefined,
        leaf: !children.length,
      };
    },
    isChinaRegion(region = {}) {
      const title = String(region.title || region.name || '').trim();
      return title === '中国' || title === '中华人民共和国';
    },
    extractChinaRegionOptions(regions) {
      const china = (regions || []).find(item => this.isChinaRegion(item));
      if (china?.children?.length) return china.children;
      if (regions.length === 1 && regions[0].children?.length) return regions[0].children;
      return regions;
    },
    findRegionOption(options, value) {
      for (const item of options || []) {
        if (String(item.id) === String(value)) return item;
        const child = this.findRegionOption(item.children, value);
        if (child) return child;
      }
      return null;
    },
    findRegionPathByName(options = [], addressRegion = '', parents = []) {
      const target = String(addressRegion || '').replace(/\s+/g, '');
      if (!target) return [];
      for (const item of options || []) {
        const nextParents = [...parents, item];
        const nextName = nextParents.map(region => region.title || region.name || '').join('');
        if (nextName === target) {
          return nextParents.map(region => region.id);
        }
        const childPath = this.findRegionPathByName(item.children, target, nextParents);
        if (childPath.length) return childPath;
      }
      return [];
    },
    getAddressRegionLabels(value) {
      const nodes = this.$refs.addressRegionCascader?.getCheckedNodes?.() || [];
      if (nodes.length && nodes[0].pathLabels?.length) {
        return nodes[0].pathLabels;
      }
      return (value || [])
        .map(code => this.findRegionOption(this.regionOptions, code)?.title)
        .filter(Boolean);
    },
    handleAddressRegionChange(value) {
      if (!value || !value.length) {
        this.driverForm.addressRegion = '';
        this.$refs.driverForm?.validateField('addressRegion');
        return;
      }
      this.$nextTick(() => {
        this.driverForm.addressRegion = this.getAddressRegionLabels(value).join('');
        this.$refs.driverForm?.validateField('addressRegion');
      });
    },
    syncAddressRegionPath() {
      if (!this.driverForm.addressRegion || this.driverForm.addressRegionPath?.length) return;
      const path = this.findRegionPathByName(this.regionOptions, this.driverForm.addressRegion);
      if (path.length) {
        this.driverForm.addressRegionPath = path;
      }
    },
    validateDrivingLicenseEndDate(rule, value, callback) {
      if (!this.driverForm.drivingLicenseStartDate) {
        callback(new Error('请选择驾驶证有效期起'));
        return;
      }
      if (this.driverForm.drivingLicenseLongTerm !== 1 && !value) {
        callback(new Error('请选择驾驶证有效期止'));
        return;
      }
      callback();
    },
    validateQualificationEndDate(rule, value, callback) {
      if (this.driverForm.qualificationLongTerm !== 1 && !value) {
        callback(new Error('请选择从业资格证有效期'));
        return;
      }
      callback();
    },
    validateEmergencyContactName(rule, value, callback) {
      if (/\d/.test(value || '')) {
        callback(new Error('紧急联系人姓名不能包含数字'));
        return;
      }
      callback();
    },
    removeDigits(value = '') {
      return String(value).replace(/\d/g, '');
    },
    openDriver(row, readonly = false) {
      this.readonly = readonly;
      if (!row?.id) {
        this.driverForm = emptyForm();
        this.driverForm.organizationName = this.getCurrentOrganizationName();
        this.driverBox = true;
        return;
      }
      getDetail(row.id).then(res => {
        const detail = res.data.data || {};
        this.driverForm = {
          ...emptyForm(),
          ...detail,
          addressRegionPath: Array.isArray(detail.addressRegionPath)
            ? detail.addressRegionPath
            : [],
          postList: detail.posts ? detail.posts.split(',').filter(Boolean) : [],
        };
        this.syncAddressRegionPath();
        this.driverBox = true;
      });
    },
    resetDriver() {
      this.driverForm = emptyForm();
      this.drivingLicenseUploads = {};
      this.readonly = false;
      this.submitLoading = false;
      this.$refs.driverForm?.clearValidate();
    },
    setImage(prop, url) {
      this.driverForm[prop] = url;
      this.$refs.driverForm?.validateField(prop);
    },
    handleIdCardUploadSuccess(prop, url) {
      this.setImage(prop, url);
      this.recognizeIdCard(url);
    },
    handleDrivingLicenseUploadSuccess(prop, url) {
      this.setImage(prop, url);
      this.drivingLicenseUploads[prop] = url;
      this.recognizeDrivingLicense();
    },
    recognizeIdCard(url = '') {
      if (!url) {
        this.$message.warning('身份证图片上传成功，未获取到图片地址，无法自动识别');
        return;
      }
      const loading = ElLoading.service({
        lock: true,
        text: '身份证识别中',
        background: 'rgba(255, 255, 255, 0.7)',
      });
      recognitionIDCard(url)
        .then(res => {
          const data = res.data.data || {};
          this.applyIdCardRecognition(data);
          this.$message.success('身份证识别完成');
        })
        .catch(() => {
          this.$message.warning('身份证图片上传成功，自动识别失败，请手动填写身份信息');
        })
        .finally(() => {
          loading.close();
        });
    },
    recognizeDrivingLicense() {
      const certificates = this.buildDrivingLicenseRecognitionCertificates();
      if (!certificates.length) {
        this.$message.warning('驾驶证图片上传成功，未获取到图片地址，无法自动识别');
        return;
      }
      const loading = ElLoading.service({
        lock: true,
        text: '驾驶证识别中',
        background: 'rgba(255, 255, 255, 0.7)',
      });
      recognitionTransportCertificates(certificates)
        .then(res => {
          const data = res.data.data || {};
          this.applyDrivingLicenseRecognition(data);
          this.$message.success('驾驶证识别完成');
        })
        .catch(() => {
          this.$message.warning('驾驶证图片上传成功，自动识别失败，请手动填写驾驶证信息');
        })
        .finally(() => {
          loading.close();
        });
    },
    buildDrivingLicenseRecognitionCertificates() {
      return ['drivingLicenseFront', 'drivingLicenseBack']
        .map(prop => {
          const url = this.drivingLicenseUploads[prop] || this.driverForm[prop];
          if (!url) return null;
          return {
            driverLicenseUrl: url,
          };
        })
        .filter(Boolean);
    },
    applyDrivingLicenseRecognition(data = {}) {
      const driverName =
        data.driverLicenseName || data.name || this.getOcrValue(data, ['name', '姓名']);
      const idCardNo = String(
        data.driverLicenseIdNo ||
          data.idNo ||
          data.idCardNo ||
          this.getOcrValue(data, ['ID_no', 'idNo', 'idCardNo', '证号'])
      ).toUpperCase();
      const drivingType =
        data.driverLicenseType ||
        data.drivingType ||
        data.driverClass ||
        this.getOcrValue(data, ['class', '准驾车型']);
      const drivingLicenseNo =
        data.driverLicenseFileNo ||
        data.drivingLicenseNo ||
        data.fileNo ||
        this.getOcrValue(data, ['file_no', '档案编号']);
      const validDateStart =
        data.driverLicenseValidDateStart ||
        data.drivingLicenseStartDate ||
        this.getOcrValue(data, ['date_vaild_start', '有效期限(起始时间)']);
      const validDateEnd =
        data.driverLicenseValidDateEnd ||
        data.drivingLicenseEndDate ||
        this.getOcrValue(data, ['date_vaild_end', '有效期限(终止时间)', '有效期限(终⽌时间)']);
      if (driverName && !this.driverForm.driverName) {
        this.driverForm.driverName = driverName;
      }
      if (idCardNo && !this.driverForm.idCardNo) {
        this.driverForm.idCardNo = idCardNo;
      }
      if (idCardNo && !this.driverForm.qualificationNo) {
        this.driverForm.qualificationNo = idCardNo;
      }
      if (drivingType) {
        this.driverForm.drivingType = drivingType;
      }
      if (drivingLicenseNo) {
        this.driverForm.drivingLicenseNo = drivingLicenseNo;
      }
      if (validDateStart) {
        this.driverForm.drivingLicenseStartDate = this.normalizeBirthday(validDateStart);
      }
      if (validDateEnd) {
        this.driverForm.drivingLicenseEndDate = this.normalizeBirthday(validDateEnd);
        this.driverForm.drivingLicenseLongTerm = 0;
      }
      this.$nextTick(() => {
        [
          'driverName',
          'idCardNo',
          'drivingType',
          'drivingLicenseNo',
          'drivingLicenseEndDate',
          'qualificationNo',
        ].forEach(prop => {
          this.$refs.driverForm?.validateField(prop);
        });
      });
    },
    applyIdCardRecognition(data = {}) {
      const driverName = data.name || data.driverName || this.getOcrValue(data, ['name', '姓名']);
      const idCardNo = String(
        data.idNo ||
          data.idCardNo ||
          data.idCard ||
          this.getOcrValue(data, ['idNo', 'idCardNo', 'number', '公民身份号码', '身份证号'])
      ).toUpperCase();
      const ocrGender = data.gender || this.getOcrValue(data, ['gender', '性别']);
      const ocrNation =
        data.nation ||
        data.ethnicGroup ||
        this.getOcrValue(data, ['ethnic_group', 'nation', '民族']);
      const ocrBirthday =
        data.birthday || data.birthDate || this.getOcrValue(data, ['date', '出生']);
      if (driverName) {
        this.driverForm.driverName = driverName;
      }
      if (ocrGender) {
        this.driverForm.gender = ocrGender;
      }
      if (ocrNation) {
        this.driverForm.nation = this.normalizeNation(ocrNation);
      }
      if (ocrBirthday) {
        this.driverForm.birthday = this.normalizeBirthday(ocrBirthday);
      }
      if (idCardNo) {
        this.driverForm.idCardNo = idCardNo;
        if (!this.driverForm.qualificationNo) {
          this.driverForm.qualificationNo = idCardNo;
        }
        const idCardInfo = this.parseIdCardInfo(idCardNo);
        if (!this.driverForm.birthday && idCardInfo.birthday) {
          this.driverForm.birthday = idCardInfo.birthday;
        }
        if (!this.driverForm.gender && idCardInfo.gender) {
          this.driverForm.gender = idCardInfo.gender;
        }
      }
      this.$nextTick(() => {
        ['driverName', 'idCardNo', 'birthday', 'gender', 'nation', 'qualificationNo'].forEach(
          prop => {
            this.$refs.driverForm?.validateField(prop);
          }
        );
      });
    },
    getOcrValue(data = {}, keys = []) {
      const keyInfos = data.keyInfos || data.keyInfo || data.ocrKeyInfos || [];
      const list = Array.isArray(keyInfos) ? keyInfos : [];
      const item = list.find(info => {
        const key = String(info.key || '').toLowerCase();
        const description = String(info.description || '');
        return keys.some(value => key === String(value).toLowerCase() || description === value);
      });
      return item ? item.value || '' : '';
    },
    normalizeNation(value = '') {
      const nation = String(value || '').trim();
      if (!nation) return '';
      if (this.nationOptions.includes(nation)) return nation;
      const fullNation = `${nation}族`;
      return this.nationOptions.includes(fullNation) ? fullNation : nation;
    },
    normalizeBirthday(value = '') {
      const birthday = String(value || '').trim();
      const match = birthday.match(/^(\d{4})[-/.年](\d{1,2})[-/.月](\d{1,2})日?$/);
      if (!match) return birthday;
      const [, year, month, day] = match;
      return `${year}-${month.padStart(2, '0')}-${day.padStart(2, '0')}`;
    },
    parseIdCardInfo(idCardNo = '') {
      if (!/^\d{17}[\dX]$/.test(idCardNo)) {
        return {};
      }
      const birthday = `${idCardNo.slice(6, 10)}-${idCardNo.slice(10, 12)}-${idCardNo.slice(
        12,
        14
      )}`;
      const date = new Date(`${birthday}T00:00:00`);
      const validDate =
        !Number.isNaN(date.getTime()) &&
        date.getFullYear() === Number(idCardNo.slice(6, 10)) &&
        date.getMonth() + 1 === Number(idCardNo.slice(10, 12)) &&
        date.getDate() === Number(idCardNo.slice(12, 14));
      return {
        birthday: validDate ? birthday : '',
        gender: Number(idCardNo.slice(16, 17)) % 2 === 1 ? '男' : '女',
      };
    },
    validateFormField(prop) {
      this.$refs.driverForm?.validateField(prop);
    },
    handleSubmit() {
      this.$refs.driverForm.validate(valid => {
        if (!valid) {
          return;
        }
        const row = {
          ...this.driverForm,
          qualificationNo: this.driverForm.qualificationNo || this.driverForm.idCardNo,
          posts: this.driverForm.postList.join(','),
        };
        delete row.addressRegionPath;
        this.submitLoading = true;
        submit(row)
          .then(() => {
            this.$message.success('操作成功');
            this.driverBox = false;
            this.onLoad(this.page);
          })
          .finally(() => {
            this.submitLoading = false;
          });
      });
    },
    handleStatus(row) {
      const status = row.status === 1 ? 2 : 1;
      const text = status === 1 ? '启用' : '停用';
      this.$confirm(`是否${text}该司机?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        changeStatus(row.id, status).then(() => {
          this.$message.success('操作成功');
          this.onLoad(this.page);
        });
      });
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning('请选择至少一条数据');
        return;
      }
      this.$confirm('是否删除选中的司机数据?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        remove(this.ids).then(() => {
          this.$message.success('操作成功');
          this.onLoad(this.page);
        });
      });
    },
    handleExpireChange(expireStatus) {
      this.query.expireStatus = expireStatus;
      this.page.currentPage = 1;
      this.onLoad(this.page);
    },
    refreshStat() {
      getExpiryStat(this.buildQuery(false)).then(res => {
        this.expiryStat = {
          total: res.data.data?.total || 0,
          within30: res.data.data?.within30 || 0,
          expired: res.data.data?.expired || 0,
        };
      });
    },
    searchReset() {
      this.searchForm = {};
      this.query = {
        expireStatus: this.query.expireStatus,
      };
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      this.searchForm = params;
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
      this.ids = list.map(item => item.id).join(',');
    },
    selectionClear() {
      this.selectionList = [];
      this.ids = '';
      this.$refs.crud?.toggleSelection();
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.searchForm);
    },
    onLoad(page, params = {}) {
      this.loading = true;
      getList(page.currentPage, page.pageSize, this.buildQuery(true, params))
        .then(res => {
          const data = res.data.data;
          this.page.total = data.total;
          this.data = data.records;
          this.selectionClear();
          this.refreshStat();
        })
        .finally(() => {
          this.loading = false;
        });
    },
    buildQuery(includeExpire = true, params = {}) {
      const query = {
        ...params,
        ...this.searchForm,
      };
      if (Array.isArray(query.organizationName)) {
        query.organizationName = query.organizationName[query.organizationName.length - 1] || '';
      }
      if (includeExpire && this.query.expireStatus) {
        query.expireStatus = this.query.expireStatus;
      }
      return query;
    },
    handleExport() {
      this.$confirm('是否导出司机数据?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        NProgress.start();
        exportBlob('/blade-transport/driver/export-driver', this.buildExportParams(), {
          feedback: true,
        })
          .then(res => {
            downloadXls(res.data, `司机管理${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
          })
          .finally(() => {
            NProgress.done();
          });
      });
    },
    buildExportParams() {
      return {
        ...this.buildQuery(true),
        ids: this.ids,
        [this.website.tokenHeader]: getToken(),
      };
    },
    formatEndDate(date, longTerm) {
      if (longTerm === 1) {
        return '长期有效';
      }
      return date || '-';
    },
    isDateExpiring(row, dateProp, longTermProp) {
      if (row[longTermProp] === 1 || !row[dateProp]) {
        return false;
      }
      const today = this.$dayjs();
      const endDate = this.$dayjs(row[dateProp]);
      return endDate.isValid() && endDate.diff(today, 'day') <= 30;
    },
  },
};
</script>

<style lang="scss" scoped>
.driver-page {
  &__identity {
    display: flex;
    flex-direction: column;
    gap: 4px;
    line-height: 20px;
  }

  &__expiry-tags {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    width: 100%;

    :deep(.el-check-tag) {
      margin: 0;
      white-space: nowrap;
    }
  }

  :deep(.el-table th .cell),
  :deep(.el-table td .cell) {
    white-space: nowrap;
  }
}

.driver-form {
  :deep(.el-date-editor.el-input),
  :deep(.el-date-editor.el-input__wrapper),
  :deep(.el-cascader),
  :deep(.el-select),
  :deep(.el-input) {
    width: 100%;
  }

  .date-range {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 8px;
  }
}

// 大尺寸证件照：按身份证 1.586:1 比例缩放（约真实尺寸 75%，240×151），左对齐显示
:deep(.driver-uploader) {
  display: block;
}

:deep(.driver-uploader .el-upload),
:deep(.driver-uploader.el-upload) {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 170px;
  border: 1px dashed #c0c4cc;
  background: #fafafa;
  overflow: hidden;
}

// 大尺寸模式：缩成 1.586:1 比例，左对齐（不再 100% 占栏）
:deep(.driver-uploader--large) {
  display: block;
  width: 240px;
  margin: 0;
}

:deep(.driver-uploader--large .el-upload),
:deep(.driver-uploader--large.el-upload) {
  width: 100%;
  height: 151px;
}

:deep(.driver-uploader__image) {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

:deep(.driver-uploader__empty) {
  width: 100%;
  height: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #606266;
}

// 弹窗内可滚动（弹窗 body 灰底已由全局 .el-dialog__body 规则生效）
.driver-dialog {
  :deep(.el-dialog__body) {
    max-height: 72vh;
    overflow: auto;
  }
}

.driver-page__date-expiring {
  color: #d40000;
  font-weight: 600;
}

@media (max-width: 1200px) {
  .driver-page {
    &__expiry-tags {
      flex: 1;
    }
  }
}
</style>
