<template>
  <div class="vue-mobile-table">
    <div class="hidden-slot-content">
      <slot></slot>
    </div>
    <!-- 标题区域 -->
    <div
      class="vue-mobile-table-header"
      :style="{ padding: `0 ${transformPX(paddingConfig.LRPadding)}` }"
    >
      <div class="header-fix-column">
        <table-header
          :fixed="true"
          :store="store"
          :sortType="sortType"
          :sortField="sortField"
          :defaultFixItemWidth="defaultFixItemWidth"
          :borderConfig="borderConfig"
          :paddingConfig="paddingConfig"
          :sortableConfig="sortableConfig"
          @changeSort="changeSort"
        ></table-header>
      </div>
      <div class="header-active-column" ref="active-header">
        <table-header
          :store="store"
          :sortType="sortType"
          :sortField="sortField"
          :defaultFixItemWidth="defaultFixItemWidth"
          :sortableConfig="sortableConfig"
          :borderConfig="borderConfig"
          :paddingConfig="paddingConfig"
          @changeSort="changeSort"
        ></table-header>
      </div>
    </div>
    <!-- 内容区域 -->
    <div
      class="table-content-wrap"
      ref="table-content"
      :style="{ padding: `0 ${transformPX(paddingConfig.LRPadding)}` }"
    >
      <div class="table-content">
        <div :style="{ transform: getTransform }">
          <div class="pulldown-wrapper" v-show="!disablePullDown">
            <div v-show="beforePullDown">
              <span>下拉刷新</span>
            </div>
            <div v-show="!beforePullDown">
              <div v-show="isPullingDown">
                <span>加载中...</span>
              </div>
              <div v-show="!isPullingDown">
                <span>刷新成功</span>
              </div>
            </div>
          </div>
          <div class="vue-mobile-table-content">
            <div class="fixed-column-content" ref="fixed-col">
              <div class="fixed-column-content-wrap">
                <table-row
                  v-for="item in visibleData"
                  :key="item.code"
                  :source="item"
                  :fixed="true"
                  :store="store"
                  :defaultFixItemWidth="defaultFixItemWidth"
                  :item-height="itemHeight"
                ></table-row>
              </div>
            </div>
            <div class="active-column-content" ref="active-col">
              <div class="active-column-content-wrap">
                <table-row
                  v-for="item in visibleData"
                  :key="item.code"
                  :source="item"
                  :defaultFixItemWidth="defaultFixItemWidth"
                  :store="store"
                  :item-height="itemHeight"
                ></table-row>
              </div>
            </div>
          </div>
          <div class="pullup-tips">
            <div v-if="loadingComplete">没有了</div>
            <div v-else>
              <div v-if="!isPullUpLoad" class="before-trigger">
                <span class="pullup-txt">上拉加载更多</span>
              </div>
              <div v-else class="after-trigger">
                <span class="pullup-txt">加载中...</span>
              </div>
            </div>
          </div>
        </div>

        <div
          class="infinite-list-phantom"
          :style="{ height: listHeight + 'px' }"
        ></div>
      </div>
    </div>
  </div>
</template>

<script>
import tableRow from "./tableRow";
import TableStore from "./tableStore";
import BScroll from "@better-scroll/core";
import Pullup from "@better-scroll/pull-up";
import PullDown from "@better-scroll/pull-down";
import Indicators from "@better-scroll/indicators";
import InfinityScroll from "@better-scroll/infinity";

import commonMixIn from "./mixin";

BScroll.use(Pullup);
BScroll.use(PullDown);
BScroll.use(Indicators);
BScroll.use(InfinityScroll);

