<template>
  <div class="header-actions" v-if="getActionList.length != 0">
    <div class="overflow-box">
      <el-button
        v-for="(item, index) in getActionList"
        :key="index"
        :type="item.type || 'primary'"
        :plain="item.plain || false"
        v-bind="getHeaderActions(item)"
        @click="item.action"
        :disabled="item.disabled || false"
      >
        {{ item.text }}
      </el-button>
    </div>
  </div>
  <div class="table-list-container by-table">
    <!-- v-if="!hideHeader" -->
    <header v-if="false" class="header">
      <h2>{{ title }}</h2>
    </header>
    <div class="by-search" v-if="!hideSearch">
      <div style="display: flex">
        <div
          class="by-dropdown"
          v-for="(i, index) in selectConfigCopy"
          :key="i.prop"
          style="margin-right: 10px"
        >
          <div class="by-dropdown-title">
            {{ i.label || i.labelCopy
            }}<i
              style="margin-left: 5px"
              class="iconfont icon-iconm_xialan1"
            ></i>
          </div>
          <ul class="by-dropdown-lists">
            <li
              @click="searchItemSelct('all', i, index)"
              v-if="i.isShowAll === false ? i.isShowAll : true"
              style="
                display: flex;
                align-items: center;
                justify-content: center;
              "
            >
              {{$t('common.all')}}
            </li>
            <li
              v-for="j in i.data"
              :key="j.value"
              @click="searchItemSelct(j, i)"
              style="
                display: flex;
                align-items: center;
                justify-content: center;
              "
            >
              {{ j.label }}
            </li>
          </ul>
        </div>
      </div>

      <div style="display: flex">
        <el-input
          :placeholder="$t('common.pleaseEnterKeywords')"
          suffix-icon="search"
          size="mini"
          v-model="pagination.keyword"
          @keyup.enter="searchFn"
        >
        </el-input>
        <el-button
          type="primary"
          style="margin-left: 10px"
          size="default"
          @click="searchFn"
          >{{$t('common.search')}}</el-button
        >
        <div class="more-icon" @click="retrievalModalFn"><img src="@/assets/images/iconm_xiangyzk.png" alt=""></div>
      </div>
    </div>
    <component :is="containerTag">
      <div class="filter-form-container">
        <slot />
      </div>

      <el-table
        ref="hocElTable"
        v-loading="loading"
        :data="source"
        v-if="!hideTable"
        style="width: 100%"
        v-bind="$attrs"
        v-on="tableEvents"
        row-key="id"
        :tree-props="{ children: 'children', hasChildren: 'hasChildren' }"
        :height="tableHeight"
      >
        <el-table-column
          v-for="(item, index) in config"
          :key="index"
          v-bind="getAttrsValue(item)"
          :type="item.type || ''"
          :selectable="
            (rowData, rowIndex) => isSelectable(rowData, rowIndex, item)
          "
        >
          <template #default="scope" v-if="!item.type">
            <slot
              :name="item.attrs.slot"
              :item="scope.row"
              v-if="item.attrs.slot"
            >
              插槽占位符
            </slot>
            <div v-else-if="isFunction(getValue(scope, item))">
              <component
                :is="renderTypeList[getMatchRenderFunction(item)].target"
                :cell-list="getValue(scope, item)()"
                :row="scope.row"
                :parent="getParent"
                @click="
                  ($event) => {
                    handleNativeClick(getAttrsValue(item), $event, item);
                  }
                "
              />
            </div>
            <div v-else>
              {{ getValue(scope, item) }}
            </div>
          </template>
        </el-table-column>
      </el-table>

      <el-row
        v-if="!hidePagination"
        class="table-pagination"
        justify="end"
        type="flex"
      >
        <el-pagination
          background
          layout="total, sizes, prev, pager, next, jumper"
          :current-page="getPagination.pageNum"
          :page-size="getPagination.pageSize"
          :total="getPagination.total"
          @size-change="handleSizeChange"
          @current-change="handlePageChange"
        />
      </el-row>
    </component>
  </div>
</template>
  
  <script>
