<template>
  <!-- 解决el-table 数据量过大导致卡顿现象 -->  
  <u-table
    :id="_uid"
    :key="isUpdate"
    v-loading="tableLoading"
    @sort-change="sortChange"
    @selection-change="handleSelectionChange"
    ref="multipleTable"
    :data="tableData"
    :row-key="rowKey"
    :border="tableBorder"
    style="width: 100%"
    :cell-style="cellStyle"
    :cell-class-name="cellClassName"
    use-virtual
    :height="uTableHeight"
    header-row-class-name="uTableHeader"
  >
    <!-- :tree-props="treeProps" 与 “height”  不能共存， 此组件暂不支持tree的格式-->
    <u-table-column v-if="selectionTable" fixed="left" type="selection" :reserve-selection="true" />
    <u-table-column v-if="isShowIndex" type="index" fixed="left" label="序号" width="50" />
    <template v-for="(item, index) in TableSize">
    <u-table-column
      min-width="150"
      :key="index"
      :prop="item.showProp ? item.prop + '.' + item.showProp : item.prop"
      :sortable="item.sortable"
      :fixed="setItemFixed(item,index)"
      :show-overflow-tooltip="showOverflowTooltip"
      :width="item.width"
      :align="item.tableAlign"
      :header-align="item.tableHeaderAlign"
      v-if="item.istrue==null?true:item.istrue"
    >
      <template #header>
        <span>{{ item.label }}</span>
        <i style="color: #f56c6c" v-if="item.rules && requiredRules">*</i>
      </template>
      <template slot-scope="scope">
        <!-- 正常表格回显 -->
        <div v-if="!isEditable">
          <!-- 时间转换 -->
          <span v-if="item.apiBaseType == 'datetime'"
            @click="showDetailInfo(scope.row[item.prop],'time')"
            style="cursor: pointer;"
            :title="'点击查看详情'"
            class="showDetailHover itemSpan"
          >
            {{ scope.row[item.prop] | formatDate }}
          </span>
          <!-- 枚举 -->
          <span v-else-if="item.isEnums" class="itemSpan">
            {{ initApiEnumList(item,scope.row[item.prop]) }}
          </span>
          <!-- 布尔 -->
          <span v-else-if="item.apiBaseType == 'boolean'" class="itemSpan">
            {{ scope.row[item.prop] ? '是' : '否' }}
          </span>
          <!-- 数值 -->
          <span v-else-if="item.apiBaseType == 'number'" class="itemSpan">
            {{ scope.row[item.prop] }}
          </span>
          <!-- 点击可出详情 | 点击可点出json （目前已知String|Guid）-->
          <span v-else
            class="itemSpan"  
            @click="showTypeHandle(initApiOtherType(scope.row[item.prop])[1],scope.row[item.prop])"
            :style="initApiOtherType(scope.row[item.prop])[1] != 'show' ? 'cursor: pointer' : ''"
            :title="'点击查看详情'"
            :class="{ showDetailHover: initApiOtherType(scope.row[item.prop])[1] != 'show' }"
          >
            {{ initApiOtherType(scope.row[item.prop])[0] }}
          </span>
        </div>
        <!-- 可编辑表格 -->
        <div v-else>
          <!-- 时间转换 -->
          <el-date-picker
            v-if="item.apiBaseType === 'datetime'"
            v-model="scope.row[item.prop]"
            type="datetime"
            placeholder="选择日期时间"
            format="yyyy-MM-dd HH:mm:ss"
            value-format="yyyy-MM-ddTHH:mm:ss"
            :disabled="Boolean(item.disabled)"
            size="mini"
          ></el-date-picker>
          <!-- 布尔、枚举 -->
          <el-select 
            v-else-if="item.isEnums || item.apiBaseType === 'boolean'"
            v-model="scope.row[item.prop]" 
            :placeholder="item.placeholder || '请选择' + item.label"
            :disabled="Boolean(item.disabled)"
            size="mini"
          >
            <el-option
              v-for="item in item.enums_list"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
          <!-- 数值 -->
          <el-input-number
            v-else-if="item.apiBaseType === 'number'"
            v-model="scope.row[item.prop]"
            :min="item.minimum || undefined"
            :max="item.maximum || undefined"
            :maxlength="item.maxLength || undefined"
            :minlength="item.minLength || undefined"
            :disabled="Boolean(item.disabled)"
            :placeholder="item.placeholder || '请输入' + item.label"
            @change="changeValue(item.prop,item,$event)"
            @clear="clearValue(item.prop,$event)"
            size="mini"
          ></el-input-number>
          <!-- 文本值 -->
          <el-input 
            v-else
            v-model="scope.row[item.prop]"
            :placeholder="item.placeholder || '请输入' + item.label"
            :disabled="Boolean(item.disabled)"
            size="mini"
          ></el-input>
        </div>
      </template>
    </u-table-column>
    </template>
    <!-- 操作列 （左侧）-->
    <u-table-column
      v-if="buttonOperationList_left"
      :fixed="'left'"
      width="auto"
      min-width="120px"
      :align="'center'"
      :header-align="'center'"
    >
      <template #header>
        <span>{{ $t('common.handle') }}</span>
      </template>
      <template slot-scope="scope">
        <el-button
          v-for="(itemButton, indexButton) in buttonOperationList_left"
          :key="indexButton"
          type="text"
          size="mini"
          @click="buttonOperationClick_left(scope.row, itemButton, indexButton)"
        >{{itemButton.label}}</el-button>
      </template>
    </u-table-column>
    <!-- 操作列 （右侧）-->
    <u-table-column
      v-if="buttonOperationList_right"
      :fixed="'right'"
      width="auto"
      min-width="120px"
      :align="'center'"
      :header-align="'center'"
    >
      <template #header>
        <span>{{ $t('common.handle') }}</span>
      </template>
      <template slot-scope="scope">
        <el-button
          v-for="(itemButton, indexButton) in buttonOperationList_right(scope.row)"
          v-show="!itemButton.hide"
          :key="indexButton"
          type="text"
          size="mini"
          v-permission="itemButton.permission || []"
          :style="{color:itemButton.color || '#409EFF'}"
          @click="buttonOperationClick_right(scope.row, itemButton, indexButton)"
        >{{itemButton.label}}</el-button>
      </template>
    </u-table-column>
    <slot></slot>

    <!-- 点开查看全部弹窗 -->
    <el-dialog 
      top="50px"
      :visible.sync="showDetailDialog"
      width="35%"
      :modal-append-to-body="false"
      :append-to-body="true"
      :show-close="true"
      :title="'内容详情'"
      :close-on-click-modal="true"
      :close-on-press-escape="true"
    >
      <el-input
        class="copyDetailInput"
        ref="copyDetailInput_ref"
        type="textarea"
        readonly
        autosize
        resize="none"
        v-model="showDetailData">
      </el-input>
      <!-- {{ showDetailData ? showDetailData + "" : showDetailData }} -->
    </el-dialog>

    <!-- 查看Json -->
    <showCopyJsonPop
      v-if="showJsonDialog"
      :JsonData="showJsonData"
      @closePop="closeJsonPop"
    ></showCopyJsonPop>

  </u-table>
