<template>
  <div class="row-list">
    <VxeRender
      ref="crud"
      v-if="reload"
      :cellClassName="cellClassNameFn"
      :data.sync="data"
      :enableEditRowFn="enableEditRowFn"
      :hasCustomToolbar="hasCustomToolbar"
      :hasOperationButton="hasOperationButton"
      :hasPagerBar="hasPagerBar"
      :hasSearchBar="hasSearchBar || showTopbarSearch"
      :hasToolBar="hasToolBar"
      :height="height"
      :id="xid"
      :isDynamicMinWidth="isDynamicMinWidth"
      :listApi="listApi"
      :listParams="listParams"
      :loadingState.sync="loading"
      :merge-cells="mergeCells"
      :operationColumnWidth="operationColumnWidth"
      :option="finalOption"
      :page="page"
      :popupColumn="popupColumn"
      :readOnly="readOnly"
      :rowStyle="rowStyle"
      :selection="selection"
      :showEditColumnIcon="showEditColumnIcon"
      :show-overflow="showOverflow"
      :showPager="showPager"
      :showType="showType"
      :sortable="sortable"
      @column-confirm="handleConfirmColumn"
      @current-change="handlerCurrentChange"
      @page-change="handlerPageChange"
      @row-update="rowUpdate"
      @selection-change="handleSelectChange"
      @tax-code-change="handleTaxCodeChange"
      @vxeSelectDone="vxeSelectDone"
    >
      <template slot="leftMenu">
        <a-button v-if="showSuperQueryShow" @click.stop="handleOpenSuperQuery()">
          {{ labels.advancedSearch }}
        </a-button>

        <a-button
          v-if="!readOnly && addBtn && multipleMaterialAdd"
          @click.stop="handleAddMultipleRow()"
        >
          {{ labels.addMaterials }}
        </a-button>
        <a-button v-if="!readOnly && addBtn && !multipleMaterialAdd" @click.stop="handleAddRow()">
          {{ labels.addRow }}
        </a-button>

        <a-button
          v-if="delBtn"
          type="danger"
          :disabled="!enableDeleteRows()"
          @click.stop="handleDeleteRows()"
          >{{ labels.deleteRow }}</a-button
        >

        <a-button v-if="selectSupplierButton" @click.stop="handleShowSupplierSelector()">
          {{ labels.addSupplier }}
        </a-button>

        <a-button v-if="copyItem" @click.stop="handleCopyItemSelector()">
          {{ labels.copyRow }}
        </a-button>

        <slot name="innerTopLeftBar" />

        <a-button v-if="!readOnly && hasValidInputButton" @click.stop="doCheck()">
          {{ labels.checkInput }}
        </a-button>

        <a-button
          v-if="bitEditItem.length"
          :tip="labels.pleaseFillFirst"
          @click.stop="bitFillAllItem()"
        >
          {{ labels.copyRowWithOneClick }}
        </a-button>

        <a-button
          v-if="showExportExcelButton || showImportExcelButton"
          @click.stop="handleDownloadExcel()"
        >
          {{ exportButtonText }}
        </a-button>

        <fast2-upload
          ref="upload"
          v-if="showImportExcelButton"
          :accept="excelXlsx"
          :btnName="importExcelButtonText"
          :isElementBtn="true"
          @file-error="onFileError"
          @file-progress="onFileProgress"
          @file-success="onFileSuccess"
        />

        <a-button v-if="addSupplierNameButton" @click.stop="handleAddSupplierName()">
          {{ labels.originalSupplierName }}
        </a-button>

        <a-button v-if="addHideFieldsButton" @click.stop="handleHideFieldsName()">
          {{ labels.hideFields }}
        </a-button>

        <a-button v-if="showLadderButton" @click.stop="handleShowLadder()">
          {{ labels.setLadderQuotes }}
        </a-button>

        <a-button v-if="showCostTemplateButton" @click.stop="handleShowCostTemplate()">
          {{ labels.setCostQuotes }}
        </a-button>

        <slot name="innerTopLeftEndBar" />
      </template>

      <template slot="rightTools" slot-scope="row">
        <slot :slot-scope="row" name="innerTopRightBar" />
      </template>

      <!-- 表格右侧 操作 buttons -->
      <template slot="operation" slot-scope="row">
        <slot :slot-scope="row.slotScope" name="operation" />
      </template>

      <!-- 自定义 slots -->
      <template
        v-for="customSlotItem in customSlotItems"
        :slot="customSlotItem.prop"
        slot-scope="{ row }"
      >
        <slot
          v-if="customSlotItem && customSlotItem.prop"
          :slot-scope="row"
          :name="customSlotItem.slotName"
        />
      </template>
      <template v-if="ticketNumber && getTicketURLFn" :slot="ticketNumber" slot-scope="{ row }">
        <router-link class="ticket-number" :to="getTicketURLFn(row)">
          {{ row[ticketNumber] }}
        </router-link>
      </template>

      <template v-for="item in itemLinkList" :slot="item.prop" slot-scope="scope">
        <component
          v-if="showDynamicComponent && isEnableEdit(scope.row, item.prop) > 0"
          :is="item.component"
          :key="item.prop"
          :api="listApi[item.prop]"
          :listParams.sync="listParams[item.prop]"
          :readonly="isEnableEdit(scope.row, item.prop) > 1"
          :selected.sync="scope.row[item.prop]"
          @selectDone="doSelect(item.func, scope.row, $event, item.option || item.params)"
        />
      </template>
    </VxeRender>
    <template v-else>
      <a-skeleton active />
      <a-skeleton active />
      <a-skeleton active />
    </template>
    <fast2-super-query
      ref="superQueryModal"
      @handleSuperQuery="handleSuperQuery"
    ></fast2-super-query>
  </div>
</template>
<script>
import cloneDeep from 'lodash/cloneDeep';
import dayjs from 'dayjs';

import { checkDataType4Vxe, checkFixDic, setRequired, setCellStyle } from '../core/utils.js';
import { DEFAULT_OPERATION_COLUMN_WIDTH, EXCEL_XLSX } from '../../../lib/const.js';
import {
  ft,
  generateDictURLWithLang,
  getApiPath,
  generateRandomString,
  simulationDownload
} from '../../../lib/utils.js';
import { validateNull } from '../../../lib/validate';
import popList from '../../../lib/popList';

import { DownloadAndImportService } from '../../../lib/api/downloadImport';
import { ElsManagePageConfigService } from '../../../lib/api/managePage';
import { PriceRecordService } from '../../../lib/api/materials';
import { i18nConfig } from '../../../mixins/i18n';

import VxeRender from './render-vxe';

const baseUrl = getApiPath();

const ENABLE_STATE = {
  false: 0,
  true: 1,
  readonly: 2
};

