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

      <!-- 工具栏 -->
      <toolBarSection v-if="!disabled" :cell="selectCell" @updateCell="updateCellStyle"/>
      
      <!-- 公式显示区 -->
      <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"
        :style="disabled ? 'width:100%' : ''"
      >
        <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-key="cell.Uid"
              @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-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-key="cell.Uid"
              >
                {{cell.ShowFormatValue}}
              </span>

              <span
                :data-rindex="rowHeader[index]"
                :data-cindex="columnHeader[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]"
                :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>
      </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"
    />
  </div>
</template>
<script>
import {
  getRowHeaderCode,
  getColumnHeaderCode,
  selectCellStyle,
  selectMoreCellStyle,
  setRelationStyle,
  getRightClickMenu,
  checkDateFormat,
  setFocus,
  findCellByKey,
  resetRelationStyle,
  resetDialogCellStyle,
  extractFactorsFromFormula,
  findCellByFactorMixed,
  splitString,
  toUpperCase,
  findCellKeyByFactor,
  isNumberVal,
  transDecimalPlace
} 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 { formulaTip } from '@/views/dataEntry_manage/databaseComponents/util';
export default {
  props: {
    disabled: { //是否只预览
      type: Boolean,
      default: false,
    },
    sourceFrom:{
      type: Object,
      default: ()=>{
        return {}
      },
    }
  },
  components: { 
    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
    },
  },
  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: []

    };
  },
  mounted() {
    if(this.$route.path === '/addMixedSheet' && !this.$route.query.id) this.initData();
  },
  methods: {

    /* 输入时实时搜索 满足日期格式不搜索 有=视为输入公式不搜索  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.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.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)
    },

    /* 当前单元格是否和插入值有关联 无就不管 */
    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)
    },

    /* 单元格更新时去更新有依赖关系单元格的值 目前只更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)
      console.log(factors)
      
      //根据因数找单元格
      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 } = e.target.dataset;
      this.rightClickCell = {
        rindex,
        cindex,
        key
      }

      this.selectCell = cell;

      let pos;
      if(rindex==='-1') { //列头处
        pos = 'col'
      }else if(cindex==='-1') { //行头
        pos = 'row'
      }else {//单元格
        pos = 'cell'
      }
      this.config.contextMenuOption = pos === 'cell' 
        ? getRightClickMenu(pos,(cell.DataType===1&&[1,2].includes(cell.DataTimeType))||[5,7,8].includes(cell.DataType))
        : getRightClickMenu(pos)

      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';
        }

        ['col','row'].includes(pos) && selectMoreCellStyle(e);
        pos==='cell' && this.clickCell(e,cell);

      })
      
    },

    /*  */
    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
      }
      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();
      }

    },

    /* 清除单元格内容 格式 关联关系 */
    clearCell() {
      if([4,5].includes(this.selectCell.DataType)) resetRelationStyle();

      this.selectCell.DataType = 3;
      this.selectCell.ShowValue = '';
      this.selectCell.Value = '';
      this.selectCell.DataTime = '';
      this.selectCell.DataTimeType = 0;
      this.selectCell.EdbInfoId = 0;
      this.selectCell.ShowStyle = '';
      this.selectCell.ShowFormatValue = '';

      this.checkCellRelation(this.selectCell)
    },

    /* 删除行列 */
    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);

        //删除时清除关系
        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)
        })
      }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)
        
        if(this.insertRelationArr.length) {
          //删除时清除关系
          let delCellIds = this.config.data[index].map(cell => cell.Uid);
          
          this.clearRelationInsertCell(delCellIds);
        }

        this.config.data.splice(index,1)

      }
    },

    /* 删除时清除关联关系 和删除单元格有关联的插入值单元格和 */
    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);

      this.config.data.forEach((row,rindex) => {
        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}`)
        })
      })
      
    },

    /* 插入行 */
    insertRow(key) {
      let { rindex } = this.rightClickCell;
      
      let index = this.rowHeader.findIndex(_ => _ === rindex)

      let row = new Array(this.columnHeader.length).fill("").map((_,cindex) => ({
        ShowValue: "",
        Value: "",
        DataType: 3,
        DataTime: "",
        EdbInfoId: 0,
        Uid: md5.hex_md5(`${new Date().getTime()}${cindex}`)
      }));

      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;
    },

    /* 指标计算弹窗 */
    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();
      }
    },

    /* 日期计算弹窗 */
    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'))
    },

    /* 初始化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
      })
    },

     /* 处理因数结构 =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;
      }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.sourceFrom.text=sourceStr
      this.$emit('updateSourceName')
    }
  },
};
</script>
<style scoped lang="scss">
.nodata {
  text-align: center;
  font-size: 16px;
  color: #666;
  padding: 100px 0;
}
.table-wrapper {
  width: 100%;
  overflow: auto;

  .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>
