<template>
  <div class="table-wrapper" @keydown="handlekeyDownKeys">
    <template v-if="config.data.length">

      <!-- 工具栏 -->
      <toolBarSection  v-if="!disabled" :cell="selectCell?selectCell:selectedCells"  @openConDialog="openConDialog"  @cellMerge="toolCellMergeFun"
        :echoParameter="{hasMergedCell}"/>
      
      <!-- 公式显示区 -->
      <div class="formula-wrapper" v-if="!disabled">
        <span style="flex-shrink: 0;color:#C0C4CC">{{$t('OnlineExcelPage.formula_lable')}}</span>
        <el-input
          v-if="selectCell&&selectCell.DataType===6"
          v-model="selectCell.Value"
          @change="updateValueByFormula"
        />
      </div>

      <table
        width="auto"
        border="0"
        class="table"
        id="myTable"
        :style="disabled ? 'width:100%' : ''"
        ref="tableRef"
        style="position: relative;"
        @mousedown="selectCellHandle"
      >
        <thead>
          <tr>
            <!-- 行头 -->
            <th class="th-tg sm"></th>

            <!-- 列头 -->
            <th
              v-for="(item, index) in columnHeader"
              :key="index"
              class="th-tg th-col"
              :data-cindex="item"
              :data-rindex="-1"
              @contextmenu.prevent="rightClickHandle"
            >
              {{ item }}
            </th>
          </tr>
        </thead>

        <tbody>
          <tr v-for="(row, index) in config.data" :key="index">
            <!-- 行头 -->
            <th
              class="th-tg th-row sm"
              @contextmenu.prevent="rightClickHandle"
              :data-rindex="rowHeader[index]"
              :data-cindex="-1"
            >
              {{ rowHeader[index] }}
            </th>

            <td
              v-for="(cell, cell_index) in row"
              :key="`${index}_${cell_index}`"
              :data-rindex="rowHeader[index]"
              :data-cindex="columnHeader[cell_index]"
              :data-datarindex="index"
              :data-datacindex="cell_index"
              :style="cell.ShowStyle?getShowCss(cell.ShowStyle):{}"
              :initIndex="initIndex(index,cell_index,rowHeader[index],columnHeader[cell_index])"
              :data-key="cell.Uid"
              v-show="!cell.merData || cell.merData.type!=='merged'"
              :colspan="(cell.merData && cell.merData.type=='merge' && cell.merData.mer)?cell.merData.mer.colspan || 1:1"
              :rowspan="(cell.merData && cell.merData.type=='merge' && cell.merData.mer)?cell.merData.mer.rowspan || 1:1"
              @click="clickCell($event, cell)"
              @dblclick="dblClickCellHandle($event,cell)"
              @contextmenu.prevent="rightClickHandle($event,cell)"
              @mouseenter="getRelationEdbInfo(cell)"
              @copy="copyCellHandle($event,cell)"
              @paste="pasteCellHandle($event,cell)"
            >
            <!-- 插入单元格禁止编辑 -->
            <!-- [4,5,6,7,8].includes(cell.DataType)&&!cell.CanEdit -->
            <template 
              v-if="!cell.CanEdit
              ||disabled
              ||(cell.DataType===1&&[1,2].includes(cell.DataTimeType))"
            >
              
              <!-- 单元格类型5 7显示指标浮窗 -->
              <el-popover
                v-if="[5,7].includes(cell.DataType)&&!disabled"
                placement="top-start"
                width="350"
                trigger="hover"
              >
                <ul>
                  <li style="display:flex;margin:10px;">
                    <label style="min-width:80px;">{{$t('OnlineExcelPage.indicator_name_lbl')}}</label> 
                    {{cellrelationEdbInfo.EdbName}}
                  </li>
                  <li style="display:flex;margin:10px;">
                    <label style="min-width:80px;">{{$t('OnlineExcelPage.lastest_date_lab')}}</label> 
                    {{cellrelationEdbInfo.LatestDate}}
                  </li>
                  <li style="display:flex;margin:10px;">
                    <label style="min-width:80px;">{{$t('Table.edb_id')}}</label> 
                    {{cellrelationEdbInfo.EdbCode}}
                  </li>
                </ul>
                <span
                  slot="reference"
                  :data-rindex="rowHeader[index]"
                  :data-cindex="columnHeader[cell_index]"
                  :data-datarindex="index"
                  :data-datacindex="cell_index"
                  :data-key="cell.Uid"
                >{{ cell.ShowStyle?cell.ShowFormatValue:cell.ShowValue }}</span>
              </el-popover>

              <!-- 数字格式化显示 -->
              <span 
                v-else-if="cell.ShowStyle"
                :data-rindex="rowHeader[index]"
                :data-cindex="columnHeader[cell_index]"
                :data-datarindex="index"
                :data-datacindex="cell_index"
                :data-key="cell.Uid"
              >
                {{isShowFormat(cell.ShowStyle)?cell.ShowFormatValue:cell.DataTime?cell.ShowValue:[7,5].includes(cell.DataType)?cell.ShowValue:cell.Value}}
              </span>

              <span
                :data-rindex="rowHeader[index]"
                :data-cindex="columnHeader[cell_index]"
                :data-datarindex="index"
                :data-datacindex="cell_index"
                :data-key="cell.Uid"
                v-else
              >{{ cell.ShowValue }}</span>
            </template>

              <el-autocomplete
                v-else
                v-model="cell.Value"
                :ref="`inputRef${cell.Uid}`"
                popper-class="edb-select-popover"
                :data-key="cell.Uid"
                :data-rindex="rowHeader[index]"
                :data-cindex="columnHeader[cell_index]"
                :data-datarindex="index"
                :data-datacindex="cell_index"
                :fetch-suggestions="searchTarget"
                @change.native="changeVal($event, cell)"
                @keydown.native="keyEnterHandle($event,cell)"
                @blur="() => {$set(cell,'CanEdit',false)}"
              >
                <!-- @select="selectTarget($event,cell)"
                  @click="clickCell($event, cell)"
                :highlight-first-item="cell.DataType===2"
                 -->
                <template slot-scope="scope">
                    <edbDetailPopover :info="scope.item">
                      <div slot="reference" v-if="cell.DataType===2" class="edb-item">
                         <span class="edb-item-name text_oneLine">{{ scope.item.EdbName }}</span>
                         <i class="el-icon-check" style="color:#0052D9;font-size:18px;"/>
                      </div>

                      <div slot="reference" v-else>{{ scope.item.EdbName }}</div>
                    </edbDetailPopover>
                </template>
              </el-autocomplete>
            </td>
          </tr>
        </tbody>
        <!-- 选区 -->
        <div ref="selectionRef" id="selection-id"
        style="position: absolute;border: 2px solid #0052D9;background-color: rgba(0, 82, 217, 0.1);visibility: hidden;z-index: 1;pointer-events: none;"></div>
        <!-- 行列选中样式 -->
        <div ref="rowColSelectRef" id="row-col-select" 
        style="position: absolute;border-color: #18ad18;border-style: solid;background-color: transparent;visibility: hidden;z-index: 1;pointer-events: none;"></div>
      </table>

      <!-- 右键菜单 -->
      <div class="contextMenu-wrapper" id="contextMenu-wrapper" @mouseleave="()=>{activeNames=[];hideContextMenu()}">
        <div :class="['item',{'deletesty': menu.key==='reset'}]" v-for="menu in config.contextMenuOption" :key="menu.key" @click="handleContext(menu.key)">
          <span v-if="!menu.children">{{menu.label}}</span>
          
          <el-collapse v-model="activeNames" @change="handleChange" v-if="menu.children" class="mixed-edb-slide-collapse">
            <el-collapse-item name="1">
              <template slot="title">
                 {{menu.label}}
              </template>
              
              <div class="subMenu-wrapper">
                <div slot="reference" class="item" v-for="submenu in menu.children" :key="submenu.key" @click="edbCalculateInsertOpen(submenu)">
                    <el-popover
                      width="300"
                      trigger="hover"
                      placement="right"
                    >
                      <div v-html="formulaTip.get(submenu.fromEdbKey)"></div>
                      <div slot="reference" style="width:100%">{{submenu.label}}</div>   
                    </el-popover>
                </div>
              </div>
            </el-collapse-item>
          </el-collapse>  

        </div>
      </div>
    </template>

    <div class="nodata" v-else>
      <tableNoData :text="$t('Table.prompt_slogan')"/>
    </div>

    <!-- 选择指标 -->
    <selectTargetValueDia
      :isShow.sync="isSelectTargetValueDialog"
      :info="insertTargetValueInfo"
      @insert="insertSelectData"
      ref="selectTargetValueRef"
    />

    <!-- 插入系统/指标日期弹窗 -->
    <insertDateDia
      :isShow.sync="isInsertDateDialog"
      :info="insertDateInfo"
      @insert="insertDatehandle"
    />

    <!-- 指标计算弹窗 -->
    <calculateEdbDia
      ref="calculateEdbDiaRef"
      :isShow.sync="isInsertCalculate"
      :info="insertCalculateInfo"
      @insert="insertCalculateData"
    />

    <!-- 日期计算弹窗 -->
    <calculateDateDia
      ref="calculateDateDiaRef"
      :isShow.sync="isInsertCalculateDate"
      :info="insertCalculateDateInfo"
      @insert="insertCalculateDateValue"
    />

    <condition-dia
      :chooseCell="selectCell?selectCell:selectedCells"
      ref="conditionDia" 
      @changeRule="getExcelRule"
      @deleteRule="deleteExcelRule"
      @editRule="editExcelRule"
    />
  </div>