const LABELS = {
  add: ft('i18n_common_add', '添加'),
  addRow: ft('i18n_common_add_row', '添加行'),
  advancedSearch: ft('i18n_common_advanced_search', '高级查询'),
  cancel: ft('i18n_common_cancel', '取消'),
  checkInput: ft('i18n_common_check_input', '检查输入'),
  completeRequiredFieldsFist: ft(
    'i18n_common_please_complete_the_required_fields_first',
    '请先完善必填项'
  ),
  continueImport: ft('i18n_common_continue_to_import', '继续导入'),
  copyRow: ft('i18n_common_copy_a_row', '复制行'),
  deleteRow: ft('i18n_common_delete_row', '删除行'),
  copyRowWithOneClick: ft('i18n_common_copy_row_with_one_click', '一键行复制'),
  downExcelTemplate: ft('i18n_common_download_excel_template', '下载Excel模板'),
  editAll: ft('i18n_common_edit_all', '全部编辑'),
  existingDataWillBeClearAndContinue: ft(
    'i18n_common_existing_data_will_be_cleared_whether_to_continue_importing',
    '已有数据将被清除, 是否继续导入?'
  ),
  failedToImportExcel: ft('i18n_common_failed_to_import_excel', '导入Excel数据失败'),
  importExcel: ft('i18n_common_import_excel', '导入Excel数据'),
  linePleaseEnterDataFirst: ft('i18n_common_line_please_enter_data_first', '第?行: 请先录入数据'),
  materialDetails: ft('i18n_common_material_details', '物料明细'),
  materials: ft('i18n_common_materials', '物料'),
  materialNumber: ft('i18n_common_material_number', '物料编码'),
  oneClickSave: ft('i18n_common_one_click_save', '一键保存'),
  operation: ft('i18n_common_operation', '操作'),
  pleaseFillFirst: ft(
    'i18n_common_Please_fill_in_the_first_line_of_data_first',
    '请先填入第一行数据'
  ),
  pleaseSelect: ft('i18n_common_please_select', '请选择 '),
  quote: ft('i18n_common_quote', '报价'),
  quotes: ft('i18n_common_quotes', '报价'),
  sameMaterialExistInLine: ft(
    'i18n_common_same_material_exists_in_line',
    '第?行, 已存在相同的物料'
  ),
  serialNumber: ft('i18n_common_serial_number', '序号'),
  setCostQuotes: ft('i18n_common_set_cost_quotes', '设置成本报价'),
  setLadderQuotes: ft('i18n_common_set_ladder_quotes', '设置阶梯报价'),
  shouldBeEnteredButNotFound: ft(
    'i18n_common_line_should_be_entered_but_field_not_found',
    '第?行: 应当录入数据, 但未找到对应字段'
  ),
  supplier: ft('i18n_common_supplier', '供应商'),
  uploadFailedPleaseTry: ft('i18n_common_upload_failed_please_try_again', '上传失败，请重试'),
  uploading: ft('i18n_common_uploading', '上传中...'),
  originalSupplierName: ft('i18n_common_Original_supplier_name:', '原始供应商名称'),
  hideFields: ft('i18n_common_hide_field:', '隐藏项目信息')
};

LABELS.addMaterials = `${LABELS.add}${LABELS.materials}`;
LABELS.addSupplier = `${LABELS.add}${LABELS.supplier}`;
LABELS.pleaseSelectMaterials = `${LABELS.pleaseSelect}${LABELS.materials}`;