import { isFunction as isFn, isBoolean } from "./type";
import ElementsMapping from "./ElementsMapping";
import ComponentsMapping from "./ComponentsMapping";
import { computed, defineComponent, getCurrentInstance, ref } from "vue";
import expand from "./expand";
export default defineComponent({
  name: "Table",
  components: {
    ElementsMapping,
    ComponentsMapping,
  },
  props: {
    hideSearch: {
      type: Boolean,
      default: false,
    },
    hideTable: {
      type: Boolean,
      default: false,
    },
    //顶部搜索下拉配置
    selectConfig: {
      type: Array,
      default() {
        return [];
      },
    },
    // 获取表格元数据时携带的参数
    filterParams: {
      type: Object,
      default() {
        return {};
      },
    },
    // 表格加载 loading
    loading: {
      type: Boolean,
      default: false,
    },
    // 表格名称
    title: {
      type: String,
      default: "",
    },
    // 表格元数据
    source: {
      type: Array,
      required: true,
      default() {
        return [];
      },
    },
    tableHeight: {
      type: Number,
      required: false,
    },
    searchConfig: {
      type: Object,
      default() {
        return {
          keyword: "",
        };
      },
    },
    // 指定外层容器的渲染组件
    containerTag: {
      type: String,
      default: "div",
    },
    // 是否隐藏表头
    hideHeader: {
      type: Boolean,
      default: false,
    },
    // 是否隐藏分页
    hidePagination: {
      type: Boolean,
      default: false,
    },
    // 分页配置
    pagination: {
      type: Object,
      default() {
        return {};
      },
    },
    // 表格配置文件
    config: {
      type: Array,
      default() {
        return [];
      },
    },
    // 表头右上方的按钮组
    actionList: {
      type: Array,
      default() {
        return [{ text: "", action: () => {} }];
      },
    },
    // element table 原生事件
    tableEvents: {
      type: Object,
      default() {
        return {};
      },
    },
    searchKey: {
      type: String,
      default: "keyword",
    },
    // 是否显示过滤的全部选项
    // isShowAll: {
    //   type: Boolean,
    //   default: true,
    // },
  },
  setup(props) {
    const { proxy } = getCurrentInstance();
    const selectConfigCopy = computed(() => {
      return props.selectConfig.map((item) => {
        if (!item.labelCopy) item.labelCopy = { ...item }.label;
        return item;
      });
    });
    const retrievalModal = ref(false);
    console.log(selectConfigCopy);
    const getAttrsValue = (item) => {
      const { attrs } = item;
      const result = {
        ...attrs,
      };
      delete result.prop;
      return result;
    };
    const renderTypeList = ref({
      render: {},
      renderHTML: {
        target: "elements-mapping",
      },
      renderComponent: {
        target: "components-mapping",
      },
    });
    const getParent = computed(() => {
      return proxy.$parent;
    });
    const getPagination = computed(() => {
      const params = {
        pageNum: 1,
        pageSize: 10,
        total: 0,
      };
      return Object.assign({}, params, props.pagination);
    });
    const getActionList = computed(() => {
      return props.actionList
        .slice()
        .reverse()
        .filter((it) => it.text);
    });
    const getValue = (scope, configItem) => {
      const prop = configItem.attrs.prop;
      const renderName = getMatchRenderFunction(configItem);
      const renderObj = renderTypeList.value[renderName];
      if (renderObj && isFunction(configItem[renderName])) {
        return renderObj.target
          ? getRenderValue(scope, configItem, {
              name: renderName,
              type: "bind",
            })
          : getRenderValue(scope, configItem);
      }
      return scope.row[prop];
    };
    const getRenderValue = (
      scope,
      item,
      fn = { name: "render", type: "call" }
    ) => {
      const prop = item.attrs.prop;
      const propValue = prop && scope.row[prop];
      scope.row.$index = scope.$index;
      const args = propValue !== undefined ? propValue : scope.row;

      return item[fn.name][fn.type](getParent.value, args);
    };
    // 匹配 render 开头的函数
    const getMatchRenderFunction = (obj) => {
      return Object.keys(obj).find((key) => {
        const matchRender = key.match(/^render.*/);
        return matchRender && matchRender[0];
      });
    };
    const isFunction = (fn) => {
      return isFn(fn);
    };
    const searchFn = (val) => {
      console.log(props);
      proxy.$emit(
        "getList",
        Object.assign(props.filterParams, { [props.searchKey]: props.pagination.keyword })
      );
    }
    const retrievalModalFn = () => {
      proxy.$emit(
        "moreSearch",
        ''
      );
    };
    const handlePageChange = (val) => {
      proxy.$emit(
        "getList",
        Object.assign(props.filterParams, { pageNum: val })
      );
    };
    const handleSizeChange = (val) => {
      proxy.$emit(
        "getList",
        Object.assign(props.filterParams, { pageSize: val })
      );
    };
    const getHeaderActions = (item) => {
      return {
        ...item.attrs,
      };
    };
    const stopBubbles = (e) => {
      const event = e || window.event;
      if (event && event.stopPropagation) {
        event.stopPropagation();
      } else {
        event.cancelBubble = true;
      }
    };
    const handleNativeClick = ({ isBubble }, e, item) => {
      // 考虑到单元格内渲染了组件，并且组件自身可能含有点击事件，故添加了阻止冒泡机制
      // 若指定 isBubble 为 false，则当前单元格恢复冒泡机制
      if (isBoolean(isBubble) && !isBubble) return;
      stopBubbles(e);
    };
    //下拉搜索相关

    const searchItemSelct = (item, i, index) => {
      if (item == "all") {
        i.label = { ...props.selectConfig[index] }.labelCopy;
        proxy.$emit(
          "getList",
          Object.assign(props.filterParams, { [i.prop]: "" })
        );
        return;
      }
      i.label = item.label;
      console.log(item, i);
      proxy.$emit(
        "getList",
        Object.assign(props.filterParams, { [i.prop]: item.value })
      );
    };

    const isSelectable = (row, index, item) => {
      if (item.type === "selection") {
        if (item.attrs && item.attrs.checkAtt) {
          if (row[item.attrs.checkAtt]) {
            return row[item.attrs.checkAtt];
          }
        } else {
          return true;
        }
      }
    };

    return {
      getParent,
      getPagination,
      renderTypeList,
      getActionList,
      getAttrsValue,
      getValue,
      getRenderValue,
      getMatchRenderFunction,
      isFunction,
      handlePageChange,
      handleSizeChange,
      getHeaderActions,
      stopBubbles,
      handleNativeClick,
      searchFn,
      searchItemSelct,
      selectConfigCopy,
      isSelectable,
      retrievalModal,
      retrievalModalFn
    };
  },
});
</script>
  <style>
