<template>
  <el-dialog title="导入数据" :close-on-click-modal="false" :visible.sync="visible" class="JNPF-dialog JNPF-dialog_center JNPF-dialog-export" lock-scroll width="1000px">
    <el-steps :space="330" :active="active" align-center finish-status="success">
      <el-step title="导入Excel文件"></el-step>
      <el-step title="字段关联"></el-step>
      <el-step title="完成导入"></el-step>
    </el-steps>
    <el-form label-position="top" style="margin-top: 20px">
      <el-form-item v-show="active === 0">
        <el-upload
          class="upload-demo"
          ref="uploadFile"
          drag
          :on-success="onSuccess"
          :before-upload="beforeUploadChange"
          accept=".xlsx,.xls"
          :action="define.comUploadUrl"
          :headers="{ 'Blade-Auth': Authorization }"
        >
          <i class="el-icon-upload"></i>
          <div class="el-upload__text">将文件拖到此处，或<em>点击上传</em></div>
          <div class="el-upload__tip" slot="tip">只能上传xlsx/xls文件</div>
          <div v-if="uploadFlag" class="el-upload__tip" slot="tip">正在上传中，请稍后...</div>
        </el-upload>
      </el-form-item>
      <el-form-item v-show="active === 1">
        <el-table :data="fileList" border height="530" :span-method="cellMerge" ref="fileList111">
          <el-table-column width="80" align="center">
            <template slot-scope="scope">
              {{ scope.$index }}
            </template>
          </el-table-column>
          <template v-for="(item, index) in fileListCols">
            <el-table-column v-if="item.merge_column && item.merge_column.length" :key="index" :label="item.title" align="center" minWidth="120">
              <el-table-column v-for="(item1, index1) in item.merge_column" :key="index1" :label="item1.title" align="center" minWidth="120">
                <template slot-scope="scope">
                  {{ scope.row[item.title + ' ' + item1.title] }}
                </template>
              </el-table-column>
            </el-table-column>
            <el-table-column v-else :key="index" :label="item.title" align="center" minWidth="120">
              <template slot-scope="scope">
                {{ scope.row[item.title] }}
              </template>
            </el-table-column>
          </template>
        </el-table>
      </el-form-item>
      <el-form-item v-show="active === 2">
        <div style="display: flex; justify-content: space-between; margin: 10px 0">
          <el-tag type="info">文件名称：{{ fileName }}</el-tag>
          <div>是否导入表头：<el-switch v-model="withHeader" :disabled="isMerge" active-color="#13ce66" :active-value="false" :inactive-value="true"></el-switch></div>
        </div>
        <div style="display: flex; justify-content: space-between; margin: 10px 0">
          <div>备注：<el-input v-model="fileContname" placeholder="请填写备注" style="width: 300px"></el-input></div>
          <div v-if="serialShow">
            <span>使用流水号规则</span>
            <el-tooltip
              style="cursor: pointer"
              effect="dark"
              :content="'当前表单存在流水号组件 「 ' + serialLabel + ' 」，默认开启使用流水号规则生成流水号，字段绑定无效，关闭后可自定义导入内容。'"
              placement="top"
            >
              <i class="el-icon-question" />
            </el-tooltip>
            <span>：</span>
            <el-switch v-model="serialFlag" active-color="#13ce66"></el-switch>
          </div>
          <!--          <div>-->
          <!--            是否清空原有数据：<el-switch v-model="coverData" active-color="#13ce66" :active-value="true" :inactive-value="false"></el-switch>-->
          <!--          </div>-->
        </div>
        <el-table :data="fileList" border highlight-current-row height="430" :span-method="cellMerge">
          <el-table-column width="80" align="center">
            <template slot-scope="scope">
              <div v-if="scope.$index === 0">字段绑定</div>
              <div v-else>{{ scope.$index }}</div>
            </template>
          </el-table-column>
          <template v-for="(item, index) in fileListCols">
            <el-table-column v-if="item.merge_column && item.merge_column.length" :key="index" :label="item.title" align="center" minWidth="120">
              <el-table-column v-for="(item1, index1) in item.merge_column" :key="index1" :label="item1.title" align="center" minWidth="120">
                <template slot-scope="scope">
                  <el-form-item v-if="scope.$index === 0">
                    <el-select v-model="associationLists[item1.index].fieldId" placeholder="请选择关联字段" clearable>
                      <el-option v-for="item2 in columnList" :key="item2.propId" :value="item2.propId" :disabled="getDisabledSelect(item2.propId)" :label="item2.label"> </el-option>
                    </el-select>
                  </el-form-item>
                  <span v-else>{{ scope.row[item.title + ' ' + item1.title] }}</span>
                </template>
              </el-table-column>
            </el-table-column>
            <el-table-column v-else :key="index"  align="center" minWidth="120">
              <template slot="header" slot-scope="scope">
                {{item.title}}
                <template v-if="getIsRelationAssociation(associationLists[item.index])">
                  <el-checkbox v-model="associationLists[item.index].isDataFrom" :true-label="1" :false-label="0">
                    转化成key
                    <el-tooltip style="cursor: pointer" effect="dark" :content="'勾选后将自定转化该列导入数据为key值'" placement="top">
                      <i class="el-icon-question" />
                    </el-tooltip>
                  </el-checkbox>
                </template>
              </template>
              <template slot-scope="scope">
                <el-form-item v-if="scope.$index === 0">
                  <el-select v-model="associationLists[item.index].fieldId" placeholder="请选择关联字段" clearable>
                    <el-option v-for="item2 in columnList" :key="item2.propId" :value="item2.propId" :disabled="getDisabledSelect(item2.propId)" :label="item2.label"> </el-option>
                  </el-select>
                </el-form-item>
                <span v-else>{{ scope.row[item.title] }}</span>
              </template>
            </el-table-column>
          </template>
        </el-table>
      </el-form-item>
    </el-form>
    <span slot="footer" class="dialog-footer">
      <el-button @click="closeClick">{{ $t('common.cancelButton') }}</el-button>
      <el-button v-if="active === 1" @click="removeClick()">上一步</el-button>
      <el-button
        v-if="active === 1"
        @click="
          active = 2
          fileList.unshift({})
          getSpanArr(fileList, mergerItems)
        "
        >下一步</el-button
      >
      <el-button type="primary" :loading="btnLoading" :disabled="active !== 2" @click="downLoad">导 入</el-button>
    </span>
  </el-dialog>