export default {
  /**
   * 导入导出说明
   *
   * @param templateName 指定下载模板文件的名称
   * @param templateNumber
   * @param tempVersion { String } Excel 模板下载接口所需参数，版本号
   * @param showImportExcelButton { Boolean } 是否显示 Excel 导入、导出按钮，默认为 false
   * @param showExportExcelButton { Boolean } 默认为 false, [显示 Excel 导出按钮 的控制条件为 showExportExcelButton 或 showImportExcelButton]
   * @event importExcel 侦听Excel导入行信息后，获取接口返回的行数据

   */
  name: 'RowVxeProvider',
  components: { VxeRender },
  props: {
    /*
     * 导入导出 begin
     */

    // confirmImportTip: 导入成功后的确认提示信息
    confirmImportTip: {
      type: String,
      default: ''
    },

    // exportButtonI18nKey: i18n key of export button text
    exportButtonI18nKey: {
      type: String,
      default: 'i18n_common_excel_download'
    },

    // exportButtonText: export button text
    exportButtonText: {
      type: String,
      default: LABELS.downExcelTemplate
    },

    // exportTemplateFn: 导出下载 template 的方法
    exportTemplateFn: {
      type: Function,
      default: null
    },

    // importExcelButtonText: import excel button text
    importExcelButtonText: {
      type: String,
      default: LABELS.importExcelData
    },

    // 模板名称，相当于下载下来的文件名
    templateName: {
      type: String,
      default: ''
    },

    templateNumber: {
      type: String,
      default: ''
    },

    // tempVersion: excel 模板, 版本号（有业务类型的使用）
    tempVersion: {
      type: String,
      default: ''
    },

    // toElsAccount: 根据els号来校验导入模板是否正确
    toElsAccount: {
      type: String,
      default: ''
    },

    // importApiFn: 导入接口方法
    importApiFn: {
      type: Function,
      default: null
    },

    // importApiParams: 获取导入接口参数方法
    importApiParamsFn: {
      type: Function,
      default: null
    },

    // 导入接口。
    importUrl: {
      type: String,
      default: ''
    },

    // 导入接口需要的自定义参数。
    customData: {
      type: Object,
      default: () => {
        return {};
      }
    },

    // showExportExcelButton: excel 模板 是否显示 导出 Excel 按钮
    showExportExcelButton: {
      type: Boolean,
      default: false
    },

    // showImportExcelButton: excel 模板 是否显示 导入行信息按钮
    showImportExcelButton: {
      type: Boolean,
      default: false
    },

    /*
     * 导入导出 end
     */

    addBtn: {
      type: Boolean,
      default: true // 是否显示添加按钮
    },

    bitEditItem: {
      type: Array,
      default: function () {
        return []; // 允许批量修改的元素
      }
    },

    // businessType: 业务类型
    businessType: {
      type: String,
      default: ''
    },

    canUploadFile: {
      type: Boolean,
      default: true
    },

    col: {
      type: Number,
      default: 0
    },

    copyItem: {
      type: Boolean,
      default: false // 是否显示复制行 按钮 默认不显示
    },

    // customSlots: 自定义 slots, 只输出 slot name, 具体内容由使用都定义(不在组件内部定义), 最多支持 10 个自定义 slot
    customSlots: {
      type: Array,
      default: function () {
        return [];
      }
    },

    data: {
      type: Array,
      default: function () {
        return [];
      }
    },

    delBtn: {
      type: Boolean,
      default: false // 是否显示删除按钮
    },

    deleteSelectedFn: {
      type: Function,
      default: null
    },

    enableDeleteRowsFn: {
      type: Function,
      default: null
    },

    // enAbleI18n: 是否支持多语言
    enAbleI18n: {
      type: Boolean,
      default: true
    },

    // 判断行是否可编辑
    enableEditRowFn: {
      type: Function,
      default: null
    },

    enableSelectDuplicateMaterial: {
      type: Boolean,
      default: false
    },

    // excludePreSlots: 排除组件内置的预定义的字段(属性)Slot, 例如 :excludePreSlots=['materialNumber']
    excludePreSlots: {
      type: Array,
      default: function () {
        return [];
      }
    },

    extendData: {
      type: Object,
      default: function () {
        return {};
      }
    },

    // fitColumnWidth: 表格所有列宽度是否自适应
    fitColumnWidth: {
      type: Boolean,
      default: true
    },

    // hasCustomToolbar 控制是否生成 vxe-table 右上角的 自定义列配置项 (列设置)
    hasCustomToolbar: {
      type: Boolean,
      default: false
    },

    hasOperationButton: {
      type: Boolean,
      default: false
    },

    // 显示分页栏, 与原来的 showType 逻辑分离
    hasPagerBar: {
      type: Boolean,
      default: false
    },

    hasSearchBar: {
      type: Boolean,
      default: true
    },

    hasToolBar: {
      type: Boolean,
      default: true
    },

    hasValidInputButton: {
      type: Boolean,
      default: false
    },

    height: {
      type: String,
      default: '400'
    },

    // 动态设置表格字段显示的最小宽度
    isDynamicMinWidth: {
      type: Boolean,
      default: false
    },

    isEnableEditFn: {
      type: Function,
      default: function () {
        return true;
      }
    },

    isManageList: {
      type: Boolean,
      default: false
    },

    // isShowHistoryPrice: 是否获取物料历史价格
    isShowHistoryPrice: {
      type: Boolean,
      default: false
    },

    itemLink: {
      type: Boolean,
      default: false // 是否只读模式
    },

    // itemLinkList: 组件内置的预定义的字段(属性)Slot
    itemLinkList: {
      type: Array,
      default: function () {
        return this.isManageList ? [] : cloneDeep(popList);
      }
    },

    itemUploadList: {
      type: Array,
      default: function () {
        return [];
      }
    },

    listApi: {
      type: Object,
      default: function () {
        return {};
      }
    },

    listParams: {
      type: Object,
      default: function () {
        return {};
      }
    },

    loading: {
      type: Boolean,
      default: false
    },

    mergeCells: {
      type: Array,
      default: function () {
        return null;
      }
    },

    /**
     * mergeSpanMethodFn: rowspan merge method
     * @deprecated since version 1.0.0
     * @see mergeCells
     */
    mergeSpanMethodFn: {
      type: Function,
      default: null
    },

    multipleMaterialAdd: {
      type: Boolean,
      default: false
    },

    option: {
      type: Object,
      default: function () {
        return { column: [] };
      }
    },

    operationColumnWidth: {
      type: Number,
      default: DEFAULT_OPERATION_COLUMN_WIDTH
    },

    originColumn: {
      type: Array,
      default: function () {
        return [];
      }
    },

    page: {
      type: Object,
      default: function () {
        return { pageSize: 100 };
      }
    },

    pageCode: {
      type: String,
      default: ''
    },

    popupColumn: {
      type: Object,
      default: () => {
        return {};
      }
    },

    readOnly: {
      type: Boolean,
      default: false // 是否只读模式
    },

    rowPermission: {
      type: Object,
      default: function () {
        return {};
      }
    },

    showCostTemplateButton: {
      type: Boolean,
      default: false
    },

    // showDynamicComponent: 显示动态生成的组件
    showDynamicComponent: {
      type: Boolean,
      default: false
    },

    showEditColumnIcon: {
      type: Boolean,
      default: true
    },

    showLadderButton: {
      type: Boolean,
      default: false
    },

    // showOverflow: boolean | string, ellipsis(只显示省略号), title(并且显示为原生 title), tooltip(并且显示为 tooltip 提示)
    showOverflow: {
      type: String,
      default: 'tooltip'
    },

    // showPager: 是否展示分页
    showPager: {
      type: Boolean,
      default: true
    },

    // showSuperQueryShow: 是否显示高级查询按钮
    showSuperQueryShow: {
      type: Boolean,
      default: false
    },

    // showTopbarSearch: 是否展示头部的全表搜索, 优先使用 hasSearchBar
    showTopbarSearch: {
      type: Boolean,
      default: false
    },

    showType: {
      type: String,
      default: 'businessType' // 远程获取 表格字段数据配置- 后续扩充 from 类型
    },

    sortable: {
      type: Boolean,
      default: true
    },

    /*
     * specialCaseProperty: 特例字段, 满足特例时不执行下面的处理(场景)
     * 场景1：isRequired(不设置必填)
     * 场景2: noEditPreSlot(编辑归如属于内置 slot 字段, 按内置 slot 显示 )
     */
    specialCaseProperty: {
      type: Object,
      default: () => {
        return { isRequired: {}, noEditPreSlot: {} };
      }
    },

    type: {
      type: String,
      default: 'crud' // 远程获取 表格字段数据配置- 后续扩充 from 类型
    },

    xid: {
      type: String,
      default: ''
    },

    /* The functions are as follows */

    /* 添加空行时，对数据进行初始化处理
      例如
      addEmptyRowProc(item) {
        item.budgetPrice = '0';
        item.quantity = '0';
        item.subtotalAmount = '0';

        return item;
      }
    */
    addEmptyRowProcFn: {
      type: Function,
      default: null
    },

    afterSelectedMaterialProcFn: {
      type: Function,
      default: null
    },

    // cellClassNameFn: 用于设置 列 的 className, 参数: row, rowIndex, column, columnIndex
    cellClassNameFn: {
      type: Function,
      default: null
    },

    /**
     * @property {Object[Function]} columnDefineProcFns - 列属性规则处理方法集合
     */
    columnDefineProcFns: {
      type: Object,
      default: null
    },

    /*
     * 单据类型相关 begin
     */
    // getTicketURLFn: 根据单据编号计算对应的 URL, 如编辑或详情页面的 URL
    getTicketURLFn: {
      type: Function,
      default: function () {
        return null;
      }
    },

    // rowClassNameFn: 用于设置 行 的 className, 参数: row, rowIndex
    rowClassNameFn: {
      type: Function,
      default: null
    },

    // rowStyle: 用于设置行样式
    rowStyle: {
      type: Function,
      default: function () {
        return null;
      }
    },

    /* 编辑后更新行数据时，对数据进行处理
       例如
       rowUpdateProc(data) {
        const budgetPriceString = Number(data.budgetPrice).toFixed(2);

        const quantityString = data.quantity.toString();

        data.budgetPrice = budgetPriceString;
        data.quantity = quantityString;

        const subtotalAmount = format(
          chain(bignumber(budgetPriceString)).multiply(bignumber(quantityString)).done()
        );

        data.subtotalAmount = Number(subtotalAmount).toFixed(2);
      }
    */

    rowUpdateProcFn: {
      type: Function,
      default: null
    },

    /**
     * 打开弹窗选择一个数据并确定后, 对选取的数据进行处理
     *
     * @property {Object[Function]} selectedItemProcFn - 选择数据后处理方法集合
     * @example
     *  selectedItemProcFn(row, item) {
     *   row.queryUuid = row.uuid,
     * }
     */
    selectedItemProcFn: {
      type: Object,
      default: null
    },

    // selection: 是否多选
    selection: {
      type: Boolean,
      default: false
    },

    // selectionChangeFn: 多选方法
    selectionChangeFn: {
      type: Function,
      default: null
    },

    // ticketNumber: 单据编号 (如采购申请单号)
    ticketNumber: {
      type: String,
      default: function () {
        return '';
      }
    },
    /*
     * 单据类型相关 end
     */

    /*
     * 询报价相关 begin
     */
    selectSupplierButton: {
      type: Boolean,
      default: false // 是否显示添加供应商 按钮 默认不显示
    },
    /*
     * 询报价相关 begin 原始供应商名称
     */
    addSupplierNameButton: {
      type: Boolean,
      default: false // 是否显示原始供应商名称 按钮 默认不显示
    },
    addHideFieldsButton: {
      type: Boolean,
      default: false // 是否显示原始供应商名称 按钮 默认不显示
    },
    supplierQuote: {
      type: Boolean,
      default: false // 是否供应商报价
    }

    /*
     * 询报价相关 end
     */
  },
  data() {
    return {
      labels: LABELS,
      configJson: [],
      currentData: [],
      defaultValues: {},
      excelXlsx: EXCEL_XLSX,
      finalOption: {},
      materialsColumn: [],
      obj: {},
      optionHash: '',
      reload: false,
      removedPreSlots: {},
      requiredColumns: {},

      showColumnProps: null,
      tabCur: -1, // 当前行索引
      uploadField: '',

      customSlotItems: []
    };
  },
  watch: {
    option: {
      handler(newVal, oldVal) {
        if (newVal) {
          this.handleOptionChanged(newVal, oldVal);
        }
      },
      immediate: true, // 刷新加载 立马触发一次handler
      deep: true
    },
    customSlots: {
      handler: async function (newVal, oldVar) {
        if (newVal) {
          this.handleCustomSlotsChanged(newVal);
        }
      },
      immediate: true,
      deep: true
    },
    'data.length': {
      handler: async function (newVal, oldVar) {
        if (newVal > 0) {
          this.data.forEach((item, index) => {
            item.$index = index;
          });
          this.$emit('update:data', this.data);
        }
      },
      immediate: true
    }
  },
  mixins: [i18nConfig],
  created() {
    this.findManagePageConfig();
  },
  methods: {
    addEmptyRow() {
      const item = { $cellEdit: true };
      const showColumnProps = this.getShowColumnProps();

      item.id = `${new Date().valueOf()}${generateRandomString(6)}`;

      for (const prop in showColumnProps) {
        // for (const prop in this.existColumnProps) {
        item[prop] = this.defaultValues[prop] || '';
      }

      if (typeof this.addEmptyRowProcFn === 'function') {
        this.data.push(this.addEmptyRowProcFn(item));
      } else {
        this.data.push(item);
      }
    },

    bitFillAllItem() {
      const copiedItem = {};

      const firstItem = this.data[0];

      const bitEditItems = this.bitEditItem;

      for (const bitEditItem of bitEditItems) {
        if (!firstItem[bitEditItem]) {
          const columnItem = this.finalOption.column.find((item) => item.prop === bitEditItem);

          if (columnItem) {
            this.$message.error(
              `${LABELS.linePleaseEnterDataFirst.replace('?', '1')} - ${
                columnItem.displayName || columnItem.label
              }`
            );
          } else {
            this.$message.error(
              `${LABELS.shouldBeEnteredButNotFound.replace('?', '1')} = ${bitEditItem}`
            );
          }

          return;
        }

        copiedItem[bitEditItem] = firstItem[bitEditItem];
      }

      for (const item of this.data) {
        Object.assign(item, copiedItem);
      }
    },

    async changeOption(finalOption = this.finalOption) {
      this.filterPreSlots();
      this.recoveryPreSlots();

      const finalOptionObject =
        this.showType === 'page'
          ? await this.filterPageColumn(finalOption)
          : await this.filterColumn(finalOption);

      this.finalOption = finalOptionObject;

      const columns = finalOptionObject.column;

      if (Array.isArray(columns)) {
        this.finalOption.column = columns;
      }

      if (this.configJson.length > 0) {
        for (const row of this.finalOption.column) {
          if (this.configJson.indexOf(row.prop) === -1) {
            row.visible = false;
          }
        }
      }

      this.$nextTick(() => {
        this.reload = true;
      });
    },

    checkAddedMaterials(list) {
      const data = this.data;

      const addMaterialList = [];
      const existsList = [];
      let message = '';

      if (data.length < 1) {
        return {
          addList: list,
          existsList,
          message
        };
      } else {
        const materialNumberList = [];

        data.forEach((item) => {
          item.materialNumber &&
            materialNumberList.push({ materialNumber: item.materialNumber, factory: item.factory });
        });

        const index = 1;

        if (this.enableSelectDuplicateMaterial) {
          for (const item of list) {
            addMaterialList.push(item);
          }
        } else {
          for (const item of list) {
            const i = materialNumberList.findIndex(
              (i) => item.materialNumber === i.materialNumber && item.factory === i.factory
            );

            if (item.materialNumber && i !== -1) {
              existsList.push({
                materialNumber: item.materialNumber,
                name: item.materialDesc || item.materialName || ''
              });

              if (!message) {
                message = `${LABELS.sameMaterialExistInLine.replace('?', index.toString())}: ${
                  LABELS.materialNumber
                }(${item.materialNumber})`;
              }
            } else {
              addMaterialList.push(item);
            }
          }
        }
      }

      return {
        addList: addMaterialList,
        existsList,
        message
      };
    },

    checkForm(callback, failback) {
      this.$refs.form.validate((valid, done) => {
        if (valid) {
          callback && callback(done);
        } else {
          failback && failback();
          return false;
        }
      });
    },

    checkSlot(item) {
      const linkItems = this.itemLinkList;

      let itemLinkIndex = 0;

      // 列表页主键 与 内部预置的 自定义的 column 冲突时, 按 主键的 形式展现, 见上面 template 中的 slot="ticketNumber"
      for (const linkItem of linkItems) {
        if (this.ticketNumber && linkItem.prop === this.ticketNumber) {
          linkItems.splice(itemLinkIndex, 1);
          break;
        }

        itemLinkIndex = itemLinkIndex + 1;
      }

      // 列表主键设置跳转路由 slot
      if (this.ticketNumber && item.prop === this.ticketNumber && this.getTicketURLFn) {
        item.slot = true;
        item.align = 'center';
      }

      // 加入只读判断 只读模式不使用slot
      for (const linkItem2 of linkItems) {
        if (item.prop === linkItem2.prop && item.isReadOnly !== 'Y') {
          item.slot = true;
          break;
        }
      }

      if (item.datatype === 'uploadImg' || item.prop === 'picture') {
        this.itemUploadList.push(item);
      }

      if (item.datatype === 'uploadFile' || item.prop === 'url') {
        item.datatype = 'uploadFile';
        item.slot = true;
        this.itemUploadList.push(item);
      }

      this.itemUploadList.map((linkItem) => {
        if (item.prop === linkItem.prop) {
          item.slot = true;
        }
      });
    },

    checkUploadSlot(item) {
      if (item.datatype === 'uploadImg' || item.prop === 'picture') {
        this.itemUploadList.push(item);
      }

      if (item.datatype === 'uploadFile' || item.prop === 'url') {
        item.datatype = 'uploadFile';
        item.slot = true;
        this.itemUploadList.push(item);
      }

      this.itemUploadList.map((linkItem) => {
        if (item.prop === linkItem.prop) {
          item.slot = true;
        }
      });

      // 非只读元素 可以上传
      this.itemUploadList.map((linkItem) => {
        if (item.prop === linkItem.prop && item.isReadOnly === 'N') {
          linkItem.open = true;
          item.formslot = true;
          item.slot = true;
        }
      });
    },

    clearSelection() {
      const curd = this.$refs.crud;
      curd && curd.clearSelection && curd.clearSelection();
    },

    async confirmImport(file) {
      return new Promise((resolve, reject) => {
        this.$confirm({
          title: LABELS.existingDataWillBeClearAndContinue,
          content: '',
          okText: LABELS.continueImport,
          cancelText: LABELS.cancel,
          onOk() {
            resolve(true);
          },
          onCancel() {
            reject(new Error());
          }
        });
      });
    },

    doCheck() {
      this.$refs.crud.fullValidEvent();
    },

    // slot 弹框 处理
    doSelect(func, row, event, params = []) {
      this[func](row, event, params);
      this.$forceUpdate();
    },

    download(blobUrl, fileName) {
      const a = document.createElement('a');
      a.download = fileName;
      a.href = blobUrl;
      a.click();
      document.body.removeChild(a);
    },

    enEditPreSlot(item) {
      this.recoveryPreSlot(item.prop);

      item.formslot = true;
      item.slot = true;
      delete item.type;
    },

    async filterColumn(option) {
      const waitUpdateDic = [];
      const crud = this.$refs.crud;

      const newColumns = [];

      const columns = option.column || [];
      const columnsCount = {};
      const bitEditItem = this.bitEditItem;

      const customSlotPropItems = {};

      const customSlots = this.customSlots || [];

      customSlots.forEach((item) => {
        if (item.prop) {
          customSlotPropItems[item.prop] = 1;
        }
      });

      for (const item of columns) {
        const itemProp = this.rowPermission[item.prop];

        if (customSlotPropItems[item.prop] && item.slot !== true) {
          item.slot = true;
        }

        await checkDataType4Vxe(item);

        if (bitEditItem.includes(item.prop)) {
          item.headerslot = true;
        }

        if (typeof itemProp !== 'undefined' && typeof itemProp.value !== 'undefined') {
          this.defaultValues[item.prop] = itemProp.value;
        } else if (item.type === 'radio' && item.dicData && item.dicData.length > 0) {
          if (item.dicData[0] && typeof item.dicData[0].value !== 'undefined') {
            this.defaultValues[item.prop] = item.dicData[0].value;
          }
        }

        this.checkUploadSlot(item);

        checkFixDic(item);
        // 普通字段控制
        if (itemProp) {
          item.isReadOnly = itemProp.isReadOnly;

          if (itemProp.display && itemProp.display !== false) {
            // 多语言
            if (this.enAbleI18n) {
              this.setI18n(item);
            } else {
              this.setDisplayName(item);
            }

            if (itemProp.value) {
              item.value = itemProp.value;
            }

            if (itemProp.isRequired === 'Y') {
              itemProp.isRequired = true;
            }

            if (itemProp.isRequired === 'N') {
              itemProp.isRequired = false;
            }

            const isRequired = this.specialCaseProperty.isRequired[item.prop]
              ? false
              : !!itemProp.isRequired;

            if (isRequired) {
              this.requiredColumns[item.prop] = 1;

              setRequired(item);
            }

            // 默认 配置会带出字典项 无需再次加载
            if (!validateNull(itemProp.bizDic) && !item.dicData && !item.dicData.length) {
              delete item.dicData;
              delete item.dicMethod;
              delete item.props;
              item.type = 'select';
              item.dicUrl = generateDictURLWithLang(
                `${baseUrl}/ElsSearchDictionaryService/no-auth/dict/${itemProp.bizDic}`,
                true
              );
              waitUpdateDic.push(item.prop);
            }

            if (itemProp.isDisabled === false) {
              delete item.disabled;
              item.cell = true;

              // if (item.datatype === 'popup' && this.removedPreSlots[item.prop]) {
              //   this.enEditPreSlot(item.prop);
              // }
            } else if (itemProp.isDisabled === true) {
              item.disabled = true;

              if (item.datatype === 'popup') {
                if (!this.specialCaseProperty.noEditPreSlot[item.prop]) {
                  this.noEditPreSlot(item);
                }
              }
            } else if (
              item.isDisabled === 'Y' ||
              this.readOnly ||
              item.ref ||
              item.disabled === true ||
              item.disabled === 'disabled'
            ) {
              item.disabled = true;
              item.cell = false;
              item.rules = [];
            } else {
              item.cell = true;
              delete item.readonly;
            }

            if (item.isReadOnly === 'Y') {
              item.disabled = true;
              item.cell = false;
              item.rules = [];
            }

            if (item.prop === 'taxRate') {
              item.cell = false;
            }
            // 允许用户编辑字段 并 输入框类型 可以编辑
            if (item.type === 'varchart' && item.isUserInput === 'N') {
              item.cell = false;
            }

            setCellStyle(item, {
              fitColumnWidth: this.fitColumnWidth,
              isVxeTable: true
            });

            item.display = true;

            if (
              this.columnDefineProcFns &&
              typeof this.columnDefineProcFns[item.prop] === 'function'
            ) {
              this.columnDefineProcFns[item.prop].call(this, item);
            }

            if (!columnsCount[item.prop]) {
              newColumns.push(item);
              columnsCount[item.prop] = true;
            }
          }
        }

        // 如果是系统必填字段
        if (item && item.isRequired === 'Y') {
          this.requiredColumns[item.prop] = 1;

          setRequired(item);

          if (item.type === 'varchart' && item.isUserInput === 'N') {
            item.cell = false;
          } else {
            item.cell = true;
          }

          item.display = true;

          if (
            this.columnDefineProcFns &&
            typeof this.columnDefineProcFns[item.prop] === 'function'
          ) {
            this.columnDefineProcFns[item.prop].call(this, item);
          }

          if (!columnsCount[item.prop]) {
            newColumns.push(item);
            columnsCount[item.prop] = true;
          }
        }
      }

      if (crud) {
        waitUpdateDic.map((prop) => {
          if (prop) {
            crud.updateDic(prop);
          }
        });
      }

      option.column = newColumns;

      return this.initSlotList(option);
    },

    filterPreSlots() {
      const excludePreSlots = this.excludePreSlots;

      if (excludePreSlots.length > 0) {
        const itemLinks = this.itemLinkList;

        const len = itemLinks.length;

        for (let i = len - 1; i >= 0; i--) {
          const item = itemLinks[i];
          if (excludePreSlots.includes(item.prop)) {
            itemLinks.splice(i, 1);
          }
        }
      }
    },

    findManagePageConfig() {
      if (this.pageCode) {
        ElsManagePageConfigService.findDetail(this.pageCode)

          .then((res) => {
            if (res.data && res.data.code === '200' && res.data.data && res.data.data.configJson) {
              this.configJson = JSON.parse(res.data.data.configJson);
            } else {
              console.log('Failed to load page management configuration, ', res.data || res);
              // this.$message.error(
              //   '查询管理页面配置信息失败, ' + (res.data.message || res.statusText || '')
              // );
            }
          })
          .catch((err) => {
            console.log('Error to load page management configuration, ', err);
            // this.$message.error('查询管理页面配置信息失败, ' + (err.message || ''));
          });
      }
    },

    async filterPageColumn(option) {
      if (!(option && option.column)) {
        return [];
      }

      const customSlotPropItems = {};

      const customSlots = this.customSlots || [];

      customSlots.forEach((item) => {
        if (item.prop) {
          customSlotPropItems[item.prop] = 1;
        }
      });

      const columns = option.column;

      for (const item of columns) {
        if (this.enAbleI18n) {
          this.setI18n(item);
        } else {
          this.setDisplayName(item);
        }

        if (customSlotPropItems[item.prop] && item.slot !== true) {
          item.slot = true;
        }

        await checkDataType4Vxe(item);

        this.checkSlot(item);

        const isRequired = item.isRequired === true || item.isRequired === 'Y';

        if (isRequired) {
          setRequired(item);
        }

        if (
          item.isDisabled === 'Y' ||
          item.isReadOnly === 'Y' ||
          this.readOnly ||
          item.ref ||
          item.disabled === true ||
          item.disabled === 'disabled'
        ) {
          item.disabled = true;
          item.cell = false;
          item.rules = [];
        } else {
          item.cell = true;
        }

        setCellStyle(item, {
          fitColumnWidth: this.fitColumnWidth,
          isManageList: this.isManageList,
          isVxeTable: true,
          readOnly: this.readOnly === true || this.readOnly === 'true'
        });

        item.display = true;
        // 如果是系统必填字段
        if (item && item.isRequired === 'Y') {
          setRequired(item);

          if (item.type === 'varchart' && item.isUserInput === 'N') {
            item.cell = false;
          }

          item.display = true;
        }
      }

      return option;
    },

    async getMaterialHistoryPrice(material) {
      const params = {
        materialNumber: material.materialNumber,
        businessType: this.businessType,
        businessMould: 'enquiry'
      };

      try {
        const res = await PriceRecordService.getPriceByMaterial(params);

        const resData = res.data;

        if (resData.code === '200' && resData.data) {
          return resData.data;
        } else {
          console.log('Failed to load material history price, ', resData);
          return null;
        }
      } catch (err) {
        console.log('Error to load material history price, ', err);
        return null;
      }
    },

    getSelectRefs(type) {
      const refs = [];
      /*
      if (!type) {
        return refs;
      }
      this.finalOption.column.map((item) => {
        const originItem = this.findObject(this.originColumn, item.prop);

        if (originItem.ref && originItem.ref.includes(type)) {
          refs.push(item.prop);
        }
      });
      */

      return refs;
    },

    getShowColumnProps() {
      const showColumnProps = this.showColumnProps || {};

      if (!this.showColumnProps) {
        const columns = this.$refs.crud.option.column;

        columns.forEach((item) => {
          showColumnProps[item.prop] = 1;
        });

        this.showColumnProps = showColumnProps;
      }

      return this.showColumnProps;
    },

    go(item, row) {
      if (window.parent) {
        const params = item.params;
        let url = item.url;
        const len = params.length;
        for (let index = 0; index < len; index++) {
          const param = params[index];
          if (index !== len - 1) {
            url = url + row[param] + '/';
          } else {
            url = url + row[param];
          }
        }

        const router = {
          name: item.label,
          src: url
        };

        const event = {
          name: 'openNewTag',
          props: router
        };

        window.parent.postMessage(event, '*');
      } else {
        window.location.href = item.url;
      }
    },

    handleAddMultipleRow() {
      this.$emit('handleAddMaterialShow');
      this.$emit('handleAddMultipleRow');
    },

    handleAddRow(title, row) {
      this.$emit('handleAddShow');
    },

    handleConfirmColumn(event) {
      if (event.type === 'confirm') {
        const tableFullColumn = event.$table.tableFullColumn;
        const configJson = [];
        tableFullColumn.forEach((item) => {
          if (
            item.type !== 'seq' &&
            item.title !== '操作' &&
            item.title !== LABELS.operation &&
            item.visible === true
          ) {
            configJson.push(item.property);
          }
        });
        const params = {
          templateCode: this.pageCode,
          configJson: JSON.stringify(configJson)
        };

        ElsManagePageConfigService.create(params)

          .then((res) => {
            if (res.data && res.data.statusCode !== '200') {
              console.log('Failed to update page columns.', res.data || res);
            }
          })
          .catch((err) => {
            console.log('Error to update page columns, ', err);
            // this.$message.error('查询管理页面配置信息失败, ' + (err.message || ''));
          });
      }
    },

    handleCopyItemSelector() {
      this.$emit('copy-item');
    },

    handlerCurrentChange(data) {
      this.currentData = data;
      this.$emit('current-change', data);
    },

    handleCustomSlotsChanged(customSlots = []) {
      for (const customSlot of customSlots) {
        if (customSlot && customSlot.prop && customSlot.slotName) {
          this.customSlotItems.push(customSlot || {});
        }
      }
    },

    deleteRow() {
      if (Object.keys(this.currentData).length > 0) {
        const { rowIndex } = this.currentData;

        this.data.splice(rowIndex, 1);
        this.$emit('handleDelRows', this.currentData);
        this.currentData = {};
      }
    },

    enableDeleteRow() {
      return true;
    },

    enableDeleteRows() {
      const enableDeleteFn = this.enableDeleteRowsFn || this.enableDeleteRow;
      return enableDeleteFn();
    },

    handleDeleteRows() {
      const deleteFn = this.deleteSelectedFn || this.deleteRow;
      deleteFn();
    },

    handleDownload(row) {
      const blobUrl = `${baseUrl}/servlet/downloadServlet?filePath=${row.filePath}`;
      const pathList = row.filePath.split('/');
      const index = pathList.length - 1;
      const fileName = pathList[index];
      this.download(blobUrl, fileName);
    },

    // excel 模板: 下载
    handleDownloadExcel() {
      if (this.exportTemplateFn && typeof this.exportTemplateFn === 'function') {
        this.exportTemplateFn();
      } else {
        DownloadAndImportService.downloadBusinessTemplate(
          this.templateNumber,
          this.tempVersion,
          this.templateName
        ).then((res) => {
          const date = dayjs(new Date()).format('YYYYMMDDHHmmss');
          const fileName = `${this.templateName}_${date}.xlsx`;

          simulationDownload(res.data, fileName);
        });
      }
    },

    handleOpenSuperQuery() {
      this.$refs.superQueryModal.show();
    },

    async handleOptionChanged(optionValue, oldOptionValue) {
      const optionValData = cloneDeep(optionValue);
      delete optionValData.data;

      if (!optionValue.column) {
        return false;
      }

      if (oldOptionValue) {
        const oldOptionValData = cloneDeep(oldOptionValue);
        delete oldOptionValData.data;

        const optionString = JSON.stringify(optionValData);
        const oldOptionString = JSON.stringify(oldOptionValData);

        if (optionString !== oldOptionString) {
          await this.changeOption(optionValData);
        }
      } else {
        await this.changeOption(optionValData);
      }
    },

    handlerPageChange(page) {
      this.$emit('page-change', page);
    },

    handleQuote(row) {
      this.$emit('on-quote', row);
    },

    handleSelectChange(selection) {
      if (typeof this.selectionChangeFn === 'function') {
        this.selectionChangeFn(selection);
      }

      this.$emit('selection-change', selection);
    },

    handleShowCostTemplate() {
      this.$emit('show-set-cost-template');
    },

    handleShowLadder() {
      this.$emit('show-set-ladder');
    },

    // 显示供应商选择框
    handleShowSupplierSelector() {
      this.$emit('show-supplier-select');
    },

    // 显示供应商选择框
    handleAddSupplierName() {
      this.$emit('handleAddSupplierName');
    },
    // 隐藏项目信息
    handleHideFieldsName() {
      this.$emit('handleHideFieldsName');
    },


    // 高级查询
    handleSuperQuery(arg, superQueryMatchType) {
      this.$emit('handleSuperQuery', arg, superQueryMatchType);
    },

    handleTaxCodeChange({ $event, value, row }) {
      this.$emit('tax-code-change', { $event, value, row });
    },

    async importExcel(data) {
      if (this.data.length > 0) {
        try {
          await this.confirmImport();
          this.importExcelData(data);
        } catch (err) {
          return false;
        }
      } else {
        this.importExcelData(data);
      }
    },

    importExcelData(data) {
      if (this.importApiFn && typeof this.importApiFn === 'function') {
        this.importExcelDataExtend(data);
      } else {
        this.importExcelDataEmbed(data);
      }
    },

    importExcelDataEmbed(data) {
      const params = Object.assign(
        {
          filePath: data.url || '',
          toElsAccount: this.toElsAccount
        },
        this.customData
      );

      DownloadAndImportService.importExcel(params, this.importUrl)
        .then((res) => {
          if (res.data && res.data.code === '200' && res.data.data) {
            const resData = res.data.data || [];
            this.$emit('importExcel', resData);
          } else {
            console.log('Failed to import excel, ', res.data);
            this.$message.error(res.data.message || LABELS.failedToImportExcel);
          }
        })
        .catch((err) => {
          console.log('Error to import excel, ', err);
          this.$message.error(LABELS.failedToImportExcel);
        });
    },

    importExcelDataExtend(data) {
      const params = {};

      if (this.importApiParamsFn && typeof this.importApiParamsFn === 'function') {
        Object.assign(params, this.importApiParamsFn() || {});
      }

      params.filePath = data.url || '';

      this.importApiFn(params)
        .then((res) => {
          if (res.data && res.data.code === '200' && res.data.data) {
            const resData = res.data.data || [];
            this.$emit('importExcel', resData);
          } else {
            console.log('Failed to import excel, ', res.data);
            this.$message.error(res.data.message || LABELS.failedToImportExcel);
          }
        })
        .catch((err) => {
          console.log('Error to import excel, ', err);
          this.$message.error(LABELS.failedToImportExcel);
        });
    },

    initSlotList(option) {
      const list = option?.column;

      this.itemLinkList.map((item) => {
        const linkItem = this.findObject(list, item.prop);

        if (linkItem !== -1 && linkItem.isReadOnly !== 'Y') {
          linkItem.slot = true;
        }
      });

      return option;
    },

    /* isEnableEditFn 返回值 状态转换: false -> 0 - 禁止编辑, true -> 1 允许编辑, readonly -> 2 只读
     * 增加 readonly 用于二级 slot 显示内容, 参考实现 material
     * 解決 slot 未启用时, vxe-table 行编辑, 没有对应的内容显示，导致单元格空白
     * 参考应用场景: 订单编辑页面
     */
    isEnableEdit(row, property) {
      const state = this.isEnableEditFn(row, property);
      return ENABLE_STATE[`${state}`];
    },

    isUploadAble(item) {
      if (this.readOnly) {
        return false;
      }

      if (item.datatype === 'uploadImg' || item.datatype === 'uploadFile') {
        if (item.isReadOnly !== 'Y') {
          return true;
        }
      }

      return false;
    },

    noEditPreSlot(item) {
      const slot = this.removePreSlot(item.prop);

      if (typeof slot === 'object') {
        delete item.formslot;
        delete item.slot;
        item.type = 'input';
      }
    },

    // excel 模板: 导入文件上传失败
    onFileError(rootFile, file, message, chunk) {
      this.$message.error(LABELS.uploadFailedPleaseTry);
    },

    // excel 模板: 导入文件上传中
    onFileProgress(rootFile, file, chunk) {
      console.log(LABELS.uploading);
    },

    // excel 模板: 导入文件上传成功
    onFileSuccess(rootFile, file, message, chunk) {
      this.$refs.upload.removeFile(file);

      const data = JSON.parse(message)?.data;

      this.importExcel(data);
    },

    onFileUploadError(rootFile, file, message, chunk) {
      this.$message.error(LABELS.uploadFailedPleaseTry);
    },

    onFileUploadSuccess(req, req1, res) {
      const data = JSON.parse(res).data;
      const prop = this.uploadField || this.itemUploadList[0].prop;

      if (prop) {
        this.obj[prop] = data.url;
        this.data[this.tableCur][prop] = data.url;
      }

      this.$forceUpdate();
    },

    onFileUploadProgress() {
      console.log('上传中');
    },

    recoveryPreSlot(prop) {
      const removedPreSlot = this.removedPreSlots[prop];

      if (removedPreSlot) {
        const itemLinkList = this.itemLinkList;

        const slot = itemLinkList.find((item) => {
          return item.prop === prop;
        });

        if (!slot) {
          itemLinkList.push(slot);
        }

        delete this.removedPreSlots[prop];
      }
    },

    recoveryPreSlots() {
      const removedPreSlots = this.removedPreSlots;

      const keys = Object.keys(removedPreSlots);

      if (keys.length > 0) {
        const itemLinkList = this.itemLinkList;

        for (const item of itemLinkList) {
          if (removedPreSlots[item.prop]) {
            delete removedPreSlots[item.prop];
          }
        }

        for (const prop in removedPreSlots) {
          itemLinkList.push(removedPreSlots[prop]);
        }

        this.removedPreSlots = {};
      }
    },

    removePreSlot(prop) {
      let index = 0;
      let propIndex = -1;
      let slot = null;

      const itemLinkList = this.itemLinkList;

      for (const item of itemLinkList) {
        const params = item.params || [];

        if (item.prop === prop || params.indexOf(prop) > -1) {
          propIndex = index;

          break;
        }

        index = index + 1;
      }

      if (propIndex > -1) {
        const removedSlots = this.itemLinkList.splice(propIndex, 1);

        slot = removedSlots[0];

        this.removedPreSlots[prop] = slot;
      }

      return slot;
    },

    resetPreSlot(prop) {
      let index = 0;
      let propIndex = -1;

      for (const item of this.itemLinkList) {
        const params = item.params || [];

        if (item.prop === prop || params.indexOf(prop) > -1) {
          propIndex = index;

          delete item.noEdit;

          break;
        }

        index = index + 1;
      }

      if (propIndex > -1) {
        // this.itemLinkList.splice(propIndex, 1);
      }
    },

    rowDelete(row, index) {
      this.$emit('handelDeleteRow', row);
      this.data.splice(index, 1);
    },

    rowUpdate({ row, rowIndex, $rowIndex, column, columnIndex, $columnIndex, field }) {
      // rowIndex: full data 中的 row index
      // $rowIndex: 虚拟列表切片中的 row index

      const data = this.data[rowIndex];

      if (row.queryUuid) {
        data.queryUuid = row.queryUuid;
      }

      // TODO: taxRate 为空，强行添加 taxCode
      if (data && !data.taxRate && data.taxCode) {
        data.taxRate = data.taxCode;
      }

      if (typeof this.rowUpdateProcFn === 'function') {
        // 如果返回的flag为-1，则代表改行数据有条件未满足，不能保存。
        const flag = this.rowUpdateProcFn(data);
        if (flag === -1) {
          return;
        }
      }

      this.$emit('row-update', {
        row,
        rowIndex,
        $rowIndex,
        column,
        columnIndex,
        $columnIndex,
        field
      });
    },

    saveSelected(row, list, option) {
      const item = list[0];

      if (option.isOption === true) {
        const dataValue = item[option.dataValueProp];
        const dataName = item[option.dataNameProp];

        if (typeof dataValue !== 'undefined' && typeof row[option.valueProp] !== 'undefined') {
          row[option.valueProp] = dataValue;
        }

        if (typeof dataName !== 'undefined') {
          const nameProp = option.nameProp;

          if (nameProp && typeof row[nameProp] !== 'undefined') {
            row[nameProp] = dataName;
          } else {
            const aliasProps = option.aliasProps || [];
            for (const aliasProp of aliasProps) {
              if (typeof row[aliasProp] !== 'undefined') {
                row[aliasProp] = dataName;
                break;
              }
            }
          }
        }
      } else {
        const params = option;
        row[params[0]] = item[params[2]];
        row[params[1]] = item[params[3]];
      }

      if (
        this.selectedItemProcFn &&
        this.selectedItemProcFn[option.valueProp] &&
        typeof this.selectedItemProcFn[option.valueProp] === 'function'
      ) {
        this.selectedItemProcFn[option.valueProp]({ row, list, option });
      }

      if (row.prop) {
        const refs = this.getSelectRefs(row.prop);

        if (refs.length) {
          this.setRefs(refs, row, item);
        }
      }
    },

    async selectedRowMaterails(row, materialList) {
      if (materialList.length > 0) {
        const checkResult = this.checkAddedMaterials(materialList);

        if (checkResult.existsList.length > 0) {
          if (checkResult.message) {
            this.$message.warning(checkResult.message, 5);
          }

          return;
        }

        const refs = this.getSelectRefs('materialNumber');
        const addMaterialList = checkResult.addList;

        for (const materialItem of addMaterialList) {
          let material = { ...materialItem };

          // 选择物料后删除 $index, 避免对话框选中的数据带回来的 $index 污染表格的数据中的 $index
          delete material.$index;

          if (
            this.afterSelectedMaterialProcFn &&
            typeof this.afterSelectedMaterialProcFn === 'function'
          ) {
            try {
              const afterResult = await this.afterSelectedMaterialProcFn(
                material,
                this.extendData,
                row
              );
              if (afterResult) {
                material = afterResult;
              }
            } catch (err) {
              continue;
            }
          }

          if (this.isShowHistoryPrice) {
            const historyPrice = await this.getMaterialHistoryPrice(material);

            if (typeof historyPrice === 'object') {
              material.historyPriceIncludingTax = historyPrice.priceIncludingTax;
              material.historyPriceExcludingTax = historyPrice.priceExcludingTax;
            }
          }

          this.setRefs(refs, row, material);

          // 创建. 修改采购申请(新增的行将物料的uuid放入queryUuid字段), 重新选择了物料也要更新 queryUuid
          row.queryUuid = material.uuid;
          row.materialNumber = material.materialNumber;

          // 新选择的物料, 不要 uuid，也避免用物料的 uuid 覆盖表格数据自身的 uuid
          delete material.uuid;

          const materialObject = row;
          Object.assign(materialObject, material);

          // 设置与物料编辑关联的表单编辑状态
          // this.disableOpenForms(item.materialNumber);
        }
      } else {
        this.$message.warning(LABELS.pleaseSelectMaterials);
      }
    },

    setRefs(list, row, origin) {
      list.map((item) => {
        if (origin[item]) {
          row[item] = origin[item];
        }
      });
    },

    setRequired(item) {
      this.requiredColumns[item.prop] = 1;

      return setRequired(item);
    },

    setUploadField(prop) {
      this.uploadField = prop;
    },

    /**
     * 切换是否已选中
     * @deprecated since version 1.0.0
     * @see clearSelection
     */
    toggleSelection() {
      alert(
        'toggleSelection is obsoleted in row-vxe-provider component. Please use clearSelection.'
      );
    },

    async validAllEvent() {
      await this.$refs.crud.validAllEvent();
    },

    async validateEvent() {
      return await this.$refs.crud.validateEvent();
    },

    vxeSelectDone(data, selectedRow) {
      this.$emit('selectDone', data, selectedRow);
    }
  }
};
</script>
<style lang="scss">
@import './required.scss';
@import './list.scss';
</style>