const TIME_BOUNCE = 800;
const THRESHOLD = 70;
const STOP = 50;
export default {
  name: "vue-mobile-table",
  mixins: [commonMixIn],
  components: {
    tableRow,
  },
  props: {
    dataKey: {
      type: String,
      default: "",
    },
    dataSource: {
      type: Array,
      default: () => [],
    },
    itemHeight: {
      type: Number,
      default: 60,
    },
    defaultFixItemWidth: {
      type: String,
      default: "30vw",
    },
    // 有些特殊需求上拉加载时需要清空之前的数据，reloadData为true会清除之前的数据
    reloadData: {
      type: Boolean,
      default: false,
    },
    requestData: {
      type: Function,
      default: () => {},
    },
    loadingComplete: {
      type: Boolean,
      default: false,
    }, // 加载完成，即没有数据可以加载了
    paddingConfig: {
      type: Object,
      default: () => ({
        LRPadding: 10,
      }),
    },
    borderConfig: {
      type: Object,
      default: () => ({
        innerBorder: true,
        color: "#e8eaec",
        borderType: "solid",
        headerBorder: true,
      }),
    },
    sortableConfig: {
      type: Object,
      default: () => ({
        iconSize: 5,
        color: "#ccc",
        activeColor: "#409eff",
      }),
    },
  },
  data() {
    return {
      store: new TableStore(), //状态管理器
      lock: false,
      disablePullDown: false,
      beforePullDown: true,
      isPullingDown: false,
      isPullUpLoad: false, // 上拉加载更多
      pullUpLoadErr: false,
      YScroll: null,
      xScroll: null,
      colHeaderScroll: null,
      headerColScroll: null,
      //可视区域高度
      screenHeight: 600,
      //偏移量
      startOffset: 0,
      // 可视区域前后缓存数量，防止滚动过快出现白屏现象
      baBuffer: 10,
      //起始索引
      start: 0,
      sortType: "", // 排序类型
      sortField: "", // 排序字段
      //结束索引
      end: null,
    };
  },
  computed: {
    //列表总高度
    listHeight() {
      return (
        this.dataSource.length * this.itemHeight -
        this.visibleData.length * this.itemHeight
      );
    },
    //可显示的列表项数
    visibleCount() {
      return Math.ceil(this.screenHeight / this.itemHeight);
    },
    //偏移量对应的style
    getTransform() {
      return `translate3d(0,${this.startOffset}px,0)`;
    },
    getHeight() {
      console.log(this.$refs["table-content"].clientHeight);
      return this.$refs["table-content"].clientHeight;
    },
    //获取真实显示列表数据
    visibleData() {
      return this.dataSource.slice(
        this.start,
        Math.min(this.end + this.baBuffer, this.dataSource.length)
      );
    },
  },
  watch: {
    dataSource: {
      immediate: true,
      handler: function () {
        // this.store.commit("setData", this.dataSource);
        this.$nextTick(() => {
          this.refreshScroll();
        });
      },
    },
  },
  methods: {
   
    refreshScroll() {
      if (this.YScroll) {
        this.YScroll.refresh();
      }
    },
    changeSort(sortType, sortField) {
      this.sortType = sortType;
      this.sortField = sortField;
      this.$emit("sortChangeEvent", this.sortType, this.sortField);
    },
    // 处理下拉刷新事件
    async pullingDownHandler() {
      if (!this.lock) {
        this.beforePullDown = false;
        this.isPullingDown = true;
        try {
          await this.requestDataInner(true);
        } finally {
          this.isPullingDown = false;
          this.finishPullDown();
        }
      }
    },
    // 处理列表滚动事件
    ScrollingHandler(pos) {
      if (pos.y >= 0) {
        this.disablePullDown = false;
      } else {
        this.disablePullDown = true;
      }
      //当前滚动位置
      let scrollTop = Math.abs(pos.y);
      //此时的开始索引
      this.start = pos.y > 0 ? 0 : Math.floor(scrollTop / this.itemHeight);
      //此时的结束索引
      this.end = this.start + this.visibleCount;
      //此时的偏移量 刷新期间不改变偏移量
      if (!(pos.y > 0)) {
        this.startOffset = scrollTop - (scrollTop % this.itemHeight);
      }
    },
    //处理上拉加载事件
    async pullingUpHandler() {
      // alert(1)
      if (!this.lock && !this.loadingComplete) {
        this.isPullUpLoad = true;
        try {
          await this.requestDataInner();
        } catch (error) {
          this.isPullUpLoad = false;
          this.pullUpLoadErr = true;
        }
        this.YScroll.finishPullUp();
        this.refreshScroll();
        this.isPullUpLoad = false;
      }
    },
    async finishPullDown() {
      this.YScroll.finishPullDown();
      this.refreshScroll();
      setTimeout(() => {
        this.beforePullDown = true;
      }, TIME_BOUNCE + 100);
    },
    /**
     * @description
     * @param {isFresh} 是否刷新
     * @returns {}
     */
    requestDataInner(isFresh = false) {
      this.lock = true;
      return new Promise((resolve, reject) => {
        this.requestData(isFresh)
          .then((res) => {
            // alert(1);
            this.lock = false;
            this.pullUpLoadErr = false;
            resolve(res);
          })
          .catch((err) => {
            this.lock = false;
            reject(err);
          });
      });
    },
    initYScroll() {
      this.YScroll = new BScroll(this.$refs["table-content"], {
        bounce: true,
        useTransition: true,
        click: true,
        pullUpLoad: true,
        // freeScroll: true,
        // eventPassthrough:'horizontal',
        pullDownRefresh: {
          threshold: THRESHOLD,
          stop: STOP,
        },
      });
      this.YScroll.on("pullingDown", this.pullingDownHandler);
      this.YScroll.on("scroll", this.ScrollingHandler);
      this.YScroll.on("pullingUp", this.pullingUpHandler);
    },
    // 左右滑动fei同步非固定列和非固定列头的滚动
    syncActiveColHeader() {
      this.colHeaderScroll = new BScroll(this.$refs["active-col"], {
        bounce: false,
        useTransition: true,
        scrollX: true,
        click: true,
        scrollY: false,
        indicators: [
          {
            relationElement: this.$refs["active-header"],
            interactive: false,
            ratio: 1,
          },
        ],
      });
    },

    // 左右滑动同步非固定猎头和非固定列滚动
    syncActiveHeaderCol() {
      this.headerColScroll = new BScroll(this.$refs["active-header"], {
        bounce: true,
        useTransition: true,
        click: true,
        scrollX: true,
        scrollY: false,
        indicators: [
          {
            relationElement: this.$refs["active-col"],
            interactive: false,
            ratio: 1,
          },
        ],
      });
    },
  },
  created() {},
  activated() {},
  updated() {},
  mounted() {
    this.$nextTick(() => {
      this.screenHeight = this.$refs["table-content"].clientHeight;
      this.start = 0;
      this.end = this.start + this.visibleCount;
      this.syncActiveColHeader();
      this.initYScroll();
      this.refreshScroll();
    });
  },
};
</script>

<style lang="less" scoped></style>