</template>

<script>
import { getToken } from '@/utils/auth'
import { read, utils } from 'xlsx'
import { cubeFieldList } from '@/api/workFlow/FlowEngine'
import { deepClone } from '@/utils'
import moment from 'moment/moment'
import { getReadExcelHeader } from '@/api/onlineDev/visualDev'
import { systemComponents } from '@/components/Generator/generator/config'
export default {
  data() {
    return {
      visible: false,
      active: 0,
      btnLoading: false,
      type: 0,
      columns: [],
      checkAll: true,
      isIndeterminate: false,
      columnList: [],
      columnLists: [],
      Authorization: 'bearer ' + getToken(),
      files: [],
      fileList: [],
      fileListCols: [],
      fileName: '',
      listValue: '',
      associationLists: [],
      withHeader: true,
      coverData: false,
      fileContname: '',
      uploadFlag: false,
      serialShow: false,
      serialFlag: true,
      dbLinkId: '',
      serialFileId: null,
      serialLabel: '',
      serialgz: [],
      isMerge: false,
      mergerItems: [],
      systemComponents
    }
  },
  methods: {
    // serialFlagSwitch(){
    //   this.getCubeFieldList(this.dbLinkId)
    //   this.associationLists.forEach((i,k)=>{
    //     if (i.fieldId === this.serialFileId){
    //       this.$set(i,'fieldId',null)
    //     }
    //   })
    // },
    init(columnList, dbLinkId, serialgzItme) {
      this.visible = true
      this.serialShow = false
      //查询当前组件是否存在流水号控件 找到propId
      let serialRow = columnList.find((o) => o.jnpfKey === 'serialNumber')
      if (serialRow) {
        this.serialShow = true
        this.serialgz = serialgzItme.serialgz
        this.serialFileId = serialRow.propId
        this.serialLabel = serialRow.label
      }
      // this.columnLists = columnList
      // this.columns = columnList.map(o => o.prop)
      if (dbLinkId) {
        this.dbLinkId = dbLinkId
        // this.getCubeFieldList(dbLinkId,columnList)
      }
      const filteredData = columnList.filter((item) => {
        return !!(item.propId && item.config && !systemComponents.some((obj) => obj.__config__.jnpfKey === item.config.jnpfKey))
      })
      this.columnList = this.flattenData(filteredData)
    },
    getIsRelationAssociation(row){
      if (!row && row.fieldId) return;
      let activeItem = this.columnList.find((o => o.propId === row.fieldId))
      if (!activeItem) return;
      return activeItem.params.compoentConfig.relationData.isText || false
    },
    flattenData(data) {
      let result = []
      data.forEach((item) => {
        if (item.children && item.children.length > 0) {
          // 将子级的标签调整为父级的标签加上子级的标签
          item.children.forEach((child) => {
            if (!systemComponents.some((obj) => obj.__config__.jnpfKey === child.jnpfKey)) {
              result.push({
                label: `${item.label} - ${child.label}`,
                title: `${item.title} - ${child.title}`,
                prop: child.prop,
                field: child.field,
                propId: child.propId
              })
            }
          })
        } else {
          result.push(item) // 子级为空的父级保留
        }
      })
      return result
    },
    getDisabledSelect(val) {
      let res = false
      this.associationLists.filter((i, k) => {
        if (i.fieldId && i.fieldId === val) {
          res = true
        }
      })
      return res
    },
    beforeUploadChange(file) {
      this.files = { 0: file }
      const fileType = file.name.substring(file.name.lastIndexOf('.') + 1)
      const extension = fileType === ''
      const extension2 = fileType === 'xlsx' || 'xls'
      const isLt2M = file.size / 1024 / 1024 < 2

      if (!extension && !extension2) {
        this.$message.error('上传文件只能是 xls或xlsx 格式!')
        return false
      }
      if (!isLt2M) {
        this.$message.error('上传文件大小不能超过 2MB!')
      }
      this.uploadFlag = true
      return (extension || extension2) && isLt2M
    },
    onSuccess(res) {
      let simulationData = {}
      this.mergerItems = []
      if (res.code === 200) {
        this.uploadFlag = true
        this.fileName = res.msg
        getReadExcelHeader({ file: res.msg }).then((r) => {
          if (r.data.code !== 200) return
          simulationData = r.data.data
          this.isMerge = simulationData.is_merge
          const fileReader = new FileReader()
          fileReader.onload = (ev) => {
            try {
              const data = ev.target.result
              const workbook = read(data, { type: 'binary', cellDates: true, dateNF: 'yyyy-mm-dd' })
              //取第一张表
              const wsname = workbook.SheetNames[0]
              const wss = workbook.Sheets[wsname]

              if (simulationData.is_merge) {
                let simulation = simulationData.column
                // 遍历数据，删除满足条件的 merge_column 属性
                this.fileListCols = simulation.map((item) => {
                  if (item.merge_column && item.merge_column.length === 1) {
                    const childTitle = item.merge_column[0].title
                    if (!childTitle || childTitle === item.title) {
                      this.mergerItems.push({ prop: item.title, columnIndex: item.index, spanArr: [], pos: 0 })
                      // 如果满足条件，删除 merge_column 属性
                      const { merge_column, ...rest } = item
                      return rest
                    }
                  }
                  return item
                })
                const loop = (list) => {
                  for (let i = 0; i < list.length; i++) {
                    let item1 = list[i]
                    if (!item1) return
                    if (item1.merge_column && Array.isArray(item1.merge_column) && item1.merge_column.length) {
                      loop(item1.merge_column)
                    } else {
                      this.associationLists.push({ fieldName: item1.title, fieldId: null, fieldKey: item1.index, isDataFrom: 0 })
                    }
                  }
                }
                loop(this.fileListCols)
                this.getMoreHeaderRow(wss)
              } else {
                //生成json表格
                const ws = utils.sheet_to_row_object_array(workbook.Sheets[wsname], {
                  raw: false
                })
                //截取前六位展示預覽
                this.fileList = ws.slice(0, 6)
                // this.fileList.unshift({})
                //获取表头
                let filteredData = this.getHeaderRow(wss)
                this.fileListCols = filteredData.map((o, k) => {
                  return {
                    title: o,
                    index: k
                  }
                })
                this.associationLists = this.fileListCols.map((i, k) => {
                  return {
                    fieldName: i.title,
                    fieldId: null,
                    fieldKey: i.index,
                    isDataFrom: 0
                  }
                })
              }
              this.$nextTick(() => {
                //如果字段和表头相同可以直接绑定
                function asscListFun(data, Lists) {
                  data.forEach((item, index) => {
                    if (item.children && item.children.length) {
                      asscListFun(item.children, Lists)
                    } else {
                      Lists.forEach((i, k) => {
                        data.forEach((v, c) => {
                          if (i.fieldName === v.title) {
                            i.fieldId = v.propId
                          }
                        })
                      })
                    }
                  })
                }
                asscListFun(this.columnList, this.associationLists)
                this.active = 1
              })
            } catch (e) {
              return false
            }
          }
          fileReader.readAsBinaryString(this.files[0])
        })
      }
    },
    getMoreHeaderRow(wss) {
      let result = []
      // 获取合并单元格对象
      const merges = wss['!merges'].map((m) => (typeof m == 'string' ? utils.decode_range(m) : m))
      let HEADERS = 2 // 如果不是从第三行开始，修改这个2的值
      const aoa = utils.sheet_to_json(wss, {
        header: 1, //生成数组
        raw: false,
        cellDates: true,
        dateNF: 'yyyy-mm-dd'
      })
      // 通过连接字段名称来创建标题名称
      let R = 0,
        headers = [],
        range = utils.decode_range(wss['!ref'])
      for (let C = 0; C <= range.e.c; ++C) {
        headers[C] = ''
        for (R = 0; R < HEADERS; ++R) {
          let m = merges.find((m) => m.s.c <= C && C <= m.e.c && m.s.r <= R && R <= m.e.r)
          if (m) {
            if (aoa[m.s.r][m.s.c] != null) {
              headers[C] += ' ' + aoa[m.s.r][m.s.c]
              R = m.e.r
            }
          } else {
            if (aoa[R][C] != null) headers[C] += ' ' + aoa[R][C]
          }
        }
        if (headers[C] === '') headers[C] = '__EMPTY_' + C
        else headers[C] = headers[C].slice(1)
      }
      //在此处更改头数组
      //处理其余行
      for (R = HEADERS; R < aoa.length; ++R) {
        let row = []
        //从合并的左上单元格提取值
        for (let C = 0; C <= range.e.c; ++C) {
          let m = merges.find((m) => m.s.c <= C && C <= m.e.c && m.s.r <= R && R <= m.e.r)
          if (m && aoa[m.s.r][m.s.c] != null) row[C] = aoa[m.s.r][m.s.c]
          else if (!m && aoa[R][C] != null) row[C] = aoa[R][C]
        }
        //构造对象和推送
        result.push(Object.fromEntries(headers.filter((h, i) => row[i] != null).map((h, i) => [h, row[i]])))
      }
      this.fileList = result.slice(0, 6)
      this.getSpanArr(this.fileList, this.mergerItems)
    },
    getHeaderRow(sheet) {
      const headers = []
      /* sheet['!ref']表示所有单元格的范围，例如从A1到F8则记录为 A1:F8*/
      const range = utils.decode_range(sheet['!ref'])
      let C,
        R = range.s.r /* 从第一行开始 */
      /* 按列进行数据遍历 */
      for (C = range.s.c; C <= range.e.c; ++C) {
        /* 查找第一行中的单元格 */
        const cell = sheet[utils.encode_cell({ c: C, r: R })]
        let hdr = 'UNKNOWN ' + C // <-- 进行默认值设置
        if (cell && cell.t) hdr = utils.format_cell(cell)
        headers.push(hdr)
      }
      return headers
    },
    //取消
    closeClick() {
      if (this.active > 0) {
        this.$confirm('此操作将删除已导入的文件, 是否继续?', '提示', {
          confirmButtonText: '确定',
          cancelButtonText: '取消',
          type: 'warning'
        })
          .then(() => {
            this.uploadFlag = false
            this.fileList = []
            this.associationLists = []
            this.fileListCols = []
            this.$nextTick(() => {
              this.$refs.uploadFile.clearFiles()
              this.active = 0
              this.visible = false
            })
          })
          .catch(() => {})
      } else {
        this.visible = false
      }
    },
    //返回上一步操作
    removeClick() {
      this.$confirm('此操作将删除已导入的文件, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
      })
        .then(() => {
          this.uploadFlag = false
          this.fileList = []
          this.associationLists = []
          this.fileListCols = []
          this.mergerItems = []
          this.$nextTick(() => {
            this.$refs.uploadFile.clearFiles()
            this.active = 0
          })
        })
        .catch(() => {})
    },
    getSerialincNumberData(serialgz) {
      let copySet = deepClone(serialgz)
      copySet.forEach((i, k) => {
        //根据设置生成数据
        if (i.type === 'createTime') {
          this.$set(i, 'chars', moment().format(i.format))
        }
      })
      return { _serialNumberConfig: copySet }
    },
    downLoad() {
      this.btnLoading = true
      let data = this.associationLists
        .map((o, i) => {
          if (o.fieldId) {
            return {
              fieldId: o.fieldId,
              index: o.fieldKey,
              isDataFrom:o.isDataFrom
            }
          }
        })
        .filter((l) => l !== undefined)
      if (this.serialFlag && this.serialFileId) {
        data = data.filter((o) => o.fieldId !== this.serialFileId)
        let serialincNumberData = this.getSerialincNumberData(this.serialgz)
        let serialData = { fieldId: this.serialFileId, index: -1, ...serialincNumberData }
        data.push(serialData)
      }
      this.$emit('UploadChange', { file: this.fileName, list: data, truncate: this.coverData, withHeader: this.withHeader, name: this.fileContname, isMerge: this.isMerge })
    },
    cellMerge({ row, column, rowIndex, columnIndex }) {
      //表格合并的方法
      let item = this.mergerItems.find((item) => item.columnIndex + 1 === columnIndex)
      if (item) {
        const _row = item.spanArr[rowIndex]
        const _col = _row > 0 ? 1 : 0
        return {
          rowspan: _row,
          colspan: _col
        }
      } else {
        return {
          rowspan: 1,
          colspan: 1
        }
      }
    },
    getSpanArr(data, array) {
      //循环数据处理
      for (let n = 0; n < array.length; n++) {
        array[n].spanArr = [] //数据清空(重新调此方法的时候需要清空上一次的数据)
        for (let i = 0; i < data.length; i++) {
          if (i === 0) {
            array[n].spanArr.push(1)
            array[n].pos = 0
          } else {
            // 判断当前元素与上一个元素是否相同
            if (data[i][array[n].prop] === data[i - 1][array[n].prop]) {
              array[n].spanArr[array[n].pos] += 1
              array[n].spanArr.push(0)
            } else {
              array[n].spanArr.push(1)
              array[n].pos = i
            }
          }
        }
      }
    }
  }
}
</script>
<style scoped></style>