</template>
<script>
import { formatTimeStrToStr } from "@/utils/formatTime";
import _ from "lodash";
import { getMatchRegConformValue } from "@/utils/index"
import showCopyJsonPop from "@/components/showCopyJsonPop"
import permission from "@/directive/permission/index"
export default {
  name: "currenTable",
  directives: { permission },
  components:{ showCopyJsonPop },
  filters: {
    formatDate(time) {
      if (time == null) {
        return '-'
      }
      return formatTimeStrToStr(time)
    },
  },
  props: {
    // table内表单数据是否可编辑
    isEditable:{
      type: Boolean,
      default: false
    },
    // 操作列按钮（左侧）
    buttonOperationList_left:{
      type: Array,
      default: null,
    },
    // 操作列按钮(右侧)
    buttonOperationList_right:{
      type: Function,
      default: null,
    },
    // 超出内容是否提示
    showOverflowTooltip:{
      type: Boolean,
      default: false,
    },
    // table是否有border
    tableBorder: {
      type: Boolean,
      default: true,
    },
    // 是否为第一个浮动，如果是，则item中的fixed无效（应用场景：主列表，因为用户排序不定元素为第一项）
    firstFixed: {
      type: Boolean,
      default: false,
    },
    propsData: {
      type: Object,
      default: () => {
        return {};
      },
    },
    tableData: {
      type: Array,
      default: () => {
        return [];
      },
    },
    tableLoading: {
      type: Boolean,
      default: false,
    },
    tableColumns: {
      type: Array,
      default: () => {
        return [];
      },
    },
    selectionTable: {
      type: Boolean,
      default: true,
    },
    requiredRules: {
      type: Boolean,
      default: true,
    },
    searchOptions: {
      type: Object,
      default: () => {
        return {};
      },
    },
    treeProps: {
      type: Object,
      default: () => {
        return {};
      }
    },
    // table key 字段设置顺序后需更新该值
    isUpdate: {
      type: Boolean,
      default: () => {
        return false
      }
    },
    rowKey:{
      type: String,
      default: 'id',
    },
    isShowIndex: {
      type: Boolean,
      default: false,
    },
    cellStyle: {
      type: Function,
      default: () => {
        return Function;
      }
    },
    cellClassName: {
      type: Function,
      default: () => {
        return Function;
      }
    },
    // 已app-main高度为100%  需要减掉的高度
    setUTableHeight: {
      type: Number,
      default: () => {
        return 280;
      }
    }
  },
  data() {
    return {
      dropCol: null,
      selectLoading: false,
      random: '',
      uTableHeight:null,//表格撑开高度
      showDetailDialog:false,//点开查看全部弹窗
      showDetailData:null,//点开查看全部内容
      showJsonDialog:false,//点开查看Json转换后table弹窗
      showJsonData:null,//点开查看Json的数据
    };
  },
  computed: {
    selectOptions() {
      return (val) => {
        if (val) {
          let options = this.$staticOptions[val];
          if (options) {
            return options();
          } else {
            return [];
          }
        } else {
          return false;
        }
      };
    },
    TableSize(){
      return  this.tableColumnsFilter()
    }
  },
  watch: {
    tableData: {
      handler(val, oldVal) {
        this.$nextTick(() => {
          if (this.$refs.multipleTable && this.$refs.multipleTable.doLayout) {
            this.$refs.multipleTable.doLayout()
          }
        });
      },
      immediate: false,
    },
    tableColumns: {
      handler(val, oldVal) {
        this.$nextTick(() => {
          if (this.$refs.multipleTable && this.$refs.multipleTable.doLayout) {
            this.$refs.multipleTable.doLayout()
          }
        });
      },
      immediate: false,
    },
    setUTableHeight(n,o){
      this.setTableHeightHandle(n)
    }
  },
  activated() {
    this.$refs.multipleTable.doLayout();
  },
  mounted() {
    this.random = this._uid
    this.setTableHeightHandle()
  },
  methods: {
    // 重新渲染表格
    doFreshLayout(){
      if (this.$refs.multipleTable && this.$refs.multipleTable.doLayout) {
        this.$refs.multipleTable.doLayout()
      }
    },
    // 设置表格高度
    setTableHeightHandle(height){
      let _height = height || this.setUTableHeight
      let _app_height = document.getElementsByClassName('app-main')[0].clientHeight
      this.uTableHeight = Number(_app_height) - Number(_height)
      this.$nextTick(() => {
        this.$refs.multipleTable.doLayout()
        this.$refs.multipleTable.$forceUpdate()
      });
    },
    // 获取表格高度 误删 业务当中有用
    getTableHeight(){
      return this.uTableHeight
    },
    setItemFixed(item,index){
      let _re = false
      if(this.firstFixed && item.fixed == 'left'){
        if(index == 0)_re = true
      }else{
        _re = item.fixed
      }
      return _re
    },
    // type=input情况下，框实时校验
    itemOnKeyUp(item,value){
      if(item.onkeyup){
        return item.onkeyup()
      }else{
        if(value && item.validType){
          this.searchData[item.prop]=getMatchRegConformValue(item.validType,value,item.pointNumberFixed)
        }
      }
    },
    // 数字类型input框onkeyup最大最小值处理
    typeNumberOnkeyup(item,value){
      if(value){
        let _match = String(value).match(/\d+/)//正整数
        this.searchData[item.prop] = _match?_match[0]:_match
      }
      if(this.searchData[item.prop] > item.max){
        this.searchData[item.prop] = item.max
      }
      if(this.searchData[item.prop] && this.searchData[item.prop] < item.min){
        this.searchData[item.prop] = item.min
      }
      if(item.onkeyup)item.onkeyup()
    },
    tableColumnsFilter() {
      let widthSize = _.cloneDeep(this.tableColumns);
      for(let i = 0;i<widthSize.length;i++){
        let item = widthSize[i]
        if (item.type == "autocomplete" || item.type == "objectAutocomplete") {
          item.width = item.width ? item.width: "300px";
        } else if (item.type == "input" || item.type == "objectInput") {
          if (item.width == '100%') {
            item.width = ''
          } else {
            item.width = item.width ? item.width: "200px";
          }
        } else if (
          item.type == "dateTimeInput" ||
          item.type == "objectDateTimeInput"
        ) {
          item.width =item.width ? item.width:  "200px";
        } else if (item.type == "objectDateTime" || item.type == "dateTime") {
          item.width =item.width ? item.width:  "200px";
        } else if (item.width == '100%') {
          item.width = ''
        } else {
          item.width =item.width ? item.width: 'auto';
        }
      }
      return widthSize
    },
    inputPlaceholder(val, item, type, func) {
      if (item.valueType) {
        if (type == "focus") {
          val.target.placeholder = "请输入" + item.label;
          if (val.target.value != "") {
            val.target.placeholder = val.target.value;
            val.target.value = "";
          }
        } else if (type == "blur") {
          //   val.target.value = "0"
          val.target.value = val.target.value.toString().replace(/[^\d.]/g,'')
          if (val.target.value == "") {
            // if (val.target.placeholder.indexOf('请输入') == -1) {
            val.target.value = val.target.placeholder;
            // }
          }
          if(item.showProp){
              func[item.prop][item.showProp]= Number(val.target.value)
            }else{
              func[item.prop]= Number(val.target.value)
            }
        }
      }
    },
    //autocomplete下拉
    querySearch(queryString, cb, val, row) {
      const { options, optionsValue, optionsLabel } = val;
      let func = val.focus;
      let data = {
        scope: row,
      };
      if (queryString) {
        data.filter = [
          {
            logic: "And",
            column: optionsValue,
            action: "Like",
            value: queryString,
          },
        ];
      }
      func(data).then((res) => {
        var restaurants = this.searchOptions["options"];
        let results = queryString
          ? restaurants.filter(
              this.createFilter(queryString, optionsValue, optionsLabel)
            )
          : restaurants;
        results.forEach((key) => {
          if (typeof optionsValue === "string") {
            key.value = key[optionsValue] + "----" + key[optionsLabel];
          } else {
            key.value =
              key[optionsValue[0]][optionsValue[1]] +
              "----" +
              key[optionsLabel];
          }
        });
        // 调用 callback 返回建议列表的数据
        cb(results);
      });
    },
    createFilter(queryString, optionsValue, optionsLabel) {
      return (restaurant) => {
        if (typeof optionsValue === "string") {
          restaurant.value =
            restaurant[optionsValue] + "----" + restaurant[optionsLabel];
        } else {
          restaurant.value =
            restaurant[optionsValue[0]][optionsValue[1]] +
            "----" +
            restaurant[optionsLabel];
        }
        return (
          restaurant.value.toLowerCase().indexOf(queryString.toLowerCase()) !=
          -1
        );
      };
    },
    handleSelect(item, val, scope) {
      let data = this.tableData[scope.$index];
      if (!val.showProp) {
        if (typeof val.optionsValue === "string") {
          data[val.prop] = item[val.optionsValue];
        } else {
          data[val.prop] = item[val.optionsValue[0]][val.optionsValue[1]];
        }
      } else {
        if (typeof val.optionsValue === "string") {
          data[val.prop][val.showProp] = item[val.optionsValue];
        } else {
          data[val.prop][val.showProp] =
            item[val.optionsValue[0]][val.optionsValue[1]];
        }
      }
      this.$emit("push", item, scope, val);
    },
    getMaxLength(arr) {
      return arr.reduce((acc, item) => {
        if (item) {
          const calcLen = this.getTexWidth(item);
          if (acc < calcLen) {
            acc = calcLen;
          }
        }
        return acc;
      }, 0);
    },
    getTexWidth(str) {
      let width = 0;
      const html = document.createElement("span");
      html.innerText = str;
      html.className = "getTextWidth";
      document.querySelector("body").appendChild(html);
      width = document.querySelector(".getTextWidth").offsetWidth;
      document.querySelector(".getTextWidth").remove();
      return width;
    },
    flexColumnWidth(label, prop) {
      const arr = this.tableData.map((x) => {
        if (typeof prop !== "string") {
          return x[prop[0]][prop[1]];
        } else {
          return x[prop];
        }
      });
      arr.push(label);
      return this.getMaxLength(arr) + 60 + "px";
    },
    //排序
    sortChange(data) {
      this.$emit("sortChange", data);
    },
    //点击selection框
    handleSelectionChange(val) {
      this.$emit("handleSelectionChange", val);
    },
    //点击name提交emit打开编辑页面
    inlineDialog(row) {
      this.$emit("inlineDialog", row);
    },
    //可点出详情弹窗
    showDetailInfo(row,type) {
      this.showDetailDialog = true
      let _row = typeof row == 'object' ? JSON.stringify(row, null, '\t') : row
      this.showDetailData = type == 'time' ? formatTimeStrToStr(row) : _row
      this.$emit("showDetailInfo", this.showDetailData);
      this.$nextTick(()=>{
        if(this.$refs.copyDetailInput_ref){
          this.$refs.copyDetailInput_ref.focus()
          this.$refs.copyDetailInput_ref.$refs.textarea.scrollTop = 0
        }
      })
    },
    closeJsonPop(){
      this.showJsonDialog = false
    },
    // 可点出json转换的table弹窗
    showJsonTable(row){
      this.showJsonDialog = true
      let _json = eval('(' + row + ')')
      this.showJsonData = _json
    },
    //点击按钮打开自定义弹窗
    buttonClick(row, index, label) {
      this.$emit("buttonClick", row, index, label);
    },
    //点击table操作列(左侧)按钮
    buttonOperationClick_left(row, item, index) {
      this.$emit("buttonOperationClick_left", row, item, index);
    },
    //点击table操作列(右侧)按钮
    buttonOperationClick_right(row, item, index) {
      this.$emit("buttonOperationClick_right", row, item, index);
    },
    // 转义枚举值
    initApiEnumList(item,data){
      let _item_enumList = {}
      if(item.enums_list){
        item.enums_list.forEach((item,key)=>{
          _item_enumList[item.value] = item.label
        })
      }
      return _item_enumList[data] || '未定义'
    },
    // 其他类型转义，直接显示 | 点击可出详情 | 点击可点出json
    initApiOtherType(data){
      try {
        let _json = JSON.parse(data)
        // 数值类型
        if(typeof _json == 'number' && _json){
          return [data,'show']
        }else{
          return [data,'json']
        }
      }
      // 直接显示
      catch(err){
        return [data,'detail']
      }
    },
    // 判断操作
    showTypeHandle(type,row){
      if(type == 'detail')this.showDetailInfo(row)
      if(type == 'json')this.showJsonTable(row)
    },
    // 可编辑表单：值更改函数
    changeValue(prop,item,val) {
      this.$emit("changeValue", prop, item, val)
    },
    // 可编辑表单：值清除函数
    clearValue(prop,item,val) {
      this.$emit("clearValue", prop, item, val)
    },
  },
};
</script>
<style lang="scss" scoped>
::v-deep .uTableHeader th{
  background: #f6f7fb !important;
  border: none !important;

  // &:last-child{
  //   background: unset !important;
  // }
}
::v-deep .el-form-item__error{
  position: relative;
}
::v-deep .el-table__fixed {
  display: block-inline !important;
  height: 100% !important;
  // bottom: 13px !important;
  .el-table__fixed-header-wrapper {
    z-index: auto !important;
  }
  .el-table__fixed-body-wrapper {
    z-index: auto !important;
  }
}
::v-deep .el-table__fixed-right {
  display: block-inline !important;
  height: auto !important;
  bottom: 13px !important;
  .el-table__fixed-header-wrapper {
    z-index: auto !important;
  }
  .el-table__fixed-body-wrapper {
    z-index: auto !important;
  }
}
::v-deep .el-table__fixed::before,
.el-table__fixed-right::before {
  z-index: auto !important;
}
.spamHover {
  color: #409eff;
  cursor: pointer;
}
.spamHover:hover {
  border-bottom: 1px solid #409eff;
  color: blue;
}
.showDetailHover:hover{
  color: #409eff;
}
span {
  white-space: pre;
}
::v-deep .el-select {
  .el-input__inner {
    padding: 0 30px 0 15px;
  }
  .el-input__prefix {
    width: 100% !important;
    left: 0;
    .el-button {
      position: absolute;
      top: 0;
      right: 0;
    }
  }
}
.u-table::before {
  height: 0px;
}

.itemSpan{
  white-space: nowrap !important
}
::v-deep .copyDetailInput{
  textarea{
    max-height: calc(100vh - 220px) !important;
    overflow: auto !important;
  }
}
</style>