<template>
  <div class="CmsEditTable">
    <vxe-grid
      ref="tableRef"
      size="small"
      v-bind="$attrs"
      v-on="listeners"
      v-loading="loading"
      element-loading-spinner="el-icon-loading"
      element-loading-background="rgba(0, 0, 0, 0.5)"
      :element-loading-text="'正在加载中，请稍等...'"
      :columns="columns"
      :loading="false"
      :height="tableHeight"
      :menu-config="menuConfig"
      :valid-config="validConfig"
      :keyboard-config="keyboardConfig"
      :custom-config="customConfig"
      :mouse-config="mouseConfig"
      :show-overflow="showOverflow"
      :toolbar-config="toolsBar ? toolsBarConfig : false"
      :checkbox-config="{
        // trigger: 'row',
        highlight: true,
        range: false,
        checkMethod: defaultCheckMethod
      }"
      :row-config="{
        useKey: 'id',
        isCurrent: true,
        isHover: true,
      }"
      :column-key="true"
      :seq-config="{ seqMethod: seqMethod }"
      :highlight-hover-row="true"
      :edit-config="tableEditConfig"
      :export-config="{
        filename: new Date().getTime(),
      }"
    >
      <template slot="form">
        <slot name="form" v-if="formItemConfig.length === 0"></slot>
        <el-card class="box-card" v-else>
          <cms-query-form-condition
            ref="queryFormRef"
            :disabled="disabled"
            :query-params="queryParams"
            :query-rules="queryRules"
            :label-width="labelWidth"
            :items="items"
            :item-column="itemColumn"
            @search="search"
            @reset="reset">
            <template v-for="(item) in items" :slot="item.prop">
              <slot :name="item.prop"></slot>
            </template>
          </cms-query-form-condition>
        </el-card>
      </template>
      <template slot="buttons">
        <div class="toolbar-tools-left">
          <slot name="left-button">
            <cms-button-group v-if="toolsBar">
              <cms-button
                @click="item.onClick"
                v-for="item in toolsBar"
                v-permission="[item.access]"
                :disabled="disabled"
                :key="item.title"
                :type="item.status"
                :icon="item.icon">
                {{ item.title }}
              </cms-button>
              <slot name="buttons"></slot>
            </cms-button-group>
          </slot>
        </div>
      </template>
      <template slot="pager" v-if="pagination">
        <vxe-pager
          @page-change="pageChange"
          :auto-hidden="false"
          :current-page.sync="tablePage.currentPage"
          :perfect="true"
          :page-size.sync="tablePage.limit"
          :total="tablePage.total"
          :layouts="[
            'PrevJump',
            'PrevPage',
            'Number',
            'NextPage',
            'NextJump',
            'Sizes',
            'FullJump',
            'Total',
          ]"
        >
        </vxe-pager>
      </template>
      <template slot="top">
        <slot name="top"></slot>
      </template>
      <template slot="bottom">
        <slot name="bottom"></slot>
      </template>
    </vxe-grid>
  </div>
</template>

<script>
import { mixTableConstants } from "../mixin/common-mixins";
import "./_CmsEditTable.less";