.table-list-container th {
  color: #333 !important;
}
.by-table td .el-button + .el-button {
  margin-left: 0 !important;
}
.by-table td .el-button {
  background: none !important;
  margin: 0 !important;
  padding: 8px 6px !important;
}
.el-checkbox__input.is-disabled .el-checkbox__inner {
  background-color: #dee1e6;
  border-color: #b2b4b9;
}
.el-table .cell {
  line-height: 34px;
}
</style>
  <style lang="scss" scoped>
.by-search {
  display: flex;
  justify-content: space-between;
  margin-bottom: 10px;
  .more-icon{
    float: right;
    cursor: pointer;
  }
}
.by-dropdown {
  position: relative;
  text-align: left;
  height: 32px;
  z-index: 1010;
  padding: 0 10px;
  transition: all 0.5s ease;
  cursor: pointer;
  line-height: 32px;

  .by-dropdown-title {
    font-size: 14px;
    background-color: #fff;
  }
  ul {
    position: absolute;
    left: 0;

    top: 32px;
    padding: 0;
    margin: 0;
    z-index: 100;
    display: none;
    white-space: nowrap;
    li {
      list-style: none;
      font-size: 12px;
      height: 30px;
      padding: 0 10px;
    }
    li:hover {
      background-color: #eff6ff;
      color: #0084ff;
    }
  }
}

.by-dropdown::before {
  display: block;
  width: 1px;
  content: " ";
  position: absolute;
  height: 14px;
  top: 8px;
  background-color: #ddd;
  right: 0;
  z-index: 1011;
}

.by-dropdown:hover {
  background: #ffffff;

  border-radius: 2px 2px 2px 2px;
  opacity: 1;
  ul {
    background: #ffffff;
    box-shadow: 0px 2px 16px 1px rgba(0, 0, 0, 0.06);
    border-radius: 2px 2px 2px 2px;
    opacity: 1;
    display: block;
    text-align: left;
  }
}
.header-actions {
  flex: 1;
  overflow-x: auto;
  padding: 20px;
  background: #fff;
  margin-bottom: 20px;
  .overflow-box {
    :deep() .el-button:nth-child(1) {
      margin-left: 10px;
    }
  }
}
.table-list-container {
  background: #fff;
  padding: 13px 20px 20px;
  .table-pagination {
    padding-top: 20px;
  }
  .header {
    display: flex;
    padding-bottom: 20px;
  }
  .el-table {
    :deep() th {
      font-size: 14px;
    }
    :deep() td {
      font-size: 14px;
    }
  }
}
.by-dropdown-lists {
  max-height: 50vh;
  overflow-y: auto;
  line-height: 1;
}
</style>