<template>
  <basic-container class="customer-archive-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"
          plain
          v-if="hasPermission('customer_archive_add')"
          @click="openArchive()"
          >新增
        </el-button>
        <el-button
          type="primary"
          icon="el-icon-download"
          plain
          v-if="hasPermission('customer_archive_export')"
          @click="handleExport"
          >批量导出
        </el-button>
        <el-button
          type="danger"
          icon="el-icon-delete"
          plain
          v-if="hasPermission('customer_archive_delete')"
          @click="handleDelete"
          >批量删除
        </el-button>
      </template>
      <template #customerCode="{ row }">
        <el-button type="primary" link @click="openArchive(row, true)">
          {{ row.customerCode }}
        </el-button>
      </template>
      <template #accessType="{ row }">
        <el-tag :type="row.accessType === 'formal' ? 'success' : 'warning'">
          {{ accessTypeMap[row.accessType] || '临时客商' }}
        </el-tag>
      </template>
      <template #approvalStatus="{ row }">
        <el-tag :type="approvalStatusMap[row.approvalStatus]?.type || 'info'">
          {{ approvalStatusMap[row.approvalStatus]?.label || '草稿' }}
        </el-tag>
      </template>
      <template #status="{ row }">
        <el-tag :type="row.status === 1 ? 'primary' : 'info'">
          {{ row.status === 1 ? '启用' : '停用' }}
        </el-tag>
      </template>
      <template #menu="{ row }">
        <el-button
          type="primary"
          text
          icon="el-icon-view"
          v-if="hasPermission('customer_archive_view')"
          @click="openArchive(row, true)"
        >
          查看
        </el-button>
        <el-button
          type="primary"
          text
          icon="el-icon-edit"
          v-if="hasPermission('customer_archive_edit') && row.approvalStatus !== 'reviewing'"
          @click="openArchive(row)"
        >
          编辑
        </el-button>
        <el-button
          type="primary"
          text
          icon="el-icon-position"
          v-if="
            hasPermission('customer_archive_submit') &&
            ['draft', 'rejected'].includes(row.approvalStatus)
          "
          @click="handleSubmitApproval(row)"
        >
          提交
        </el-button>
        <el-button
          type="success"
          text
          icon="el-icon-check"
          v-if="hasPermission('customer_archive_approve') && row.approvalStatus === 'reviewing'"
          @click="handleApprove(row)"
        >
          审核通过
        </el-button>
        <el-button
          type="warning"
          text
          icon="el-icon-close"
          v-if="hasPermission('customer_archive_reject') && row.approvalStatus === 'reviewing'"
          @click="handleReject(row)"
        >
          审核不通过
        </el-button>
        <el-button
          type="primary"
          text
          :icon="row.status === 1 ? 'el-icon-close' : 'el-icon-check'"
          v-if="hasPermission('customer_archive_status')"
          @click="handleStatus(row)"
        >
          {{ row.status === 1 ? '停用' : '启用' }}
        </el-button>
        <el-button
          type="danger"
          text
          icon="el-icon-delete"
          v-if="hasPermission('customer_archive_delete') && row.approvalStatus === 'draft'"
          @click="rowDel(row)"
        >
          删除
        </el-button>
      </template>
    </avue-crud>
    <empty-pagination
      :page="page"
      @size-change="sizeChange"
      @current-change="currentChange"
      @load="onLoad(page, query)"
    />

    <el-dialog
      :title="dialogTitle"
      append-to-body
      v-model="archiveBox"
      width="92%"
      top="4vh"
      class="archive-dialog"
      @closed="resetArchive"
    >
      <el-form
        ref="archiveForm"
        :model="archiveForm"
        :rules="formRules"
        label-position="right"
        :disabled="readonly"
        class="archive-form"
      >
        <div class="section-title dialog-section-title">基本信息</div>
        <el-alert
          type="warning"
          :closable="false"
          show-icon
          title="临时客商可暂存基础信息，但不能参与结算；正式客商需资质完整、评分完成并审批通过后生效。"
          class="archive-rule-alert"
        />
        <el-row :gutter="18">
          <el-col v-if="readonly" :span="6">
            <el-form-item label="客商编号" prop="customerCode">
              <el-input v-model="archiveForm.customerCode" disabled placeholder="保存后自动生成" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="准入类型" prop="accessType">
              <el-radio-group v-model="archiveForm.accessType">
                <el-radio label="temporary">临时客商</el-radio>
                <el-radio label="formal">正式客商</el-radio>
              </el-radio-group>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="审批状态" prop="approvalStatus">
              <el-select v-model="archiveForm.approvalStatus" disabled>
                <el-option
                  v-for="item in approvalStatusOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="状态" prop="status">
              <el-select v-model="archiveForm.status">
                <el-option label="启用" :value="1" />
                <el-option label="停用" :value="2" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="客商简称" prop="shortName">
              <el-input v-model="archiveForm.shortName" maxlength="20" show-word-limit />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="客商全称" prop="fullName">
              <el-input v-model="archiveForm.fullName" maxlength="100" show-word-limit />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="客商性质" prop="customerNature">
              <el-select v-model="archiveForm.customerNature" filterable>
                <el-option label="有限公司" value="有限公司" />
                <el-option label="个体工商户" value="个体工商户" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="统一社会信用代码" prop="unifiedCreditCode">
              <el-input
                v-model="archiveForm.unifiedCreditCode"
                maxlength="18"
                show-word-limit
                @input="
                  archiveForm.unifiedCreditCode = String(
                    archiveForm.unifiedCreditCode || ''
                  ).toUpperCase()
                "
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="客商类型" prop="customerType">
              <el-select v-model="archiveForm.customerType" multiple filterable>
                <el-option
                  v-for="item in customerTypeOptions"
                  :key="item.value"
                  :label="item.label"
                  :value="item.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="所属项目" prop="projectName">
              <el-input v-model="archiveForm.projectName" maxlength="100" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="法人/负责人" prop="legalPerson">
              <el-input v-model="archiveForm.legalPerson" maxlength="10" show-word-limit />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="联系电话" prop="contactPhone">
              <el-input v-model="archiveForm.contactPhone" maxlength="20" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="所属组织" prop="deptName">
              <el-tree-select
                v-model="archiveForm.deptId"
                :data="deptTree"
                :props="{ label: 'title', value: 'id', children: 'children' }"
                check-strictly
                filterable
                clearable
                @change="onDeptChange"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="开票税点" prop="invoiceTaxRate">
              <el-input-number v-model="archiveForm.invoiceTaxRate" :min="0" :precision="2" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="营业期限类型" prop="businessTermType">
              <el-select v-model="archiveForm.businessTermType" clearable>
                <el-option label="长期" value="长期" />
                <el-option label="固定期限" value="固定期限" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="营业期限截止日" prop="businessEndDate">
              <el-date-picker
                v-model="archiveForm.businessEndDate"
                type="date"
                value-format="YYYY-MM-DD"
                :disabled="archiveForm.businessTermType === '长期'"
              />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="注册资金(万元)" prop="registeredCapital">
              <el-input-number v-model="archiveForm.registeredCapital" :min="0" :precision="2" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="客商负责人" prop="principal">
              <el-input v-model="archiveForm.principal" maxlength="10" show-word-limit />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="助记码" prop="mnemonicCode">
              <el-input v-model="archiveForm.mnemonicCode" maxlength="15" show-word-limit />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="客户等级" prop="customerLevel">
              <el-input v-model="archiveForm.customerLevel" maxlength="30" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="最大资金使用额度(万元)" prop="maxCreditLimit">
              <el-input-number v-model="archiveForm.maxCreditLimit" :min="0" :precision="2" />
            </el-form-item>
          </el-col>
          <el-col :span="6">
            <el-form-item label="申请总资金使用额度(万元)" prop="applyCreditLimit">
              <el-input-number v-model="archiveForm.applyCreditLimit" :min="0" :precision="2" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="注册/实际经营地址" prop="registeredAddress">
              <el-input v-model="archiveForm.registeredAddress" maxlength="200" show-word-limit />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="经营范围" prop="businessScope">
              <el-input
                v-model="archiveForm.businessScope"
                type="textarea"
                maxlength="500"
                show-word-limit
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="备注" prop="remark">
              <el-input
                v-model="archiveForm.remark"
                type="textarea"
                maxlength="500"
                show-word-limit
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>

      <div class="section-head">
        <div class="section-title dialog-section-title">资质附件</div>
        <div v-if="!readonly" class="section-actions">
          <el-button type="primary" icon="el-icon-upload" @click="addAttachment"
            >OCR上传识别</el-button
          >
          <el-button type="primary" icon="el-icon-plus" @click="addAttachment">添加附件</el-button>
          <el-button icon="el-icon-download" @click="downloadAttachments">批量下载</el-button>
        </div>
      </div>
      <el-alert
        type="info"
        :closable="false"
        title="支持 JPG、PNG、PDF、Word、Excel、PPT，单文件大小不超过 10MB；正式客商需上传公司营业执照、道路运输证等核心材料。"
        class="archive-rule-alert"
      />
      <el-alert
        v-if="missingQualificationText"
        type="error"
        :closable="false"
        :title="missingQualificationText"
        class="archive-rule-alert"
      />
      <el-table :data="qualificationFiles" border>
        <el-table-column label="序号" type="index" width="70" align="center" />
        <el-table-column label="附件类型" min-width="160">
          <template #default="{ row }">
            <el-select v-model="row.type" :disabled="readonly" filterable>
              <el-option label="法人身份证" value="法人身份证" />
              <el-option label="公司营业执照" value="公司营业执照" />
              <el-option label="道路运输证" value="道路运输证" />
              <el-option label="开户许可证" value="开户许可证" />
              <el-option label="其他" value="其他" />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="文件名称" min-width="180">
          <template #default="{ row }">
            <vehicle-attachment-upload
              v-model="row.files"
              :readonly="readonly"
              :multiple="false"
              accept=".jpg,.jpeg,.png,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx"
              :max-size="10"
              button-text="上传文件"
              :show-tip="false"
              @success="file => handleQualificationUploadSuccess(file, row)"
            />
          </template>
        </el-table-column>
        <el-table-column label="附件描述" min-width="220">
          <template #default="{ row }">
            <el-input v-model="row.description" :disabled="readonly" maxlength="200" />
          </template>
        </el-table-column>
        <el-table-column label="文件大小" min-width="120">
          <template #default="{ row }">
            <span>{{ row.size || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="上传人" min-width="120">
          <template #default="{ row }">
            <span>{{ row.uploadUserName || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="上传时间" min-width="170">
          <template #default="{ row }">
            <span>{{ row.uploadTime || '-' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="操作" width="90" align="center" v-if="!readonly">
          <template #default="{ $index }">
            <el-button type="danger" text @click="qualificationFiles.splice($index, 1)"
              >删除</el-button
            >
          </template>
        </el-table-column>
      </el-table>

      <el-tabs v-model="activeTab" class="archive-tabs">
        <el-tab-pane label="评分表" name="scores">
          <div class="section-head">
            <span></span>
            <el-button type="primary" icon="el-icon-plus" v-if="!readonly" @click="addScore">
              添加评分记录
            </el-button>
          </div>
          <el-table :data="archiveForm.scores" border>
            <el-table-column label="序号" type="index" width="70" align="center" />
            <el-table-column label="评分日期" min-width="150">
              <template #default="{ row }">
                <el-date-picker
                  v-model="row.scoreDate"
                  type="date"
                  value-format="YYYY-MM-DD"
                  :disabled="readonly"
                />
              </template>
            </el-table-column>
            <el-table-column label="自评得分" prop="selfScore" width="110" align="center" />
            <el-table-column label="复评得分" prop="reviewScore" width="110" align="center" />
            <el-table-column label="最终得分" prop="finalScore" width="110" align="center" />
            <el-table-column label="额度" min-width="150">
              <template #default="{ row }">
                <el-input-number
                  v-model="row.applyCreditLimit"
                  :min="0"
                  :precision="2"
                  :disabled="readonly"
                />
              </template>
            </el-table-column>
            <el-table-column label="信用等级" min-width="130">
              <template #default="{ row }">
                <el-input v-model="row.creditLevel" :disabled="readonly" maxlength="30" />
              </template>
            </el-table-column>
            <el-table-column label="自评状态" prop="selfStatus" width="110" align="center" />
            <el-table-column label="复评状态" prop="reviewStatus" width="110" align="center" />
            <el-table-column label="操作" width="210" align="center">
              <template #default="{ row, $index }">
                <el-button type="primary" text @click="openScore(row)">评分明细</el-button>
                <el-button type="success" text v-if="!readonly" @click="finishScore(row)"
                  >完成评分</el-button
                >
                <el-button
                  type="danger"
                  text
                  v-if="!readonly"
                  @click="archiveForm.scores.splice($index, 1)"
                >
                  删除
                </el-button>
              </template>
            </el-table-column>
          </el-table>
        </el-tab-pane>
        <el-tab-pane label="联系人" name="contacts">
          <editable-table
            :data="archiveForm.contacts"
            :columns="contactColumns"
            :readonly="readonly"
            @add="archiveForm.contacts.push(emptyContact())"
          />
        </el-tab-pane>
        <el-tab-pane label="收款信息" name="receiptAccounts">
          <editable-table
            :data="archiveForm.receiptAccounts"
            :columns="receiptColumns"
            :readonly="readonly"
            @add="archiveForm.receiptAccounts.push(emptyReceiptAccount())"
          />
        </el-tab-pane>
        <el-tab-pane label="发票信息" name="invoices">
          <editable-table
            :data="archiveForm.invoices"
            :columns="invoiceColumns"
            :readonly="readonly"
            @add="archiveForm.invoices.push(emptyInvoice())"
          />
        </el-tab-pane>
        <el-tab-pane label="变更记录" name="changeRecords">
          <el-table :data="archiveForm.changeRecords" border>
            <el-table-column label="序号" type="index" width="70" align="center" />
            <el-table-column label="变更日期" prop="changeTime" min-width="170" />
            <el-table-column label="变更内容" prop="changeContent" min-width="260" />
            <el-table-column label="变更账号" prop="changeUserName" min-width="160" />
          </el-table>
        </el-tab-pane>
      </el-tabs>

      <template #footer>
        <el-button @click="archiveBox = false">{{ readonly ? '关闭' : '取消' }}</el-button>
        <el-button type="primary" v-if="!readonly" @click="saveArchive">保存</el-button>
        <el-button type="success" v-if="!readonly" @click="saveAndSubmitArchive">提交</el-button>
        <el-button v-if="!readonly" @click="archiveBox = false">返回</el-button>
      </template>
    </el-dialog>

    <el-dialog
      title="评分明细"
      append-to-body
      v-model="scoreBox"
      width="88%"
      class="archive-dialog"
    >
      <el-table :data="currentScore.details" border class="score-detail-table">
        <el-table-column label="序号" type="index" width="70" align="center" />
        <el-table-column label="评分类目" prop="categoryName" min-width="130" />
        <el-table-column label="评分项目" prop="itemName" min-width="170" />
        <el-table-column label="评分标准" prop="optionDescription" min-width="180" />
        <el-table-column label="选项" min-width="240">
          <template #default="{ row }">
            <el-select
              v-model="row.selectedOption"
              filterable
              :disabled="readonly"
              @change="scoreOptionChange(row, $event)"
            >
              <el-option
                v-for="item in parseScoreOptions(row.optionsJson)"
                :key="item.value"
                :label="`${item.label}（${item.score || 0}分）`"
                :value="item.value"
              />
            </el-select>
          </template>
        </el-table-column>
        <el-table-column label="自评得分" width="130" align="center">
          <template #default="{ row }">
            <el-input-number v-model="row.selfScore" :min="0" :precision="2" :disabled="readonly" />
          </template>
        </el-table-column>
        <el-table-column label="复评得分" width="130" align="center">
          <template #default="{ row }">
            <el-input-number
              v-model="row.reviewScore"
              :min="0"
              :precision="2"
              :disabled="readonly"
            />
          </template>
        </el-table-column>
        <el-table-column label="得分说明" prop="scoreDescription" min-width="220" />
      </el-table>
      <template #footer>
        <el-button @click="scoreBox = false">关闭</el-button>
        <el-button type="primary" v-if="!readonly" @click="saveScoreDetail">保存明细</el-button>
      </template>
    </el-dialog>
  </basic-container>
</template>

<script>
import {
  getList,
  getDetail,
  submit,
  submitApproval,
  approve,
  reject,
  changeStatus,
  remove,
  getScoreTemplate,
} from '@/api/vehicle/customer-archive';
import { getList as getCustomerTypeList } from '@/api/base/customer-type';
import { getDeptTree } from '@/api/system/dept';
import { exportBlob } from '@/api/common';
import { downloadXls } from '@/utils/util';
import { getToken } from '@/utils/auth';
import { mapGetters } from 'vuex';
import NProgress from 'nprogress';
import 'nprogress/nprogress.css';

const EditableTable = {
  props: {
    data: {
      type: Array,
      default: () => [],
    },
    columns: {
      type: Array,
      default: () => [],
    },
    readonly: {
      type: Boolean,
      default: false,
    },
  },
  emits: ['add'],
  template: `
    <div>
      <div class="section-head">
        <span></span>
        <el-button type="primary" icon="el-icon-plus" v-if="!readonly" @click="$emit('add')">添加</el-button>
      </div>
      <el-table :data="data" border>
        <el-table-column label="序号" type="index" width="70" align="center" />
        <el-table-column
          v-for="column in columns"
          :key="column.prop"
          :label="column.label"
          :min-width="column.minWidth || 150"
        >
          <template #default="{ row }">
            <el-select v-if="column.type === 'select'" v-model="row[column.prop]" :disabled="readonly">
              <el-option label="是" :value="1" />
              <el-option label="否" :value="0" />
            </el-select>
            <el-input v-else v-model="row[column.prop]" :disabled="readonly" :maxlength="column.maxlength || 200" />
          </template>
        </el-table-column>
        <el-table-column label="操作" width="90" align="center" v-if="!readonly">
          <template #default="{ $index }">
            <el-button type="danger" text @click="data.splice($index, 1)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
  `,
};

export default {
  components: {
    EditableTable,
  },
  data() {
    const nonNegativeLabelMap = {
      invoiceTaxRate: '开票税点',
      registeredCapital: '注册资金',
      maxCreditLimit: '最大资金使用额度',
      applyCreditLimit: '申请总资金使用额度',
    };
    const validateNonNegative = (rule, value, callback) => {
      if (value === undefined || value === null || value === '') {
        callback();
      } else if (Number(value) < 0) {
        callback(new Error(`${nonNegativeLabelMap[rule.field] || '数值'}不能小于0`));
      } else {
        callback();
      }
    };
    const validateBusinessEndDate = (rule, value, callback) => {
      if (this.archiveForm.businessTermType === '固定期限' && !value) {
        callback(new Error('请选择营业期限截止日'));
      } else {
        callback();
      }
    };
    return {
      form: {},
      query: {},
      loading: true,
      data: [],
      page: {
        pageSize: 10,
        pageSizes: [10, 20, 50, 100],
        currentPage: 1,
        total: 0,
      },
      selectionList: [],
      archiveBox: false,
      scoreBox: false,
      readonly: false,
      activeTab: 'scores',
      archiveForm: this.emptyArchive(),
      currentScore: { details: [] },
      qualificationFiles: [],
      deptTree: [],
      deptOptions: [],
      customerTypeOptions: [
        { label: '客户', value: '客户' },
        { label: '承运商', value: '承运商' },
      ],
      accessTypeMap: {
        temporary: '临时客商',
        formal: '正式客商',
      },
      approvalStatusOptions: [
        { label: '草稿', value: 'draft' },
        { label: '审核中', value: 'reviewing' },
        { label: '审核通过', value: 'approved' },
        { label: '审核不通过', value: 'rejected' },
      ],
      approvalStatusMap: {
        draft: { label: '草稿', type: 'info' },
        reviewing: { label: '审核中', type: 'warning' },
        approved: { label: '审核通过', type: 'success' },
        rejected: { label: '审核不通过', type: 'danger' },
      },
      contactColumns: [
        { label: '联系人姓名', prop: 'contactName', minWidth: 150, maxlength: 30 },
        { label: '联系电话', prop: 'contactPhone', minWidth: 150, maxlength: 20 },
        { label: '邮箱', prop: 'email', minWidth: 200, maxlength: 100 },
        { label: '职务', prop: 'positionName', minWidth: 140, maxlength: 50 },
        { label: '是否默认', prop: 'isDefault', type: 'select', minWidth: 110 },
        { label: '备注', prop: 'remark', minWidth: 220, maxlength: 200 },
      ],
      receiptColumns: [
        { label: '收款方名称', prop: 'accountName', minWidth: 180, maxlength: 100 },
        { label: '开户行名称', prop: 'bankName', minWidth: 180, maxlength: 100 },
        { label: '银行账号', prop: 'bankAccount', minWidth: 180, maxlength: 50 },
        { label: '注册电话', prop: 'registeredPhone', minWidth: 150, maxlength: 20 },
        { label: '注册地址', prop: 'registeredAddress', minWidth: 220, maxlength: 200 },
        { label: '纳税人识别号', prop: 'taxNo', minWidth: 180, maxlength: 30 },
        { label: '是否默认', prop: 'isDefault', type: 'select', minWidth: 110 },
      ],
      invoiceColumns: [
        { label: '受票方名称', prop: 'invoiceTitle', minWidth: 180, maxlength: 100 },
        { label: '纳税人识别号', prop: 'taxNo', minWidth: 180, maxlength: 30 },
        { label: '开户行名称', prop: 'bankName', minWidth: 180, maxlength: 100 },
        { label: '注册电话', prop: 'registeredPhone', minWidth: 150, maxlength: 20 },
        { label: '银行账号', prop: 'bankAccount', minWidth: 180, maxlength: 50 },
        { label: '注册地址', prop: 'registeredAddress', minWidth: 220, maxlength: 200 },
        { label: '邮箱', prop: 'email', minWidth: 200, maxlength: 100 },
        { label: '收件人姓名', prop: 'receiverName', minWidth: 150, maxlength: 30 },
        { label: '收件人电话', prop: 'receiverPhone', minWidth: 150, maxlength: 20 },
        { label: '收件人地址', prop: 'receiverAddress', minWidth: 220, maxlength: 200 },
        { label: '是否默认', prop: 'isDefault', type: 'select', minWidth: 110 },
      ],
      formRules: {
        fullName: [{ required: true, message: '请输入客商全称', trigger: 'blur' }],
        customerNature: [{ required: true, message: '请选择客商性质', trigger: 'change' }],
        unifiedCreditCode: [
          { required: true, message: '请输入统一社会信用代码', trigger: 'blur' },
          {
            pattern: /^[A-Z0-9]{18}$/,
            message: '统一社会信用代码必须为18位大写字母或数字',
            trigger: 'blur',
          },
        ],
        customerType: [
          { type: 'array', required: true, message: '请选择客商类型', trigger: 'change' },
        ],
        legalPerson: [{ required: true, message: '请输入法人/负责人', trigger: 'blur' }],
        contactPhone: [
          { required: true, message: '请输入联系电话', trigger: 'blur' },
          { pattern: /^1\d{10}$/, message: '联系电话必须为11位手机号', trigger: 'blur' },
        ],
        deptName: [{ required: true, message: '请选择所属组织', trigger: 'change' }],
        invoiceTaxRate: [{ validator: validateNonNegative, trigger: 'blur' }],
        registeredCapital: [{ validator: validateNonNegative, trigger: 'blur' }],
        maxCreditLimit: [{ validator: validateNonNegative, trigger: 'blur' }],
        applyCreditLimit: [{ validator: validateNonNegative, trigger: 'blur' }],
        businessEndDate: [{ validator: validateBusinessEndDate, trigger: 'change' }],
        registeredAddress: [{ max: 200, message: '地址最多200个字符', trigger: 'blur' }],
        businessScope: [{ max: 500, message: '经营范围最多500个字符', trigger: 'blur' }],
        remark: [{ max: 500, message: '备注最多500个字符', trigger: 'blur' }],
      },
      option: {
        height: 'auto',
        calcHeight: 32,
        tip: false,
        searchBtnText: '查询',
        emptyBtnText: '重置',
        searchShow: true,
        searchMenuSpan: 24,
        searchIcon: true,
        searchIndex: 8,
        searchMenuPosition: 'right',
        border: true,
        index: true,
        indexLabel: '序号',
        addBtn: false,
        viewBtn: false,
        delBtn: false,
        editBtn: false,
        selection: true,
        dialogClickModal: false,
        menuWidth: 420,
        column: [
          { label: '客商编号', prop: 'customerCode', slot: true, search: true, minWidth: 140 },
          { label: '客商简称', prop: 'shortName', search: true, minWidth: 150 },
          { label: '客商名称', prop: 'fullName', search: true, minWidth: 220, overHidden: true },
          { label: '客商类型', prop: 'customerType', search: true, minWidth: 140 },
          {
            label: '客商性质',
            prop: 'customerNature',
            type: 'select',
            search: true,
            minWidth: 120,
            dicData: [
              { label: '有限公司', value: '有限公司' },
              { label: '个体工商户', value: '个体工商户' },
            ],
          },
          { label: '统一信用代码', prop: 'unifiedCreditCode', search: true, minWidth: 190 },
          { label: '所属组织', prop: 'deptName', search: true, minWidth: 180 },
          {
            label: '准入类型',
            prop: 'accessType',
            slot: true,
            type: 'select',
            search: true,
            minWidth: 120,
            dicData: [
              { label: '临时客商', value: 'temporary' },
              { label: '正式客商', value: 'formal' },
            ],
          },
          {
            label: '审批状态',
            prop: 'approvalStatus',
            slot: true,
            type: 'select',
            search: true,
            minWidth: 130,
            dicData: [
              { label: '草稿', value: 'draft' },
              { label: '审核中', value: 'reviewing' },
              { label: '审核通过', value: 'approved' },
              { label: '审核不通过', value: 'rejected' },
            ],
          },
          { label: '当前节点', prop: 'currentNode', minWidth: 150 },
          { label: '当前处理人', prop: 'currentProcessor', minWidth: 150 },
          {
            label: '审核通过时间',
            prop: 'approvedTime',
            type: 'datetime',
            format: 'YYYY-MM-DD HH:mm:ss',
            valueFormat: 'YYYY-MM-DD HH:mm:ss',
            minWidth: 170,
          },
          {
            label: '状态',
            prop: 'status',
            slot: true,
            type: 'select',
            search: true,
            dataType: 'number',
            minWidth: 100,
            dicData: [
              { label: '启用', value: 1 },
              { label: '停用', value: 2 },
            ],
            clearable: true,
          },
          {
            label: '创建开始时间',
            prop: 'createTimeStart',
            type: 'date',
            format: 'YYYY-MM-DD 00:00:00',
            valueFormat: 'YYYY-MM-DD 00:00:00',
            search: true,
            hide: true,
            display: false,
          },
          {
            label: '创建结束时间',
            prop: 'createTimeEnd',
            type: 'date',
            format: 'YYYY-MM-DD 23:59:59',
            valueFormat: 'YYYY-MM-DD 23:59:59',
            search: true,
            hide: true,
            display: false,
          },
        ],
      },
    };
  },
  created() {
    this.initDeptTree();
    this.initCustomerTypes();
  },
  computed: {
    ...mapGetters(['permission', 'userInfo']),
    isAdmin() {
      const authority = this.userInfo.authority || '';
      return authority.includes('admin');
    },
    permissionList() {
      return {
        addBtn: false,
      };
    },
    ids() {
      let ids = [];
      this.selectionList.forEach(ele => {
        ids.push(ele.id);
      });
      return ids.join(',');
    },
    dialogTitle() {
      if (this.readonly) return '查看客商档案';
      return this.archiveForm.id ? '编辑客商档案' : '新增客商档案';
    },
    missingQualificationText() {
      if (this.archiveForm.accessType !== 'formal') return '';
      const types = this.qualificationFiles
        .filter(item => item.url)
        .map(item => item.type || item.name)
        .filter(Boolean);
      const missing = ['公司营业执照', '道路运输证'].filter(
        item => !types.some(type => String(type).includes(item))
      );
      return missing.length ? `缺失核心资质材料：${missing.join('、')}` : '';
    },
    uploadHeaders() {
      return {
        [this.website.tokenHeader]: getToken(),
      };
    },
  },
  methods: {
    hasPermission(code) {
      return this.isAdmin || this.validData(this.permission[code], false);
    },
    emptyArchive() {
      return {
        accessType: 'temporary',
        approvalStatus: 'draft',
        status: 1,
        customerType: [],
        contacts: [],
        receiptAccounts: [],
        invoices: [],
        scores: [],
        changeRecords: [],
      };
    },
    emptyContact() {
      return {
        contactName: '',
        contactPhone: '',
        email: '',
        positionName: '',
        isDefault: 0,
        remark: '',
      };
    },
    emptyReceiptAccount() {
      return {
        accountName: '',
        bankName: '',
        bankAccount: '',
        registeredPhone: '',
        registeredAddress: '',
        taxNo: '',
        isDefault: 0,
      };
    },
    emptyInvoice() {
      return {
        invoiceTitle: '',
        taxNo: '',
        bankName: '',
        registeredPhone: '',
        bankAccount: '',
        registeredAddress: '',
        email: '',
        receiverName: '',
        receiverPhone: '',
        receiverAddress: '',
        isDefault: 0,
      };
    },
    initDeptTree() {
      getDeptTree(this.userInfo.tenantId).then(res => {
        this.deptTree = res.data.data || [];
        this.deptOptions = this.flattenDept(this.deptTree);
      });
    },
    initCustomerTypes() {
      getCustomerTypeList(1, 200, { status: 1 }).then(res => {
        const records = res.data.data.records || [];
        if (records.length) {
          this.customerTypeOptions = records.map(item => ({
            label: item.name,
            value: item.name,
          }));
          ['客户', '承运商'].forEach(type => {
            if (!this.customerTypeOptions.some(item => item.value === type)) {
              this.customerTypeOptions.push({ label: type, value: type });
            }
          });
        }
      });
    },
    flattenDept(tree, level = 0) {
      const result = [];
      tree.forEach(item => {
        result.push({
          label: `${'　'.repeat(level)}${item.title || item.deptName || item.name}`,
          value: item.id,
          rawLabel: item.title || item.deptName || item.name,
        });
        if (item.children && item.children.length) {
          result.push(...this.flattenDept(item.children, level + 1));
        }
      });
      return result;
    },
    onDeptChange(value) {
      const dept = this.deptOptions.find(item => item.value === value);
      this.archiveForm.deptName = dept ? dept.rawLabel : '';
      this.$refs.archiveForm?.validateField('deptName');
    },
    parseAttachments(value) {
      if (!value) return [];
      if (Array.isArray(value)) return value;
      try {
        const list = JSON.parse(value);
        return Array.isArray(list)
          ? list.map(item => ({
              ...item,
              files: item.url ? [item] : [],
            }))
          : [];
      } catch (error) {
        return String(value)
          .split(',')
          .map(item => ({ name: item.trim(), url: item.trim() }))
          .filter(item => item.url)
          .map(item => ({
            ...item,
            files: [item],
          }));
      }
    },
    stringifyAttachments(list) {
      const files = (list || [])
        .filter(item => item.url)
        .map(item => ({
          type: String(item.type || '').trim(),
          name: String(item.name || '').trim(),
          description: String(item.description || '').trim(),
          size: String(item.size || '').trim(),
          uploadUserName: String(item.uploadUserName || '').trim(),
          uploadTime: String(item.uploadTime || '').trim(),
          url: String(item.url || '').trim(),
        }))
        .filter(item => item.url);
      return files.length ? JSON.stringify(files) : '';
    },
    addAttachment() {
      this.qualificationFiles.push({
        type: '',
        name: '',
        description: '',
        size: '',
        uploadUserName: this.userInfo.realName || this.userInfo.userName || '',
        uploadTime: this.$dayjs().format('YYYY-MM-DD HH:mm:ss'),
        url: '',
        files: [],
      });
    },
    formatAttachmentSize(size) {
      if (!size) return '';
      const byteSize = Number(size);
      if (!Number.isFinite(byteSize)) return String(size);
      const mb = byteSize / 1024 / 1024;
      if (mb >= 1) return `${mb.toFixed(2)} MB`;
      return `${(byteSize / 1024).toFixed(2)} KB`;
    },
    handleQualificationUploadSuccess(file, row) {
      row.name = file.name || row.name || '资质附件';
      row.size = this.formatAttachmentSize(file.size || row.size);
      row.uploadUserName = this.userInfo.realName || this.userInfo.userName || '';
      row.uploadTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss');
      row.url = file.url || row.url || '';
      row.files = [file];
    },
    downloadAttachments() {
      const files = this.qualificationFiles.filter(item => item.url);
      if (!files.length) {
        this.$message.warning('暂无可下载附件');
        return;
      }
      files.forEach(item => window.open(item.url, '_blank'));
    },
    normalizeDetail(detail) {
      const customerType = detail.customerType
        ? String(detail.customerType)
            .split(',')
            .map(item => item.trim())
            .filter(Boolean)
        : [];
      return {
        ...this.emptyArchive(),
        ...detail,
        customerType,
        contacts: detail.contacts || [],
        receiptAccounts: detail.receiptAccounts || [],
        invoices: detail.invoices || [],
        scores: (detail.scores || []).map(this.normalizeScore),
        changeRecords: detail.changeRecords || [],
      };
    },
    normalizeScore(score) {
      return {
        scoreDate: this.$dayjs().format('YYYY-MM-DD'),
        selfStatus: '未完成',
        reviewStatus: '未完成',
        details: [],
        ...score,
        details: score.details || [],
      };
    },
    openArchive(row, readonly = false) {
      this.readonly = readonly;
      this.activeTab = 'scores';
      if (row && row.id) {
        getDetail(row.id).then(res => {
          this.archiveForm = this.normalizeDetail(res.data.data);
          this.qualificationFiles = this.parseAttachments(
            this.archiveForm.qualificationAttachments
          );
          this.archiveBox = true;
        });
        return;
      }
      this.archiveForm = this.emptyArchive();
      this.qualificationFiles = [];
      this.archiveBox = true;
    },
    resetArchive() {
      this.readonly = false;
      this.archiveForm = this.emptyArchive();
      this.qualificationFiles = [];
      this.currentScore = { details: [] };
      this.scoreBox = false;
      this.$refs.archiveForm?.clearValidate();
    },
    validateFormalForApproval(archive) {
      if (archive.accessType !== 'formal') return true;
      if (!archive.qualificationAttachments) {
        this.$message.warning('正式客商提交审核前必须维护资质附件');
        return false;
      }
      const hasCompletedScore = (archive.scores || []).some(
        item => item.selfStatus === '已完成' || item.reviewStatus === '已完成' || item.finalScore
      );
      if (!hasCompletedScore) {
        this.$message.warning('正式客商提交审核前必须完成信用评分');
        return false;
      }
      return true;
    },
    normalizeArchive() {
      const archive = JSON.parse(JSON.stringify(this.archiveForm));
      archive.customerType = Array.isArray(archive.customerType)
        ? archive.customerType.join(',')
        : archive.customerType;
      archive.qualificationAttachments = this.stringifyAttachments(this.qualificationFiles);
      archive.contacts = (archive.contacts || []).filter(
        item => item.contactName || item.contactPhone
      );
      archive.receiptAccounts = (archive.receiptAccounts || []).filter(
        item => item.accountName || item.bankAccount
      );
      archive.invoices = (archive.invoices || []).filter(item => item.invoiceTitle || item.taxNo);
      archive.scores = (archive.scores || []).map(score => this.calculateScore(score));
      return archive;
    },
    saveArchive() {
      this.$refs.archiveForm.validate(valid => {
        if (!valid) {
          this.$message.warning('请先完整填写必填项');
          return;
        }
        submit(this.normalizeArchive()).then(() => {
          this.archiveBox = false;
          this.onLoad(this.page);
          this.$message({ type: 'success', message: '操作成功!' });
        });
      });
    },
    saveAndSubmitArchive() {
      this.$refs.archiveForm.validate(valid => {
        if (!valid) {
          this.$message.warning('请先完整填写必填项');
          return;
        }
        const archive = this.normalizeArchive();
        if (!this.validateFormalForApproval(archive)) return;
        submit(archive).then(res => {
          const data = res.data.data;
          const id = (data && typeof data === 'object' ? data.id : data) || this.archiveForm.id;
          if (!id) {
            this.archiveBox = false;
            this.onLoad(this.page);
            this.$message({ type: 'success', message: '保存成功，请在列表提交审批' });
            return;
          }
          submitApproval(id).then(() => {
            this.archiveBox = false;
            this.onLoad(this.page);
            this.$message({ type: 'success', message: '提交成功!' });
          });
        });
      });
    },
    addScore() {
      getScoreTemplate().then(res => {
        const score = this.normalizeScore(res.data.data);
        if (!score.details || !score.details.length) {
          this.$message.warning('当前评分量化表未配置评分项目');
          return;
        }
        this.archiveForm.scores.push(score);
        this.activeTab = 'scores';
      });
    },
    openScore(row) {
      this.currentScore = row;
      this.scoreBox = true;
    },
    parseScoreOptions(value) {
      if (!value) return [];
      if (Array.isArray(value)) return value;
      try {
        const options = JSON.parse(value);
        return Array.isArray(options) ? options : [];
      } catch (error) {
        return [];
      }
    },
    scoreOptionChange(detail, optionValue) {
      const option = this.parseScoreOptions(detail.optionsJson).find(
        item => item.value === optionValue
      );
      const score = Number(option?.score || 0);
      detail.selfScore = score;
      detail.reviewScore = score;
    },
    calculateScore(score) {
      const details = score.details || [];
      const selfScore = details.reduce((sum, item) => sum + Number(item.selfScore || 0), 0);
      const reviewScore = details.reduce((sum, item) => sum + Number(item.reviewScore || 0), 0);
      score.selfScore = Number(selfScore.toFixed(2));
      score.reviewScore = Number(reviewScore.toFixed(2));
      score.finalScore = Number((reviewScore || selfScore).toFixed(2));
      return score;
    },
    finishScore(score) {
      if (!score.details || !score.details.length) {
        this.$message.warning('请先读取评分量化表');
        return;
      }
      if (score.details.some(item => !item.selectedOption)) {
        this.$message.warning('请完整选择评分明细选项');
        return;
      }
      this.calculateScore(score);
      score.selfStatus = '已完成';
      score.reviewStatus = '已完成';
      this.$message.success('评分已完成');
    },
    saveScoreDetail() {
      this.calculateScore(this.currentScore);
      this.scoreBox = false;
    },
    rowDel(row) {
      this.$confirm('仅草稿状态客商可删除，确定删除该数据?', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => remove(row.id))
        .then(() => {
          this.onLoad(this.page);
          this.$message({ type: 'success', message: '操作成功!' });
        });
    },
    handleDelete() {
      if (this.selectionList.length === 0) {
        this.$message.warning('请选择至少一条数据');
        return;
      }
      if (this.selectionList.some(item => item.approvalStatus !== 'draft')) {
        this.$message.warning('仅草稿状态客商可删除');
        return;
      }
      this.$confirm('确定删除所选草稿客商?', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => remove(this.ids))
        .then(() => {
          this.onLoad(this.page);
          this.$message({ type: 'success', message: '操作成功!' });
          this.selectionClear();
        });
    },
    handleSubmitApproval(row) {
      getDetail(row.id).then(res => {
        const archive = this.normalizeDetail(res.data.data);
        archive.qualificationAttachments = archive.qualificationAttachments || '';
        if (!this.validateFormalForApproval(archive)) return;
        this.$confirm('是否提交客商准入审批?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning',
        })
          .then(() => submitApproval(row.id))
          .then(() => {
            this.onLoad(this.page);
            this.$message({ type: 'success', message: '提交成功!' });
          });
      });
    },
    handleApprove(row) {
      this.$confirm('是否确认审核通过?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => approve(row.id))
        .then(() => {
          this.onLoad(this.page);
          this.$message({ type: 'success', message: '审核通过!' });
        });
    },
    handleReject(row) {
      this.$confirm('是否确认审核不通过?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => reject(row.id))
        .then(() => {
          this.onLoad(this.page);
          this.$message({ type: 'success', message: '操作成功!' });
        });
    },
    handleStatus(row) {
      const nextStatus = row.status === 1 ? 2 : 1;
      const actionName = nextStatus === 1 ? '启用' : '停用';
      this.$confirm(`是否确认${actionName}该客商?`, '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      })
        .then(() => changeStatus(row.id, nextStatus))
        .then(() => {
          this.onLoad(this.page);
          this.$message({ type: 'success', message: '操作成功!' });
        });
    },
    searchReset() {
      this.query = {};
      this.onLoad(this.page);
    },
    searchChange(params, done) {
      this.query = params;
      this.page.currentPage = 1;
      this.onLoad(this.page, params);
      done();
    },
    selectionChange(list) {
      this.selectionList = list;
    },
    selectionClear() {
      this.selectionList = [];
      this.$refs.crud.toggleSelection();
    },
    currentChange(currentPage) {
      this.page.currentPage = currentPage;
    },
    sizeChange(pageSize) {
      this.page.pageSize = pageSize;
    },
    refreshChange() {
      this.onLoad(this.page, this.query);
    },
    onLoad(page, params = {}) {
      this.loading = true;
      getList(page.currentPage, page.pageSize, { ...params, ...this.query })
        .then(res => {
          const pageData = res.data.data;
          this.page.total = pageData.total;
          this.data = pageData.records;
          this.selectionClear();
        })
        .finally(() => {
          this.loading = false;
        });
    },
    handleExport() {
      this.$confirm('是否导出客商档案数据?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning',
      }).then(() => {
        NProgress.start();
        exportBlob(
          '/blade-transport/customer-archive/export-customer-archive',
          this.buildExportParams()
        )
          .then(res => {
            downloadXls(res.data, `客商档案${this.$dayjs().format('YYYY-MM-DD HH:mm:ss')}.xlsx`);
          })
          .finally(() => {
            NProgress.done();
          });
      });
    },
    buildExportParams() {
      return {
        ...this.query,
        ids: this.ids,
        [this.website.tokenHeader]: getToken(),
      };
    },
  },
};
</script>

<style lang="scss" scoped>
.customer-archive-page {
  :deep(.el-table th .cell),
  :deep(.el-table td .cell) {
    white-space: nowrap;
  }
}

.archive-form {
  :deep(.el-input-number),
  :deep(.el-select),
  :deep(.el-date-editor) {
    width: 100%;
  }
}

.section-title {
  margin: 16px 0 12px;
  font-size: 18px;
  font-weight: 700;
  color: #303133;
}

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 18px 0 12px;

  .section-title {
    margin: 0;
  }
}

.section-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: flex-end;
}

.archive-rule-alert {
  margin-bottom: 12px;
}

.archive-tabs {
  margin-top: 18px;
}

.score-detail-table {
  width: 100%;
}

:deep(.archive-dialog .el-dialog__body) {
  max-height: 72vh;
  overflow: auto;
}
</style>