</template>
<script>
import {
  getRowHeaderCode,
  getColumnHeaderCode,
  selectCellStyle,
  selectMoreCellStyle,
  setRelationStyle,
  getRightClickMenu,
  checkDateFormat,
  setFocus,
  findCellByKey,
  resetRelationStyle,
  resetDialogCellStyle,
  extractFactorsFromFormula,
  findCellByFactorMixed,
  splitString,
  toUpperCase,
  findCellKeyByFactor,
  isNumberVal,
  transDecimalPlace,
  resetStyle
} from "../common/customTable";
import * as sheetInterface from "@/api/modules/sheetApi.js";
import { dataBaseInterface } from '@/api/api.js';
import md5 from '@/utils/md5.js';
import selectTargetValueDia from './selectTargetValueDia.vue';
import insertDateDia from './insertDateDia.vue';
import calculateEdbDia from './calculateEdbDia.vue';
import calculateDateDia from './calculateDateDia.vue';
import toolBarSection from './toolBarSection.vue';
import conditionDia from './conditionDia.vue'
import { formulaTip } from '@/views/dataEntry_manage/databaseComponents/util';
import conditionTableMixin from "../mixins/conditionTableMixin.js"
export default {
  mixins:[conditionTableMixin],
  props: {
    disabled: { //是否只预览
      type: Boolean,
      default: false,
    },
    sourceFrom:{
      type: Object,
      default: ()=>{
        return {}
      },
    }
  },
  components: {
    conditionDia,
    selectTargetValueDia,
    insertDateDia,
    calculateEdbDia,
    calculateDateDia,
    toolBarSection
  },
  computed: {
    //列头
    columnHeader() {
      return getColumnHeaderCode(
        this.config.data[0] ? this.config.data[0].length : 0
      );
    },
    //行头
    rowHeader() {
      let total_length = this.config.data.length;
      // console.log(this.config.data)
      return getRowHeaderCode(total_length);
    },
  },
  watch:{
    'config.data':{
      handler(newVal){
        if(!this.disabled && this.hasInit){
          this.$emit("autoSave")
        }
      },
      deep:true
    },
    insertRelationArr:{
      handler(newVal){
        if(!this.disabled && this.hasInit){
          this.$emit("autoSave")
        }
      },
      deep:true
    },
    'endCell.row':{
      handler(newVal){
        this.setSelectionStyle()
      }
    },
    'endCell.column':{
      handler(newVal){
        this.setSelectionStyle()
      }
    }
  },
  data() {
    return {
      config: {
        /* 单元格类型 
          1手动日期格 DataTimeType 0 /系统日期导入格 DataTimeType 1  /指标日期导入格 DataTimeType 2
          2指标格 //eta1.5.6又弃用了
          3自定义输入 
          4插入值 表格里有关联的日期和指标格  // eta1.1.6弃用了
          5弹窗里的插入值 有关联日期格 
          6公式计算单元格 
          7指标计算的插入值单元格
          8日期计算值单元格
        */
        data: [], 
        contextMenuOption: [],
      },

      selectCell: {},//选中单元格info

      rightClickCell: {},//右键单元格 key c r

      insertTargetCell: {},//选择右键插入时的单元格 可和右键单元格不一样 key c r

      insertRelationArr: [], //表格单元格依赖关系数组

      isSelectTargetValueDialog: false,//选择指标插入值弹窗
      insertTargetValueInfo: {},//编辑 关联info

      cellrelationEdbInfo: {}, //指标浮窗信息

      copyCellItem: {},//复制时的单元格信息 用于粘贴赋值

      calculateClickCell: null,//双击公式单元格时的单元格信息 用于之后选其他单元格拼接公式

      isInsertDateDialog: false,//导入日期弹窗
      insertDateInfo: {},

      isInsertCalculate: false,//插入指标计算值
      insertCalculateInfo: {},//指标计算单元格info

      formulaTip,
      
      hasInit:false,

      isInsertCalculateDate: false,//日期计算弹窗
      insertCalculateDateInfo: {},//日期计算info

      activeNames: [],
      // 合并单元格data
      isSelectionStart:false, //选区开始
      startCell:{// 选区时鼠标开始的单元格
        row:null,
        column:null
      }, 
      endCell:{// 选区时鼠标结束的单元格
        row:null,
        column:null
      },
      selectionStart:{// 选区范围的左上角单元格
        row:null,
        rowSpan:0,
        column:null,
        colSpan:0
      },
      selectionEnd:{// 选区范围的右下角角单元格
        row:null,
        rowSpan:0,
        column:null,
        colSpan:0
      },
      hasMergedCell:false,// 选区内是否有合并的单元格
      selectedCells:[],
      // 选区有'值'单元格 因为超一个单元格有值不让合并，所以记录一个就行
      hasValueCellItem:{
        cellNumber:0, //有几个
        row:null,
        column:null
      },
      // 做个缓存
      cacheKey:'',
      cacheCellDom:{},
      //规则列表
      excelRuleList:[]
    };
  },
  mounted() {
    if(this.$route.path === '/addMixedSheet' && !this.$route.query.id) this.initData();
  },
  methods: {
    // 获取规则
    async getExcelRule(ExcelInfoId='',){
      const res = await dataBaseInterface.getRuleList({ExcelInfoId:ExcelInfoId?ExcelInfoId:this.$route.query.id})
      // console.log(res)
      if(res.Ret !== 200) return
      this.excelRuleList = res.Data.List?res.Data.List:[];
      this.commonInitCell()
    },

    openConDialog({chooseItem,chooseCells}){
      this.$refs.conditionDia.openDialog(chooseItem,chooseCells,this.excelRuleList,this.$route.query.id)
    },
    
    /* 输入时实时搜索 满足日期格式不搜索 有=视为输入公式不搜索  eta1.5.6弃用了*/
    async searchTarget(query,cb) {
      return cb([])
      
      //又要过滤掉2020-05-这样的奇葩其他格式 不让检索
      let dateOtherRegex = /^(?:(?:19|20)\d\d)([-])(0[1-9]|1[0-2])(-?)$/
      if(!query
        ||checkDateFormat(query)
        ||dateOtherRegex.test(query)
        ||query.startsWith('=')
      ) return cb([])
      
      const { DataType,EdbInfoId } = this.selectCell;

      const res = DataType===2 
        ? await dataBaseInterface.targetDetail({EdbInfoId})
        : await sheetInterface.searchTarget({
            KeyWord: query,
            CurrentIndex: 1,
            PageSize: 1000
          })
      if(res.Ret !== 200) return

      let arr = DataType===2 ? [res.Data] : (res.Data.List||[])
      cb(arr);
    },

    /* 单击 */
    clickCell(e, cell) {
      if(this.disabled) return

      selectCellStyle(e);
      this.clearSelection()
      this.hasMergedCell = !!(cell && cell.merData)
      this.selectCell = cell;
      setFocus(e);

      //是插值单元格时寻找关联依赖的单元格 设置选框
      if([4,5,7].includes(cell.DataType)) {
        const { key } = e.target.dataset;
        if(!this.insertRelationArr.find(_ => _.key===key)) return
        let { relation_date,relation_edb } = this.insertRelationArr.find(_ => _.key===key)
        relation_date.key && setRelationStyle(relation_date)
        relation_edb.key && setRelationStyle(relation_edb)
      }

      //选择指标弹窗打开时选择日期更新弹窗数据
      this.isSelectTargetValueDialog&&this.$refs.selectTargetValueRef.changeRleationDate(this.selectCell)

      //计算指标弹窗打开时选择日期更新弹窗数据
      this.isInsertCalculate&&this.$refs.calculateEdbDiaRef.changeRleationDate(this.selectCell)

      //日期计算弹窗打开选中日期框时且有选中item时更新选中值
      cell.DataType===1&&this.isInsertCalculateDate&&this.$refs.calculateDateDiaRef.selectIndex&&this.$refs.calculateDateDiaRef.setSelectItemValue(this.selectCell)
    },

    /* 插入值 往左往上寻找同行同列是否有符合条件的一指标一日期 */
    async insertValue() {
      
      let params = this.findNearestCell();
      console.log(params)
      if(!params) {
        this.selectCell.DataType = 3;
        this.selectCell.DataTimeType = 0;
        this.selectCell.ShowValue = '';
        this.selectCell.Value = '';
        this.selectCell.DataTime = '';
        this.selectCell.EdbInfoId = 0;
        this.$message.warning(this.$t('OnlineExcelPage.no_here_val_msg') );
        return
      }

      const { EdbInfoId,Date,DataTimeType } = params

      const res = await sheetInterface.insertData({EdbInfoId,Date})
      if(res.Ret !==200) return


      res.Data ? this.$message.success(this.$t('OnlineExcelPage.insert_success_msg') ) : this.$message.warning(this.$t('OnlineExcelPage.the_date_no_val_msg') ) 

      this.selectCell.DataType = 4;
      this.selectCell.ShowValue = res.Data;
      this.selectCell.Value = res.Data;
      this.selectCell.EdbInfoId = EdbInfoId;
      this.selectCell.DataTime = Date;

      this.setRelation(params)
    },
    
    // 建立插入单元格和依赖单元格关联关系
    setRelation(data,cellType=4) {
      const { insert_cell } = data;

      let relation_obj = {
        type: cellType,
        key: insert_cell.key,
        relation_date: {
          type: 1,
          key: insert_cell.relation_date
        },
        relation_edb: {
          type: 2,
          key: insert_cell.relation_edb
        }
      }

      let haveIndex = this.insertRelationArr.findIndex(_ => _.key===insert_cell.key);
      if(haveIndex===-1) {
        this.insertRelationArr.push(relation_obj)
      }else {
        this.insertRelationArr.splice(haveIndex,1,relation_obj)
      }
      console.log(this.insertRelationArr)
    },

    /* 向左向上找出所有格子 找出离插入单元格最近的两个符合条件的单元格 看是否满足一指标一日期的条件
      不满足就无法插入值
    */
    findNearestCell() {
      let { rindex,cindex,key } = this.rightClickCell;
      
      let index_row = this.rowHeader.findIndex(_ => _===rindex);
      let index_col = this.columnHeader.findIndex(_ => _===cindex);

      //同行左侧所有格子
      let row_cell_arr = this.config.data[index_row].filter((_,cell_index) => cell_index<index_col);
      //同列上侧所有格子
      let col_cell_arr = this.config.data.filter((row,row_index) => row_index<index_row).map(row=> row[index_col]);

      if(!row_cell_arr.length || !col_cell_arr.length){
        return null
      }

      //寻找最近的符合1 2类型的两个格子
      let params = null;
      
      for (let i = row_cell_arr.length - 1; i >= 0; i--) {
        for (let j = col_cell_arr.length - 1; j >= 0; j--) {
          if(!params) {
            if((row_cell_arr[i].DataType===1&&col_cell_arr[j].DataType===2)
            ||(row_cell_arr[i].DataType===2&&col_cell_arr[j].DataType===1)) {
              params = {
                DataTimeType: row_cell_arr[i].DataType===1 ? row_cell_arr[i].DataTimeType : col_cell_arr[j].DataTimeType,
                Date: row_cell_arr[i].DataType===1 ? row_cell_arr[i].ShowValue : col_cell_arr[j].ShowValue,
                EdbInfoId: row_cell_arr[i].DataType===2 ? row_cell_arr[i].EdbInfoId : col_cell_arr[j].EdbInfoId,
                insert_cell: {
                  key,
                  relation_date: row_cell_arr[i].DataType===1 ? row_cell_arr[i].Uid: col_cell_arr[j].Uid,
                  relation_edb: row_cell_arr[i].DataType===2 ? row_cell_arr[i].Uid: col_cell_arr[j].Uid,
                },
              }
              break
            }
          }
        }
      }
      return params;

    },

    /* 选择指标 单元格类型为2 已经是指标单元格了就重置单元格 否则就视为选择指标*/
    // selectTarget(e,cell) {
    //   const { EdbName,EdbInfoId }  = e;

    //   //如果已经是指标单元格了再次点击就清空
    //   if(cell.DataType===2&&cell.EdbInfoId) {
    //     this.clearCell()
    //   }else {
    //     cell.DataType = 2;
    //     cell.DataTime = '';
    //     cell.ShowValue = EdbName;
    //     cell.Value = EdbName;
    //     cell.EdbInfoId = EdbInfoId;
    //   }

    //   this.checkCellRelation(cell)
    // },

    /* 输入框失焦 设置单元格类型 处理关联关系 */
    async changeVal(e, cell) {
      // 是日期格式 DataType为1
      // 自定义内容 DataType 3
      //有=号为输入公式 DataType 6
      const {value} = e.target;
      if(!value){ //无值重置单元格
        cell.DataType = 3;
        cell.ShowValue = value;
        cell.Value = value;
        cell.EdbInfoId = 0;
        cell.DataTime = '';
        cell.Extra=''
      }else {
        //指标类型不做格式处理
        if(cell.DataType===2) return
        
        console.log(checkDateFormat(value))
        let dateFormat = checkDateFormat(value);
        if(dateFormat) { //是日期格式
          cell.DataType = 1;
          cell.Extra='';
          cell.ShowValue = dateFormat;
          cell.DataTime = dateFormat;
          cell.Value = dateFormat;
        }else if(value.startsWith('=')) { //公式单元格
          cell.Value = value;
          cell.DataType = 6;
          let calculateVal = await this.getValueByFormula(value);
          if(!calculateVal) return
          cell.ShowValue = calculateVal;
          //处理公式关系
          this.$set(cell,'Extra',this.dealFormulaConstruction(value))
        }else {//自定义值
          cell.DataType = 3;
          cell.ShowValue = value;
          cell.Value = value;
          cell.EdbInfoId = 0;
          cell.DataTime = '';
          cell.Extra=''
        }
      }

      /* 不是数字类型，清除原来设置的格式 */
      if(!isNumberVal(value)){
        cell.ShowStyle = '';
        cell.ShowStyle = '';
      } ;

      //判断是否是有插入值的依赖单元格 更新值或重置关系
      this.checkCellRelation(cell)
      this.commonInitCell('edit')

    },

    /* 当前单元格是否和插入值有关联 无就不管 */
    async checkCellRelation(cell) {
      if(!this.insertRelationArr.length) return

      const key= cell.Uid;
      
      //有关联的N组数组
      let haveRelationArr = this.insertRelationArr.filter(_ => _.relation_date.key===key||_.relation_edb.key===key);

      if(!haveRelationArr.length) return

      //去处理每一组关联的情况
      haveRelationArr.forEach(relation => {
        const { relation_date,relation_edb,type } = relation;
  
        if((relation_date.key === key && cell.DataType === 1) || (relation_edb.key === key && cell.DataType === 2)) { //单元格类型不变只变值仍有关联关系 更新值
          // 根据关系关联数组去更新每种单元格类型的值
          this.updateRelationCell(relation,cell)
  
  
        }else {
          // 清除插入值单元格式和关联关系
          this.clearInsertCell(relation.key);
        }
      })
 
    },

    // 清除插入值单元格式和关联关系
    clearInsertCell(key) {
      this.config.data.forEach(row => {
        row.forEach(cell => {
          if(cell.Uid === key) {
            cell.DataType = 3;
            cell.EdbInfoId = 0;
            cell.DataTime = '';
            cell.ShowValue = '';
            cell.Value = '';
            cell.ShowStyle = ''
          }
        })
      })

      let relationIndex = this.insertRelationArr.findIndex(_ => _.key===key)
      this.insertRelationArr.splice(relationIndex,1)
    },
    // 替换关联关系
    replaceCellRelation(originKey,replaceKey){
      if(!this.insertRelationArr.length) return
      this.insertRelationArr = JSON.parse(JSON.stringify(this.insertRelationArr).replaceAll(originKey,replaceKey))
    },
    /* 单元格更新时去更新有依赖关系单元格的值 目前只更4 5 7*/
    updateRelationCell(relation,cell) {
      const cellTypeMap = {
        4: this.refreshRelationInsertCell,
        5: this.refreshRelationByEdbInsertCell,
        7: this.refreshRelationByEdbCalculateCell,
      }

      cellTypeMap[relation.type]&& cellTypeMap[relation.type](relation,cell)
      
    },

    //关联类型4的单元格值刷新
    async refreshRelationInsertCell({relation_date,relation_edb},cell) {
        //刷新插入值结果
        let params = null;
        if(relation_date.key === key && cell.DataType === 1) { //修改的是依赖日期格
          let { EdbInfoId } = findCellByKey(this.config.data,relation.key)
          params = {
            EdbInfoId,
            Date: cell.ShowValue
          }

        } else if( relation_edb.key === key && cell.DataType === 2) { //修改的依赖指标格
          let {ShowValue} = findCellByKey(this.config.data,relation_date.key)
          params = {
            EdbInfoId: cell.EdbInfoId,
            Date: ShowValue
          }
        }

        const res = await sheetInterface.insertData(params)
        if(res.Ret !==200) return

        //现在日期无值也不清除关系了
        // !res.Data && this.clearInsertCell(relation.key);
        
        this.config.data.forEach(row => {
          row.forEach(cell => {
            if(cell.Uid === relation.key) {
                cell.DataType = relation.type;
                cell.ShowValue = res.Data;
                cell.Value = res.Data;
                cell.EdbInfoId = params.EdbInfoId;
                cell.DataTime = params.Date;
            }
          })
        })
    },

    //关联类型5的弹窗插值单元格值刷新
    async refreshRelationByEdbInsertCell(relation,cell) {

      let { EdbInfoId,Value } = findCellByKey(this.config.data,relation.key)

      let params = {
        EdbInfoId,
        MoveForward: JSON.parse(Value).MoveForward,
        DateChange: JSON.parse(Value).DateChange,
        Date: cell.ShowValue
      }
      const res = await sheetInterface.getDateLatelyData(params)
      if(res.Ret !== 200) return

      let value = (res.Data.List&&res.Data.List.length)
        ? res.Data.List.find(_ => _.DataTime===res.Data.Date) 
          ? res.Data.List.find(_ => _.DataTime===res.Data.Date).Value.toString() 
          : ''
        : ''

      this.config.data.forEach(row => {
        row.forEach(cell => {
          if(cell.Uid === relation.key) {
              cell.ShowValue = value;
              cell.ShowFormatValue = cell.ShowStyle ? transDecimalPlace(value,JSON.parse(cell.ShowStyle)) : '';
          }
        })
      })
    },

    //关联类型7的指标计算单元格值刷新
    async refreshRelationByEdbCalculateCell(relation,cell) {
      console.log(relation,cell)
      
      console.log(findCellByKey(this.config.data,relation.key))
      let { Value } = findCellByKey(this.config.data,relation.key)

      const {
        Source,
        Frequency,
        Formula,
        EdbInfoId,
        MoveFrequency,
        MoveType, 
        Calendar,
        MoveForward,
        DateChange
      } = JSON.parse(Value);

      let params = {
        DataTime: cell.ShowValue,
        Source,
        Frequency,
        Formula,
        EdbInfoId,
        MoveFrequency,
        MoveType, 
        Calendar,
        MoveForward,
        DateChange,
      }
      const res = await sheetInterface.getMixedCalculateData(params)
      if(res.Ret !== 200) return

      let value = res.Data.ShowValue||"";

      this.config.data.forEach(row => {
        row.forEach(cell => {
          if(cell.Uid === relation.key) {
              cell.ShowValue = value;
              cell.ShowFormatValue = cell.ShowStyle ? transDecimalPlace(value,JSON.parse(cell.ShowStyle)) : '';
          }
        })
      })
    },

    /* 输入公式的计算值 */
    async getValueByFormula(val) {

      // 提取因数数组
      let factors = extractFactorsFromFormula(val)
      
      //根据因数找单元格
      let isAllCell = factors.some(_ => findCellByFactorMixed(this.config.data,_)===null||isNaN(findCellByFactorMixed(this.config.data,_)))
      if(isAllCell) {
        this.$message.warning(this.$t('OnlineExcelPage.formula_val_error_msg') )
        return '';
      } 

      let TagMap = {};
      factors.forEach(_ => {
        if(!TagMap[_]) {
          TagMap[_] = Number(findCellByFactorMixed(this.config.data,_))
        }
      });
      
      const res = await sheetInterface.calculateCustomCellData({
        CalculateFormula: val,
        TagMap
      })
      if(res.Ret !== 200) return 
      return res.Data
    },

    /* 顶部公式改变 */
    async updateValueByFormula(value) {
      this.changeVal({target: {value}},this.selectCell)
    },

    /* 右键 */
    rightClickHandle(e,cell) {
      if(this.disabled) return

      const { rindex,cindex,key,datacindex,datarindex } = e.target.dataset;
      this.rightClickCell = {
        rindex,
        cindex,
        datarindex,
        datacindex,
        key
      }

      this.selectCell = cell;

      let pos;
      if(rindex==='-1') { //列头处
        pos = 'col'
      }else if(cindex==='-1') { //行头
        pos = 'row'
      }else if( datarindex>=this.selectionStart.row && datarindex<=this.selectionEnd.row &&
      datacindex>=this.selectionStart.column && datacindex<=this.selectionEnd.column &&
      (this.selectionEnd.row-this.selectionStart.row>0||this.selectionEnd.column-this.selectionStart.column>0)){
        // 选区
        pos = 'selection'
      }else {//单元格
        pos = 'cell'
      }

      pos==='cell' && this.clickCell(e,cell);

      this.config.contextMenuOption = pos === 'cell' 
        ? getRightClickMenu(pos,(cell.DataType===1&&[1,2].includes(cell.DataTimeType))||[5,7,8].includes(cell.DataType),false,{cellMerged:this.hasMergedCell})
        : getRightClickMenu(pos,false,false,{cellMerged:this.hasMergedCell})

      this.$nextTick(() => {
        let dom = $('#contextMenu-wrapper')[0];

        if(e.clientY > window.innerHeight/2) {
          dom.style.left = e.clientX-3 + 'px';
          dom.style.top = e.clientY-dom.offsetHeight-3 + 'px';
        }else {
          dom.style.left = e.clientX-3 + 'px';
          dom.style.top = e.clientY-3 + 'px';
        }

        if(['col','row'].includes(pos)){
          this.clearSelection()
          selectMoreCellStyle(e);
        }
      })
      
    },

    /*  */
    hideContextMenu() {
      const dom = $('#contextMenu-wrapper')[0];
			dom.style.left = '-9999px';
			dom.style.top = '-9999px';
    },

    /* 右键事件 */
    async handleContext(key) {

      //可右键编辑的单元格类型
      let editHandlesMap = {
        1: this.insertDateOpen,
        5: this.selectTargetOpen,
        7: this.edbCalculateInsertOpen,
        8: this.insertDateCalculateOpen
      }

      const keyMap = {
        'del': this.delColOrRow,//删除
        'insert-col-left': this.insertCol,//向左插入列
        'insert-col-right': this.insertCol,//向右插入列
        'insert-row-up': this.insertRow,//向上插入行
        'insert-row-down': this.insertRow,//向下插入行
        'insert-value': this.insertValue,//插入值
        'choose-target': this.selectTargetOpen,//选择指标插入值
        'insert-date': this.insertDateOpen,//导入系统日期
        // 'insert-edb-date': this.insertDateOpen,//导入指标日期
        'insert-date-calculate': this.insertDateCalculateOpen,//日期计算弹窗
        'reset': this.clearCell, //清空
        'cell-edit': this.selectCell ? editHandlesMap[this.selectCell.DataType] : null,
        'cell-merge':this.mergeCellFun,
        'cell-unmerge':this.unmergeCellsFun
      }
      keyMap[key] && keyMap[key](key)
      
      key!=='insert-edb-calculate' && this.hideContextMenu()
    },

    /* 打开选择指标弹窗  
    打开弹窗后仍可以在页面上点击 多存一个选择指标时的当前单元格信息 */
    selectTargetOpen(type) {
      this.insertTargetCell = this.selectCell;
      resetDialogCellStyle();
      setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target')
      if(type === 'cell-edit') {
        this.insertTargetValueInfo = {
          ...this.insertTargetCell
        }
      }else {
        this.insertTargetValueInfo = {}
      }
      this.isSelectTargetValueDialog = true;

      this.resetDialogStatus('insertEdbVal')
    },

    /* 插入选择指标的值 */
    insertSelectData({ edbId,value,relationDate,relationUid,str,sourceName }) {

      this.insertTargetCell.DataType = 5;
      this.insertTargetCell.ShowValue = value;
      this.insertTargetCell.Value = str;
      this.insertTargetCell.EdbInfoId = edbId;
      this.insertTargetCell.DataTime = relationDate;
      this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(value,JSON.parse(this.insertTargetCell.ShowStyle)) : '';

      value ? this.$message.success(this.$t('ETable.Msg.insertion_success_msg')) : this.$message.warning(this.$t('ETable.Msg.date_no_data'))

      this.updateSourceFrom(sourceName)
      //如果有关联表格日期就建立新的关联关系
      if(relationDate&&relationUid) {
        let relation = {
          insert_cell: {
            key: this.insertTargetCell.Uid,
            relation_date: relationUid,
            relation_edb: '',
          }
        }
  
        this.setRelation(relation,5);
      }else { //重新插值后之后原来有关联的清除关系
        let haveIndex = this.insertRelationArr.findIndex(_ => _.key===this.insertTargetCell.Uid);
        haveIndex!==-1 && this.insertRelationArr.splice(haveIndex,1)
        resetRelationStyle();
      }
      this.commonInitCell('edit')
    },

    /* 
      清除单元格内容 格式 关联关系 
      config:{
        single:true 清除单个，不考虑合并单元格的联系
      }
    */
    clearCell(c) {
      const isCell = c && typeof(c)=='object' && c.Uid
      const cell = isCell ? c: this.selectCell

      if([4,5].includes(cell.DataType)) resetRelationStyle();

      cell.DataType = 3;
      cell.ShowValue = '';
      cell.Value = '';
      cell.DataTime = '';
      cell.DataTimeType = 0;
      cell.EdbInfoId = 0;
      cell.ShowStyle = '';
      cell.ShowFormatValue = '';
      cell.Extra && (cell.Extra = '');

      this.checkCellRelation(cell)

    },
    findDataByStartKey(key){
      if(!key) return {data:{},row:-1,col:-1}
      let mergeCellDom = this.$refs.tableRef.querySelector(`[data-key="${key}"]`)
      let row = +mergeCellDom.dataset.datarindex
      let col = +mergeCellDom.dataset.datacindex
      return {data:this.config.data[row][col],row,col}
    },
    /* 删除行列 */
    delColOrRow() {
      let { rindex,cindex } = this.rightClickCell;

      if(rindex==='-1') { //删除列
        console.log('删除列',cindex)

        if(this.columnHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_column_msg') )

        let index = this.columnHeader.findIndex(_ => _ === cindex);

        // 处理删除列对合并单元格的影响
        let startMainKey=''
        this.config.data.map((row,rowInd) => {
          let rowEle=row[index]
          if(rowEle.merData){
            let {data,row,col} = this.findDataByStartKey(rowEle.merData.mer.sKey)
            let r = row
            let c = col
            let rs = data.merData.mer.rowspan
            let cs = data.merData.mer.colspan
            if(cs == 1) return //只有一列

            if(rowEle.merData.type == 'merged'){
              // 每个大单元格只处理一次
              if(startMainKey != rowEle.merData.mer.sKey){
                if(data.merData.mer.colspan==2 && data.merData.mer.rowspan==1){
                  //删除这一列之后，只有一个单元格了
                  data.merData=null
                  return
                }
                data.merData.mer.colspan--
                startMainKey = rowEle.merData.mer.sKey
              }
            }else{
              // 右一列的单元格作为新的左上角单元格
              const newStartCell = this.config.data[r][c+1]
              if(rowEle.merData.mer.colspan==2 && rowEle.merData.mer.rowspan==1){
                //删除这一列之后，只有一个单元格了
                newStartCell.merData=null
                return
              }
              newStartCell.merData=rowEle.merData
              newStartCell.merData.mer.sKey = newStartCell.Uid
              newStartCell.merData.mer.colspan--
              for (let i = r; i < (r+rs); i++) {
                for (let j = c+1; j < (c+cs); j++) {
                  const element = this.config.data[i][j];
                  if(element.merData.type == 'merged'){
                    element.merData.mer.sKey = newStartCell.Uid
                  }
                }                  
              }
            }
          }
        })
        //删除时清除关系
        if(this.insertRelationArr.length) {
          let delCellIds = this.config.data.map(row => row[index].Uid);
          this.clearRelationInsertCell(delCellIds);
        }
        this.config.data.forEach(row => {
          row.splice(index,1)
        })
        // 删除的是最后一列
        if(!(index < this.config.data[0].length)){
          resetStyle()
        }
      }else if(cindex === '-1') { //删除行
        console.log('删除行',rindex)

        if(this.rowHeader.length === 1) return this.$message.warning(this.$t('OnlineExcelPage.keep_one_row_msg') )

        let index = this.rowHeader.findIndex(_ => _ === rindex)
        // 处理删除行对合并单元格的影响
        let startMainKey=''
        this.config.data[index].map((rowEle,rowInd) => {
          if(rowEle.merData){
            let {data,row,col} = this.findDataByStartKey(rowEle.merData.mer.sKey)
            let r = row
            let c = col
            let rs = data.merData.mer.rowspan
            let cs = data.merData.mer.colspan
            if(rs == 1) return //只有一行

            if(rowEle.merData.type == 'merged'){
              // 每个大单元格只处理一次
              if(startMainKey != rowEle.merData.mer.sKey){
                if(data.merData.mer.colspan==1 && data.merData.mer.rowspan==2){
                  //删除这一行之后，只有一个单元格了
                  data.merData=null
                  return
                }
                data.merData.mer.rowspan--
                startMainKey = rowEle.merData.mer.sKey
              }
            }else{
              // 下一行的单元格作为新的左上角单元格
              const newStartCell = this.config.data[r+1][c]
              if(rowEle.merData.mer.colspan==1 && rowEle.merData.mer.rowspan==2){
                //删除这一行之后，只有一个单元格了
                newStartCell.merData=null
                return
              }
              newStartCell.merData=rowEle.merData
              newStartCell.merData.mer.sKey = newStartCell.Uid
              newStartCell.merData.mer.rowspan--
              for (let i = r+1; i < (r+rs); i++) {
                for (let j = c; j < (c+cs); j++) {
                  const element = this.config.data[i][j];
                  if(element.merData.type == 'merged'){
                    element.merData.mer.sKey = newStartCell.Uid
                  }
                }                  
              }
            }
          }
        })
        if(this.insertRelationArr.length) {
          //删除时清除关系
          let delCellIds = this.config.data[index].map(cell => cell.Uid);
          
          this.clearRelationInsertCell(delCellIds);
        }

        this.config.data.splice(index,1)
        // 删除的是最后一行
        if(!(index < this.config.data.length)){
          resetStyle()
        }
      }
    },

    /* 删除时清除关联关系 和删除单元格有关联的插入值单元格和 */
    clearRelationInsertCell(delCellIds) {
      //清除关联插入值得单元格
      let haveRelationArr = this.insertRelationArr.filter(_ => delCellIds.includes(_.relation_date.key)||delCellIds.includes(_.relation_edb.key));
      // console.log(haveRelationArr)

      haveRelationArr.forEach(relation => {
        !delCellIds.includes(relation)&&this.clearInsertCell(relation.key);
      })

      this.insertRelationArr = this.insertRelationArr.filter(_ => !delCellIds.includes(_.key)&&!delCellIds.includes(_.relation_date.key)&&!delCellIds.includes(_.relation_edb.key))
    },

    /* 插入列 */
    insertCol(key) {
      let { cindex } = this.rightClickCell;
      
      let index = this.columnHeader.findIndex(_ => _ === cindex);
      let checkIndex = key==='insert-col-left'?index-1:index+1
      let startMainKey=''
      this.config.data.forEach((row,rindex) => {
        let isEnlargeCell = !!(row[index].merData && row[checkIndex] && row[checkIndex].merData)
        if(isEnlargeCell && startMainKey != row[index].merData.mer.sKey){
          const data = row[index].merData.type == 'merge'?row[index]:this.findDataByStartKey(row[index].merData.mer.sKey).data
          data.merData.mer.colspan++
          startMainKey = row[index].merData.mer.sKey
        }
        row.splice(key==='insert-col-left'?index:index+1,0,{
          ShowValue: "",
          Value: "",
          DataType: 3,
          DataTime: "",
          EdbInfoId: 0,
          Uid: md5.hex_md5(`${new Date().getTime()}${rindex}`),
          merData:isEnlargeCell?{
            type:'merged',
            mer:{
              sKey:row[index].merData.mer.sKey,//左上角第一个单元格的Uid
            }
          }:null
        })
      })
    },

    /* 插入行 */
    insertRow(key) {
      let { rindex } = this.rightClickCell;
      
      let index = this.rowHeader.findIndex(_ => _ === rindex)
      let checkIndex = key==='insert-row-up'?index-1:index+1
      let startMainKey=''

      let row = new Array(this.columnHeader.length).fill("").map((_,cindex) => {
        let isEnlargeCell = !!(this.config.data[index][cindex].merData &&(this.config.data[checkIndex]&&this.config.data[checkIndex][cindex]) && this.config.data[checkIndex][cindex].merData)
        if(isEnlargeCell && startMainKey != this.config.data[index][cindex].merData.mer.sKey){
          const data = this.config.data[index][cindex].merData.type == 'merge'?
                      this.config.data[index][cindex]:
                      this.findDataByStartKey(this.config.data[index][cindex].merData.mer.sKey).data
          data.merData.mer.rowspan++
          startMainKey = this.config.data[index][cindex].merData.mer.sKey
        }

        return {
          ShowValue: "",
          Value: "",
          DataType: 3,
          DataTime: "",
          EdbInfoId: 0,
          Uid: md5.hex_md5(`${new Date().getTime()}${cindex}`),
          merData:isEnlargeCell?{
            type:'merged',
            mer:{
              sKey:this.config.data[index][cindex].merData.mer.sKey,//左上角第一个单元格的Uid
            }
          }:null
        }
      });

      this.config.data.splice( key==='insert-row-up'?index:index+1,0,row)

    },

    /* 单元格类型5 浮到上面展示指标信息浮窗 */
    async getRelationEdbInfo({EdbInfoId,DataType}) {
      if(![5,7].includes(DataType)||this.disabled) return

      const res = await dataBaseInterface.targetDetail({EdbInfoId})

      if(res.Ret !== 200) return

      this.cellrelationEdbInfo =  res.Data;
    },

    /* 导入系统/指标日期弹窗 */
    insertDateOpen(type) {
      this.insertTargetCell = this.selectCell;
      resetDialogCellStyle();

      if(type === 'cell-edit') { //编辑日期
        this.insertDateInfo = {
          ...this.insertTargetCell
        }
      }else {
        this.insertDateInfo = {
          // key:type
        }
      }
      this.isInsertDateDialog = true;
      this.resetDialogStatus();
    },

    /* 弹窗都是无遮罩的 弹一个就重置其他的 */
    resetDialogStatus(type='init') {
      if(type!=='insertEdbVal') {
        this.$refs.selectTargetValueRef&&this.$refs.selectTargetValueRef.initData();
        this.isSelectTargetValueDialog = false;
      }
      if(type!=='insertEdbCalculateVal') {
        this.$refs.calculateEdbDiaRef&&this.$refs.calculateEdbDiaRef.initData();
        this.isInsertCalculate = false;
      }
      if(type!=='insertDateCalculateVal') {
        this.$refs.calculateDateDiaRef&&this.$refs.calculateDateDiaRef.initData();
        this.isInsertCalculateDate = false;
      }
    },

    /* 插入系统/指标日期 */
    insertDatehandle({insertValue,dataTimeType,str,sourceName}) {
      this.updateSourceFrom(sourceName)

      this.insertTargetCell.DataType = 1;
      this.insertTargetCell.DataTimeType = dataTimeType;
      this.insertTargetCell.ShowValue = insertValue;
      this.insertTargetCell.Value = str;
      this.insertTargetCell.EdbInfoId = 0;
      this.insertTargetCell.DataTime = insertValue;
      this.commonInitCell('edit')
    },

    /* 指标计算弹窗 */
    edbCalculateInsertOpen(item) {
      this.insertTargetCell = this.selectCell;
      resetDialogCellStyle();
      setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target');

      if(item === 'cell-edit') { //编辑
        const { Value } = this.insertTargetCell;

        let menuInfo = this.config.contextMenuOption
          .find(_ => _.key==='insert-edb-calculate').children
          .find(menu => menu.source === JSON.parse(Value).Source);

        this.insertCalculateInfo = {
          ...menuInfo,
          ...this.insertTargetCell
        }
      }else {
        this.insertCalculateInfo = {
          ...item
        }
      }
      this.isInsertCalculate = true;

      this.resetDialogStatus('insertEdbCalculateVal')
    },

    /* 导入指标计算值 */
    insertCalculateData(item) {
      // console.log(item)
      const { InsertValue,EdbInfoId,Str,relationDate,relationUid,sourceName } = item;
      this.insertTargetCell.DataType = 7;
      this.insertTargetCell.ShowValue = InsertValue;
      this.insertTargetCell.Value = Str;
      this.insertTargetCell.EdbInfoId = EdbInfoId;
      this.insertTargetCell.DataTime = relationDate;
      this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(InsertValue,JSON.parse(this.insertTargetCell.ShowStyle)) : '';

      InsertValue ? this.$message.success(this.$t('ETable.Msg.insertion_success_msg')) : this.$message.warning(this.$t('ETable.Msg.date_no_data'))

      this.updateSourceFrom(sourceName)

      //如果有关联表格日期就建立新的关联关系
      if(relationDate&&relationUid) {
        let relation = {
          insert_cell: {
            key: this.insertTargetCell.Uid,
            relation_date: relationUid,
            relation_edb: '',
          }
        }
  
        this.setRelation(relation,7);
      }else { //重新插值后之后原来有关联的清除关系
        let haveIndex = this.insertRelationArr.findIndex(_ => _.key===this.insertTargetCell.Uid);
        haveIndex!==-1 && this.insertRelationArr.splice(haveIndex,1)
        resetRelationStyle();
      }
      this.commonInitCell('edit')
    },

    /* 日期计算弹窗 */
    insertDateCalculateOpen(type) {
      this.insertTargetCell = this.selectCell;
      resetDialogCellStyle()
      setRelationStyle({ key:this.insertTargetCell.Uid },'td-choose-insert-target')

      if(type === 'cell-edit') { //编辑
        this.insertCalculateDateInfo = {
          ...this.insertTargetCell
        }
      }else {
        this.insertCalculateDateInfo = {}
      }
      this.isInsertCalculateDate = true;
      this.resetDialogStatus('insertDateCalculateVal');
    },

    /* 插入日期计算值 */
    insertCalculateDateValue(data) {
      const { insertValue,str } = data;
      this.insertTargetCell.DataType = 8;
      this.insertTargetCell.ShowValue = insertValue;
      this.insertTargetCell.Value = str;
      this.insertTargetCell.EdbInfoId = 0;
      this.insertTargetCell.DataTime = '';
      this.insertTargetCell.ShowFormatValue = this.insertTargetCell.ShowStyle ? transDecimalPlace(insertValue,JSON.parse(this.insertTargetCell.ShowStyle)) : '';

      this.$message.success(this.$t('ETable.Msg.insertion_success_msg'))
      this.commonInitCell('edit')
    },

    /* 初始化8行5列 */
    initData(initData=null) {
      this.hasInit=false
      if(initData) {
        const { CellRelation,Data } = initData;
        this.config.data = Data;
        this.insertRelationArr = JSON.parse(CellRelation);
      }else {
        this.config.data = new Array(8).fill("").map((_,_rindex) => {
          return new Array(5).fill("").map((cell,_cindex) => ({
            ShowValue: "",
            ShowStyle: '',
            ShowFormatValue: '',
            Value: "",
            DataType: 3,
            DataTimeType: 0,
            DataTime: "",
            EdbInfoId:0,
            Uid: md5.hex_md5(`${new Date().getTime()}${_rindex}${_cindex}`),
          }));
        });
      }
      this.$nextTick(()=>{
        this.hasInit=true
        if(this.$route.query.id){
          this.getExcelRule()
        }
      })
    },

     /* 处理因数结构 =a1+b1 => [{ Tag: a,Row:1,Key:'' }] */
    dealFormulaConstruction(val) {
      // 提取因数数组
      let factors = extractFactorsFromFormula(val)
      let arr = factors.map(str => ({
          Tag: splitString(toUpperCase(str))[0],
          Row: splitString(toUpperCase(str))[1],
          Key: findCellKeyByFactor(str)
      }))
      return JSON.stringify(arr)
    },


    /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
    copyCellHandle(e,cell) {
      this.copyCellItem = cell;
      // 阻止默认的复制操作
      e.preventDefault();
    },

    /* 要支持复制粘贴把公式也带过去 公式单元格类型为6 其余就正常复制文本 */
    pasteCellHandle(e,cell) {
      if(this.copyCellItem.DataType === 6) {
        cell.DataType = this.copyCellItem.DataType;
        cell.ShowValue = this.copyCellItem.ShowValue;
        cell.Value = this.copyCellItem.Value;
        cell.DataTime = this.copyCellItem.DataTime;
        cell.EdbInfoId = this.copyCellItem.EdbInfoId;
        cell.ShowStyle = this.copyCellItem.ShowStyle;
        cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
        cell.Extra = this.copyCellItem.Extra;
      }else {
        cell.DataType = 3;
        cell.ShowValue = this.copyCellItem.ShowValue;
        cell.Value = this.copyCellItem.ShowValue;
        cell.ShowStyle = this.copyCellItem.ShowStyle;
        cell.ShowFormatValue = this.copyCellItem.ShowFormatValue;
        cell.DataTime = '';
        cell.EdbInfoId = 0;
      }

      // 阻止默认的粘贴操作
      e.preventDefault();
    },

    /* 单元格enter失焦 */
    keyEnterHandle(e,cell) {
      if(e.keyCode===13) {
        //非得搞个要回车失焦
        e.target.nodeName && e.target.blur();
        this.$refs[`inputRef${e.target.dataset.key}`]&&this.$refs[`inputRef${e.target.dataset.key}`][0].close()

        // cell.DataType===6 && this.$set(cell,'CanEdit',false)
        // this.$set(cell,'CanEdit',false)
      }
    },

    /* 双击切换状态 插值单元格不允许切换 可切换类型1，2，3，6*/
    dblClickCellHandle(e,cell) {
      if(this.disabled || ![1,2,3,6].includes(cell.DataType) || [1,2].includes(cell.DataTimeType)) return

      this.$set(cell,'CanEdit',true)
      console.log(cell)

      this.$nextTick(() => {
        if(e.target.childNodes[0].childNodes[0].childNodes[1].nodeName==='INPUT') e.target.childNodes[0].childNodes[0].childNodes[1].focus();
      })
    },

    /* 处理保存的参数 */
    getSaveParams() {
      const { data } = this.config;

      let params = {
        CellRelation: JSON.stringify(this.insertRelationArr),
        Data: data
      }

      return params
    },

    /* tab禁掉 */
    handlekeyDownKeys(e) {
      if(e.keyCode === 9) {
        e.preventDefault();
      }
    },

    // /* 改变单元格显示文本 */
    // updateCellStyle({ShowStyle,ShowFormatValue}) {
    //   this.$set(this.selectCell,'ShowStyle',ShowStyle)
    //   this.$set(this.selectCell,'ShowFormatValue',ShowFormatValue)
    // },
    // 更新数据来源
    updateSourceFrom(source){
      if(!source) return
      let concatSourceArr = this.sourceFrom.text?`${this.sourceFrom.text},${source}`.split(','):[source];
      let sourceStr = Array.from(new Set(concatSourceArr)).join(',');
      this.$set(this.sourceFrom,'text',sourceStr)
      this.$emit('updateSourceName')
    },
    // ==================================================合并单元格
    // 选区开始
    selectCellHandle(e) {
      // 不是左键的mousedown事件
      if(e.button!==0) return
      if(this.disabled) return
      this.isSelectionStart=true
      
      let startTd;
      if(e.target.nodeName==='TD'){
        startTd = e.target
      }else if(e.target.parentNode.nodeName==='TD'){
        startTd = e.target.parentNode
      }else if(e.target.parentNode.parentNode.nodeName==='TD'){
        startTd = e.target.parentNode.parentNode
      }else if(e.target.parentNode.parentNode.parentNode.nodeName==='TD'){
        startTd = e.target.parentNode.parentNode.parentNode
      }

      if(!startTd) return

      this.startCell={
        row:+startTd.dataset.datarindex,
        column:+startTd.dataset.datacindex
      }
      document.addEventListener('mousemove',this.selectZoneHandle)
      document.addEventListener('mouseup',this.selectCellEndHandle)
    },
    // 选取
    selectZoneHandle(e) {
      if(!this.isSelectionStart) return 
      if(this.disabled) return
      const selection = window.getSelection();
      if (selection.rangeCount>0) {
        // 清除选中的文本范围
        selection.removeAllRanges();
      }

      let tableRect=this.$refs.tableRef.getBoundingClientRect()
      const mouseX = e.pageX;
      const mouseY = e.pageY;

      let endTd;

      if(mouseX >= tableRect.left && mouseX <= tableRect.right &&
      mouseY >= tableRect.top && mouseY <= tableRect.bottom){
        // 表格内
        if(e.target.nodeName==='TD'){
          endTd = e.target
        }else if(e.target.parentNode.nodeName==='TD'){
          endTd = e.target.parentNode
        }else if(e.target.parentNode.parentNode.nodeName==='TD'){
          endTd = e.target.parentNode.parentNode
        }else if(e.target.parentNode.parentNode.parentNode.nodeName==='TD'){
          endTd = e.target.parentNode.parentNode.parentNode
        }
        if(!endTd) return 

        this.endCell={
          row:+endTd.dataset.datarindex,
          column:+endTd.dataset.datacindex
        }
      }
    },
    // 选区结束
    selectCellEndHandle(){
      this.isSelectionStart=false
      // click事件走在mouseup事件前面，延迟下
      setTimeout(()=>{
        if((this.selectionStart.row || this.selectionStart.row==0) 
      && (this.selectionEnd.row || this.selectionEnd.row==0)
      && (this.selectionStart.column || this.selectionStart.column==0)
      && (this.selectionEnd.column || this.selectionEnd.column==0)){
          this.selectedCells=[]
          resetStyle()
          this.selectCell=null
          // 选区
          for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
            for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
              this.selectedCells.push(this.config.data[i][j])
            }        
          }
        }else{
          this.selectedCells=[]
        }
      },1)
      document.removeEventListener('mousemove',this.selectZoneHandle)
      document.removeEventListener('mouseup',this.selectCellEndHandle)
    },
    findCellDom(key){
      if(!key) return null
      if(key !== this.cacheKey){
        // 重新找
        this.cacheCellDom = this.$refs.tableRef.querySelector(`[data-key="${key}"]`)
        this.cacheKey=key
      }
      return this.cacheCellDom
    },
    // 确定选区范围和设置选区样式
    setSelectionStyle(){
     if(!this.isSelectionStart) return
      // 开始的单元格没有
      if(!( (this.startCell.row || this.startCell.row==0) && 
        (this.startCell.column || this.startCell.column==0))) return 
      // 结束的单元格没有
      if(!( (this.endCell.row || this.endCell.row==0) && 
        (this.endCell.column || this.endCell.column==0))) return

      // 递归确定选区范围
      const findZone = ({sR,eR,sC,eC})=>{
        this.hasValueCellItem.cellNumber=0
        
        for (let i = sR; i < eR+1; i++) {
          for (let j = sC; j < eC+1; j++) {
            const element = this.config.data[i][j]
            if(element.Value){
              this.hasValueCellItem.cellNumber++
              this.hasValueCellItem.row=i
              this.hasValueCellItem.column=j
            }

            if(element.merData && element.merData.type==='merge'){
              if(i+element.merData.mer.rowspan-1 > eR){
                // 该单元格的行有合并 重新规定选取范围
                return findZone({sR,eR:i+element.merData.mer.rowspan-1,sC,eC})
              }
              if(j+element.merData.mer.colspan-1 > eC){
                // 该单元格的列有合并 重新规定选取范围
                return findZone({sR,eR,sC,eC:j+element.merData.mer.colspan-1})
              }
              this.hasMergedCell=true
            }
            
            if(element.merData && element.merData.type==='merged' ){
              let item = this.findCellDom(element.merData.mer.sKey)
              let row = +item.dataset.datarindex
              let col = +item.dataset.datacindex
              if(row < sR){
                // 该单元格的行有被合并 重新规定选取范围
                return findZone({sR:row,eR,sC,eC})
              }
              if(col < sC){
                // 该单元格的行有被合并 重新规定选取范围
                return findZone({sR,eR,sC:col,eC})
              }
              this.hasMergedCell=true
            }
          }
        }
        // 防止选中的区域不是整个的单元格（合并后的），后面确定selectionRef 区域大小有问题
        if(this.config.data[eR][eC].merData && this.config.data[eR][eC].merData.type==='merged'){
          let item = this.findCellDom(this.config.data[eR][eC].merData.mer.sKey) 
          let row = +item.dataset.datarindex
          let col = +item.dataset.datacindex
          eR=row
          eC=col
          this.hasMergedCell=true
        }
        return {startR:sR,
                endR:eR,
                startC:sC,
                endC:eC}
      }

      // 看是否是从下往上、从右往左选的
      let rowReverse = this.startCell.row > this.endCell.row
      let colReverse = this.startCell.column > this.endCell.column
      let postion={
        sR:rowReverse?this.endCell.row:this.startCell.row,
        eR:rowReverse?this.startCell.row:this.endCell.row,
        sC:colReverse?this.endCell.column:this.startCell.column,
        eC:colReverse?this.startCell.column:this.endCell.column
      }

      this.hasMergedCell=false
      const zone = findZone(postion)

      let start = this.config.data[zone.startR][zone.startC]
      let end = this.config.data[zone.endR][zone.endC]

      this.selectionStart.row = zone.startR
      this.selectionStart.column = zone.startC
      this.selectionStart.rowSpan = start.merData?start.merData.mer.rowspan:1
      this.selectionStart.colSpan = start.merData?start.merData.mer.colspan:1

      this.selectionEnd.row = zone.endR
      this.selectionEnd.column = zone.endC
      this.selectionEnd.rowSpan = end.merData?end.merData.mer.rowspan:1
      this.selectionEnd.colSpan = end.merData?end.merData.mer.colspan:1

      let tableRect = this.$refs.tableRef.getBoundingClientRect()
      let startTd = this.$refs.tableRef.querySelector(`[data-key="${start.Uid}"]`)
      let endTd = this.$refs.tableRef.querySelector(`[data-key="${end.Uid}"]`)
      if(!(startTd && endTd)) return
      let startRect = startTd.getBoundingClientRect()
      let endRect = endTd.getBoundingClientRect()

      this.$refs.selectionRef.style.left = startRect.left-tableRect.left+'px'
      this.$refs.selectionRef.style.top = startRect.top-tableRect.top+'px'
      let width = Math.abs(endRect.right - startRect.right) + startRect.width
      let height = Math.abs(endRect.bottom - startRect.bottom) + startRect.height
      this.$refs.selectionRef.style.width = width+'px'
      this.$refs.selectionRef.style.height = height + 'px'
      this.$refs.selectionRef.style.visibility='visible'
    },
    clearSelection(){
      this.$refs.selectionRef.style.width = 0
      this.$refs.selectionRef.style.height = 0
      this.$refs.selectionRef.style.visibility='hidden'
      this.selectionStart={
        row:null,
        rowSpan:0,
        column:null,
        colSpan:0
      }
      this.selectionEnd={
        row:null,
        rowSpan:0,
        column:null,
        colSpan:0,
      }
      this.selectedCells=[]
    },
    mergeCellFun(){
      // 无选区
      if(!((this.selectionStart.row || this.selectionStart.row==0) 
      && (this.selectionEnd.row || this.selectionEnd.row==0)
      && (this.selectionStart.column || this.selectionStart.column==0)
      && (this.selectionEnd.column || this.selectionEnd.column==0))) return

      if(this.hasValueCellItem.cellNumber>1 || this.hasValueCellItem.cellNumber<0){
        return this.$message.warning(this.$t('ETable.Msg.merge_cell_fail_msg'))
      }
      const firstCell = this.config.data[this.selectionStart.row][this.selectionStart.column]
      if(this.hasValueCellItem.cellNumber!=0 && (this.hasValueCellItem.row!=this.selectionStart.row || this.hasValueCellItem.column!=this.selectionStart.column)){

        const reserveCell=this.config.data[this.hasValueCellItem.row][this.hasValueCellItem.column]
        // 将原本有值的单元格 移给左上角第一个单元格
        firstCell.ShowValue=reserveCell.ShowValue
        firstCell.ShowStyle=reserveCell.ShowStyle
        firstCell.ShowFormatValue=reserveCell.ShowFormatValue
        firstCell.Value=reserveCell.Value
        firstCell.DataType=reserveCell.DataType
        firstCell.DataTimeType=reserveCell.DataTimeType
        firstCell.DataTime=reserveCell.DataTime
        firstCell.EdbInfoId=reserveCell.EdbInfoId
        reserveCell.CanEdit && (firstCell.CanEdit=reserveCell.CanEdit)
        reserveCell.Extra && (firstCell.Extra=reserveCell.Extra)
        // 处理合并后的依赖关系 就是替换
        this.replaceCellRelation(reserveCell.Uid,firstCell.Uid)
        // 清空
        this.clearCell(reserveCell)
      }


      this.$set(firstCell,'merData',{
        type:'merge',
        mer:{
          sKey:firstCell.Uid,//保留的单元格的Uid
          rowspan: this.selectionEnd.row - this.selectionStart.row+1,
          colspan: this.selectionEnd.column - this.selectionStart.column+1,
        }
      })

      for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
        for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
          const element = this.config.data[i][j]
          if(i == this.selectionStart.row && j == this.selectionStart.column){
            continue
          }
          element.merData={
            type:'merged',
            mer:{
              sKey:firstCell.Uid,//左上角第一个单元格的Uid
            }
          }
        }        
      }

      let startCell = this.config.data[this.selectionStart.row][this.selectionStart.column]
      let target = this.$refs.tableRef.querySelector(`[data-key="${startCell && startCell.Uid}"]`)
      // 触发单元格的点击事件
      target.click()
    },
    unmergeCellsFun(){
      if((this.selectionStart.row || this.selectionStart.row==0) 
      && (this.selectionEnd.row || this.selectionEnd.row==0)
      && (this.selectionStart.column || this.selectionStart.column==0)
      && (this.selectionEnd.column || this.selectionEnd.column==0)){
        // 选区
        for (let i = this.selectionStart.row; i < this.selectionEnd.row+1; i++) {
          for (let j = this.selectionStart.column; j < this.selectionEnd.column+1; j++) {
            this.unmergeCellFun(this.config.data[i][j])
          }        
        }
      }else{
        // 单个单元格
        this.selectCell && this.unmergeCellFun(this.selectCell)
      }
      this.hasMergedCell=false
      // 取消合并后，调整选区(有的话)
      if((this.selectionStart.row || this.selectionStart.row==0) 
      && (this.selectionEnd.row || this.selectionEnd.row==0)
      && (this.selectionStart.column || this.selectionStart.column==0)
      && (this.selectionEnd.column || this.selectionEnd.column==0)){
        this.selectionStart.rowSpan=1
        this.selectionStart.colSpan=1

        this.selectionEnd.row += (this.selectionEnd.rowSpan-1)
        this.selectionEnd.column += (this.selectionEnd.colSpan-1)
        this.selectionEnd.rowSpan=1
        this.selectionEnd.colSpan=1
      }

    },
    unmergeCellFun(cell){
      if(!(cell.merData && cell.merData.type=='merge')) return
      let {row,col} = this.findDataByStartKey(cell.merData.mer.sKey)
      const sRow = row,
          sCol = col,
          eRow = row+cell.merData.mer.rowspan-1,
          eCol = col+cell.merData.mer.colspan-1

      for (let i = sRow; i < eRow+1; i++) {
        for (let j = sCol; j < eCol+1; j++) {
          this.config.data[i][j].merData=null
        }
      }
    },
    toolCellMergeFun(){
      if(this.hasMergedCell) this.unmergeCellsFun()
      else this.mergeCellFun()
    }
  },
};
</script>
<style scoped lang="scss">
.nodata {
  text-align: center;
  font-size: 16px;
  color: #666;
  padding: 100px 0;
}
.table-wrapper {
  width: 100%;
  overflow: auto;
  * { box-sizing: border-box; }

  .formula-wrapper {
    height: 42px;
    display: flex;
    align-items: center;
    background: #fff;
    border-radius: 4px;
    box-shadow: 0 3px 6px rgba(0, 0, 0, 0.05);
    border: 1px solid #DCDFE6;
    margin-bottom: 15px;
    padding: 0 15px;
  }
  .table td,th {
    width: 104px;
    min-width: 104px;
    height: 35px;
    max-height: 35px;
    background: #fff;
    text-align: center;
    word-break: break-all;
    border: 1px solid #dcdfe6;
    overflow: hidden;
    text-overflow: ellipsis;
    position: relative;
    color: #606266;

    &.td-chose::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 2px solid #0033ff;
      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
    }
    &.td-relation::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 2px dashed #0033ff;
      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
    }
    // &.td-col-select::after {
    //   position: absolute;
    //   top: 0;
    //   left: 0;
    //   right: 0;
    //   bottom: 0;
    //   content: "";
    //   display: block;
    //   outline: 0;
    //   border: 1px solid rgb(24, 173, 24);
    //   border-bottom: none;
    //   border-top: none;
    // }
    // &.td-row-select::after {
    //   position: absolute;
    //   top: 0;
    //   left: 0;
    //   right: 0;
    //   bottom: 0;
    //   content: "";
    //   display: block;
    //   outline: 0;
    //   border: 1px solid rgb(24, 173, 24);
    //   border-left: none;
    //   border-right: none;
    // }
    &.td-choose-insert-target::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 2px dashed orange;
      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
    }
  }

  .th-tg {
    background: #ebeef5;
    &:hover {
      cursor: pointer;
      background: #ddd;
      /* border: 2px solid #409eff; */
    }
    &.sm {
      width: 36px;
      min-width: 36px;
      max-width: 36px;
    }
  }
  //整行选中
  tr {
    position: relative;
    &.choose-all::after {
      position: absolute;
      top: 0;
      left: 0;
      right: 0;
      bottom: 0;
      content: "";
      display: block;
      outline: 0;
      border: 2px solid #5897fb;
      box-shadow: 0 0 5px rgba(73, 177, 249, 0.5);
    }
  }

  .contextMenu-wrapper {
    position: fixed;
    z-index: 99;
    top: -9999px;
    left: -9999px;
    background: #fff;
    padding: 10px 0;
    min-width: 180px;
    max-height: 400px;
    overflow-y: auto;
    /* border: 1px solid #999; */
    box-shadow: 0 1px 4px #999;
    .item {
      padding: 10px 25px;
      cursor: pointer;
      &:hover {
        background-color: #f5f7fa;
      }
      &:hover .subMenu-wrapper {
        display: block;
      }
    }

    .subMenu-wrapper {
      width: 180px;
      /* display: none; */
      padding: 10px 0;
      /* box-shadow: 0 1px 4px #999; */
      /* background: #fff; */
      /* position: absolute;
      right: -178px;
      top:-205px;
      max-height: 400px;
      overflow-y: auto; */
      .item {
        &:hover {
          background: #fff;
        }
      }
    }
  }
}
</style>
<style lang="scss">
.table-wrapper {
  td {
    .el-input__inner {
      border: none;
      outline: none;
      text-align: center;
      height: 34px;
      line-height: 34px;
    }
  }
  .el-input.is-disabled .el-input__inner {
    background-color: #fff;
  }
}
.formula-wrapper .el-input__inner { border: none; outline: none; }
.edb-select-popover {
  width: 300px !important;
  .edb-item {
    display: flex;
    justify-content: space-between;
    align-items: center;
    .edb-item-name {
      max-width: 260px;
    }
  }
}
.mixed-edb-slide-collapse {
  border: none !important;
  .el-collapse-item__header {
    padding: 0;
    height: auto;
    line-height: normal;
    margin-bottom: 0 !important;
    background: transparent !important;
  }
  .el-collapse-item__wrap {
    background: transparent !important;
    border: none !important;
  }
  .el-collapse-item__content {
    padding: 0 !important;
  }
}
</style>