export default {
  mixins: [ mixTableConstants ],
  props: {
    columns: Array,
    parentHeight: {
      type: Number,
      default: () => {
        return 0;
      },
    },
    customForm: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    labelWidth: {
      type: String,
      default: () => {
        return "100px";
      },
    },
    emptyText: {
      type: String,
      default: () => {
        return "";
      },
    },
    formRule: {
      type: Object,
      default: () => {
        return {};
      },
    },
    showRight: {
      type: Boolean,
      default: () => {
        return false;
      },
    },
    formItemConfig: {
      type: Array,
      default: () => {
        return [];
      },
    },
    keyboardConfig: {
      type: Object,
      default: () => {
        return { isArrow: true }
      }
    },
    tableConfig: {
      type: Object,
      default: () => {
        return {
          enable: false,  // 是否启用表格配置
          configCode: undefined, // 配置表格的编号， 唯一值
          saveConfigUrl: Function, // 保存表格配置信息的地址
          queryConfigUrl: Function, // 查询表格配置信息的地址
        }
      }
    }
  },
  data() {
    return {
      items: [],
      tableHeight: "auto",
      itemColumn: undefined,
      toolsBarConfig: {
        size: "small",
        perfect: true,
        slots: {
          buttons: "buttons",
        },
      },
    };
  },
  watch: {
    requestCall: {
      handler(val) {
        if (Array.isArray(val)) {
          if (this.$refs["tableRef"]) this.$refs["tableRef"].loadData(val);
        }
      },
      immediate: true,
      deep: true,
    },
    'height': {
      handler(val) {
        if (this.fixedHeight) {
          this.tableHeight = val;
        }
      },
      immediate: true
    },
  },
  computed: {
    tableEditConfig() {
      return {
        trigger: 'manual',
        mode: 'row',
        autoClear: false,
        ...this.editConfig
      };
    }
  },
  // 激活组件
  async created() {
    this.initColumns();
    if (this.fixedHeight) {
      this.tableHeight = this.height;
    } else {
      const h = window.document.body.clientHeight;
      if (h < 800) this.tableHeight = h - this.marginTop - 2;
      else this.tableHeight = h - this.marginTop;
    }
    this.initTableData();
  },
  activated() {
    this.initTableData();
  },
  methods: {
    getRef() {
      return this.$refs["queryForm"].getRef();
    },
    initColumns() {
      this.columns.forEach(col => {
        if (!col.visible) {
          col.visible = true;
        }
        if (!col.align) {
          col.align = 'left'
        }
      })

      if (this.tableConfig.enable) {
        const params = { configCode: this.tableConfig.configCode };
        this.tableConfig.queryConfigUrl({ ...params }).then(res => {
          if (res.code === 200) {

          }
        })
      }
    },
    defaultCheckMethod(params) {
      if (this.checkMethod) {
        return this.checkMethod(params);
      }
      const row = params.row;
      return row['approvalStatus'] !== 4;
    },
    /**
     * 导出操作
     */
    openExportEvent() {
      const cols = []
      this.columns.forEach(item => {
        if (item.field !== 'opts' && item.field !== 'checkbox' && item.field !== 'radio') {
          cols.push(item)
        }
      })
      this.$refs.tableRef.openExport({
        columns: cols,
      })
    },
    handleClick(tab, event) {
      console.log(tab, event);
    },
    search() {
      this.reload();
      if (this.searchMethod) {
        this.searchMethod()
      }
    },
    // 搜索添加验证
    validate(callback) {
      this.$refs.queryFormRef.validate(valid => {
        if (callback) callback(valid);
        return false;
      })
    },
    initTableData() {
      this.$forceUpdate();
      if (!Array.isArray(this.formItemConfig)) {
        this.items = this.formItemConfig.items;
        this.itemColumn = this.formItemConfig.column;
      } else {
        this.items = this.formItemConfig;
      }
      if (this.constantLoad && typeof this.constantLoad === 'function') {
        this.constantLoad({}).then(data => {
          if (this.initLoadTableData) {
            console.log('执行完成， 准备加载表格...', data);
            setTimeout(() => {
              this.loadTableData();
            }, 200)
          }
        })
      } else {
        if (this.initLoadTableData) {
          this.loadTableData();
        }
      }
    },
    reset() {
      for (const key in this.queryParams) {
        this.queryParams[key] = undefined
      }
      this.$emit('reset')
    },
    /**
     * 初始化加载表格
     */
    loadTableData() {
      if (!this.requestCall) {
        this.$messageTips.warning("请求地址不存在，请检查配置.");
        return false;
      }
      this.loading = true
      if (typeof this.requestCall === "function") {
        if (this.pagination) {
          this.queryParams.rows = this.tablePage.pageSize;
          this.queryParams.page = this.tablePage.currentPage;
        }
        this.requestCall(this.queryParams, { loading: false }).then((response) => {
          if (this.pagination && this.$refs["tableRef"] && response) {
            const { rows, total, extraMap, code } = response;
            if (code === 200) {
              this.$refs["tableRef"].loadData(rows);
              this.tablePage.total = total;
              setTimeout(() => {
                this.loading = false;
              }, 300);
              if (this.resultCallback) {
                this.resultCallback(rows, extraMap);
              }
            } else {
              this.loading = false
              this.$messageTips.error(response.msg);
            }
          } else {
            if (this.$refs["tableRef"] && response) {
              debugger;
              const { data } = response;
              this.$refs["tableRef"].loadData(data);
              if (this.resultCallback) {
                this.resultCallback(data);
              }
            }
            this.loading = false
          }
        }).catch(() => {
          this.loading = false;
        });
      } else if (Array.isArray(this.requestCall)) {
        this.$refs["tableRef"].loadData(this.requestCall);
        this.loading = false
      } else if (typeof this.requestCall == "object") {
        if (this.pagination && this.$refs["tableRef"]) {
          this.$refs["tableRef"].loadData(this.requestCall["rows"]);
          this.tablePage.total = this.requestCall["total"];
        } else {
          this.tableData = this.requestCall;
        }
        this.loading = false
      }
    },
    setTableData(data = []) {
      this.$refs["tableRef"].loadData(data);
    },
    /**
     * 获取多条件展开
     */
    getFolding() {
      this.collapse = !this.collapse;
    },
    newInstance() {
      return this.$refs["tableRef"];
    },
    getCheckboxRecords() {
      return this.$refs["tableRef"].getCheckboxRecords();
    },
    reload() {
      this.loadTableData();
    },
    pageChange({ type, currentPage, pageSize }) {
      if (type === "size") {
        this.tablePage.currentPage = 1;
        this.tablePage.pageSize = pageSize;
      } else {
        this.tablePage.currentPage = currentPage;
      }
      this.loadTableData();
    },
    currentChange(event) {
      this.$emit("current-change", event);
    },
    filterMethod({ value, row, column }) {
      console.log(value, row, column);
    },
    cellDblClick(data) {
      this.$emit("cell-dblclick", data);
    },
    // finishCallback 配置完成进行重新加载， 并且保存到数据库
    finishCallback(columns) {
      this.visibleColumnConfig = false;
      console.log('finishCallback:', columns);
      this.$refs['tableRef'].reloadColumn(columns);
      if (this.tableConfig.enable) {
        const params = { configCode: this.tableConfig.configCode };
        this.tableConfig.saveConfigUrl({ ...params }).then(res => {
          if (res.code === 200) {
            this.$messageTips.success(res.msg);
          }
        })
      }
    },
    closeModalCallback(visible) {
      this.visibleColumnConfig = visible;
    },
    /**
     * 往表格插入临时数据，从指定位置插入一行或多行；
     * 第二个参数：row 指定位置（不支持树表格）、
     * null从第一行插入、-1 从最后插入
     * 返回: records: Array<object>, row?: Row
     * 用法:
     */
    async insertAt(records = {}, row) {
      let table = this.newInstance();
      let hasActive = table.getActiveRecord();
      if (hasActive) {
        return Promise.reject(hasActive);
      }
      let result = { row_status: 'add', ...records, row_add: true };
      const { row: newRow } = await table.insertAt(result, row);
      await this.newInstance().setActiveRow(newRow);
      return Promise.resolve(newRow);
    },
    // 获取新增内容
    getInsertRecords() {
      return Promise.resolve(this.newInstance().getInsertRecords());
    },
    // 获取修改内容
    getUpdateRecords() {
      return Promise.resolve(this.newInstance().getUpdateRecords());
    },
    // 获取删除内容
    getRemoveRecords() {
      return Promise.resolve(this.newInstance().getRemoveRecords());
    },
    getAllRecords() {
      return Promise.resolve(this.newInstance().getTableData());
    },
    // 还原操作
    revertAt() {
      return this.newInstance().revertData();
    },
    // 打开编辑操作
    setActiveRow(row) {
      return this.newInstance().setActiveRow(row);
    },
    clearActived() {
      return this.newInstance().clearActived();
    },

    batchLines(row) {
      let rows = this.batchSave(row);
      return new Promise(resolve => {
        this.newInstance().reloadData(rows).then(() => {
          resolve({ rows, row });
        });
      });
    },
    batchSave(row) {
      /**
       * 此处待优化
       * 1. vxe-table 里面有getCheckboxRecords()方法
       */
      let isCheckboxConfig = !!Object.keys(this.checkboxConfig || {}).length,
        checkboxKey = isCheckboxConfig ? this.checkboxConfig.checkField : '';
      return this.tableData.map(tr => {
        if (isCheckboxConfig && tr[checkboxKey]) {
          for (let key in row) {
            let td = row[key];
            if (!(td == null || td.length === 0)) {
              tr[key] = td;
            }
          }
        }
        return tr;
      });
    },
    removeRow(row) {
      return this.newInstance().remove(row);
    },
    // 表格调度中心 = 代理 + 适配 模式
    tableDispatch(methodName, ...args) {
      return this.getTable()[methodName](...args);
    }
  },
}
</script>

<style scoped lang="less">
/deep/ .el-card__body {
  padding: 0 !important;
}

/deep/ .el-card__header {
  padding: 10px;
  background: #f8f8f9 !important;

  .clearfix {
    span {
      i {
        margin-right: 5px;
      }
    }
  }
}

/deep/ .cms-form .r-main {
  padding: 0;
}

/deep/ .cms-form .r-bottom {
  line-height: 55px;
  height: 45px;
  padding: 0 !important;
}

.cms-search-container {
  display: flex;
  width: 100%;
  flex-direction: row;

  .cms-search-form {
    flex: 1;
  }

  .cms-search-tools {
    width: auto;
    padding-top: 10px;
    padding-left: 10px;
  }
}

.toolbar-tools {
  display: flex;
  flex-direction: row;

  .toolbar-tools-left {
    flex: 1;
  }

  .toolbar-tools-right {
    width: auto;
  }
}
</style>
