/**
*  @Author      LiuShaolong
*  @Description 通用页面
*  @CreateDate  2019/11/12 16:09
*/
<template>
  <el-container class="basic-page" :style="'height: ' + height + '; width: ' + width + '; border: 1px solid #eee'">
    <el-header v-if="$slots.header || showHeader" height="40px">
      <slot name="header"></slot>
    </el-header>
    <el-container style="overflow: auto;">
      <el-main style="padding: 0;">
        <el-row
            v-if="(searchable && searchFilters.length > 0) || buttons.length !== 0 || filterable || searchFilter && searchFilter.key">
          <el-col
              :style="'width: ' + ((searchable && searchFilters.length > 0) ? 'calc(100% - 54px);' : '100%;') + 'min-height: 36px'">
            <zy-button-group v-bind="$props" :items="buttons" :selection="selection" :params="params" @search="search"
                             :search-filter="searchFilter" :filter="tableFilter" @inline="inlineChange"
                             @filter="filter">
              <template #message>
                <slot name="message"></slot>
              </template>
            </zy-button-group>
          </el-col>
          <el-col v-if="!!searchable && searchFilters.length > 0" style="width: 44px; margin-left: 10px; float: right;">
            <el-button-group style="padding-top: 4px;">
              <el-button type="primary" @click="showSearch = !showSearch" icon="el-icon-search"></el-button>
            </el-button-group>
          </el-col>
        </el-row>
        <zy-table ref="commonTable" v-if="!$slots.mainContent" v-bind="$attrs" :filter="tableFilter"
                  :data-type="dataType" :source="tableSource" :pagination="pagination" :height="tableHeight"
                  :required-params="requiredParams" @selection-change="selectChange" @generate-slots="generateSlots"
                  @row-click="rowClick" @cell-click="cellClick" @header-click="headerClick" @refresh="refresh"
                  @header-dragend="headerDragend" @clear-filter="tableFilter = ''" @cell-edit="cellEdit">
          <template slot="before">
            <slot name="before"></slot>
          </template>
          <template v-for="item in columns" v-if="item.custom" :slot="item.key" slot-scope="scope">
            <slot :name="item.key" :row="scope['row']" :column="item"></slot>
          </template>
          <template slot="after">
            <slot name="after"></slot>
          </template>
          <template slot="pagination">
            <slot name="pagination"></slot>
          </template>
        </zy-table>
        <slot name="mainContent"></slot>
      </el-main>
      <el-aside v-if="searchable && searchFilters.length > 0" :width="showSearch ? asideWidth : '0'"
                style="transition: 200ms">
        <el-card class="common-form-card" style="height: 100%;"
                 body-style="height: calc(100% - 40px); overflow-y: auto; padding: 0 10px;">
          <div slot="header">
            <span>查询</span>
            <i style="float: right; padding: 3px 0 3px 15px; cursor: pointer;" class="el-icon-close"
               @click="showSearch = false"></i>
          </div>
          <zy-form ref="commonForm" :label-width="labelWidth" :filters="searchFilters"
                   :cols="formCols" :searchable="true" @search="onSearch">
            <template slot="customItem" slot-scope="scope">
              <slot name="customItem" :data="scope.data" :label-width="scope.labelWidth"></slot>
            </template>
          </zy-form>
        </el-card>
      </el-aside>
    </el-container>
  </el-container>
</template>
<script>

  export default {
    name: 'ZyPage',
    components: {},
    props: {
      showHeader: {type: Boolean, default: false},
      autoLoad: {type: Boolean, default: true},
      buttons: {type: Array, default: () => []},
      searchable: {type: Boolean, default: true},
      searchFilter: {type: Object, default: () => new Object},
      filterable: {type: Boolean, default: false,},
      searchFilters: {type: Array, default: () => []},
      request: {type: Function,},
      requestParams: {type: Object, default: () => new Object},
      dataType: {type: String, default: 'table'},
      pagination: {type: Boolean, default: true},
      labelWidth: {type: String, default: '100px'},
      tableColumns: {type: Array, default: () => []},
      tableData: {type: Array, default: () => []},
      height: {type: String, default: '100%'},
      width: {type: String,},
      formCols: {type: Number, default: 1},
      asideWidth: {type: String, default: '300px'},
      requiredParams: {type: Array, default: () => []},
      defaultExpandSearch: {type: Boolean, default: false}
    },
    data() {
      return {
        showSearch: false,
        selection: [],
        params: {},
        tableSource: {
          request: null,
          params: {},
          columns: [],
          data: []
        },
        columns: [],
        tableFilter: '',
        inline: true,
      }
    },
    created() {
    },
    mounted() {
      this.tableSource = {
        request: this.request,
        columns: this.tableColumns,
        data: this.tableData,
      };
      this.$nextTick(() => this.init())
    },
    watch: {
      showSearch: {
        handler: function () {
          setTimeout(window.onresize, 200);
        }
      },
      request: {
        handler: function (nv) {
          this.tableSource.request = nv;
        }
      },
      tableColumns: {
        handler: function (nv) {
          this.columns = nv;
          this.tableSource.columns = nv;
        },
        deep: true
      },
      tableData: {
        handler: function (nv) {
          this.tableSource.data = nv;
        },
        deep: true
      },
    },
    computed: {
      tableHeight: {
        get() {
          let space = 10;
          if (this.buttons.length !== 0 || ((this.searchable && this.searchFilters.length > 0)) || this.filterable || this.searchFilter && this.searchFilter.key) {
            space += 36;
          }
          if (this.buttons.length !== 0 && (this.filterable || this.searchFilter && this.searchFilter.key) && !this.inline) {
            space += 30;
          }
          return 'calc(100% - ' + space + 'px)';
        },
        set(value) {
        }
      }
    },
    methods: {
      init() {
        this.showSearch = this.defaultExpandSearch;
        for (let key in this.requestParams) {
          if (Object.prototype.hasOwnProperty.call(this.requestParams, key)) {
            this.params[key] = this.requestParams[key];
          }
        }
        if (!this.autoLoad) {
          return;
        }
        if (this.searchable && this.searchFilters.length > 0) {
          this.dataLoadWatcher();
        } else {
          this.getTableData();
        }
      },
      loadData(page, loading) {
        if (this.searchable && this.searchFilters.length > 0) {
          this.dataLoadWatcher();
        } else {
          this.getTableData(page, loading);
        }
      },
      refresh() {
        this.$emit('refresh');
      },
      dataLoadWatcher() {
        if (this.searchFilters.length === 0) {
          return this.getTableData();
        }
        if (this.formValidated()) {
          return this.getTableData();
        } else {
          this.showSearch = true;
          let unwatch = this.$watch(() => {
            return this.formValidated();
          }, (nv) => {
            if (nv) {
              this.getTableData();
              if (unwatch) {
                unwatch();
              }
            }
          }, {
            deep: true,
          })
        }
      },
      filter(filter) {
        this.tableFilter = filter;
      },
      inlineChange(inline) {
        this.inline = inline;
      },
      generateSlots(columns) {
        this.$emit('generate-slots', columns);
        this.columns = columns;
      },
      formValidated() {
        let valid = false;
        this.$refs['commonForm'].validateForm(v => {
          valid = v;
        });
        return valid;
      },
      getTableData(page, loading) {
        let formData = (this.searchable && this.searchFilters.length > 0) ? this.$refs['commonForm'].formData : {};
        this.params = _.merge(this.params, formData);
        for (let key in this.requestParams) {
          if (Object.prototype.hasOwnProperty.call(this.requestParams, key)) {
            this.params[key] = this.requestParams[key];
          }
        }
        let params = _.cloneDeep(this.params);
        this.tableSource.params = params;
        this.$nextTick(function () {
          if (!this.$slots.mainContent) {
            let table = this.$refs['commonTable'];
            table.getTable(page, table.size, loading);
          } else {
            this.$emit('load-data', params)
          }
        })
      },
      clearData() {
        this.tableSource.params = _.merge(this.params, this.requestParams);
        this.$refs['commonTable'].clearData();
      },
      selectChange(selection, total) {
        this.selection = selection;
        this.$emit('selection-change', selection, total)
      },
      rowClick(row, selection) {
        this.$emit('row-click', row, selection);
      },
      cellClick(row, column, cell, e) {
        this.$emit('cell-click', row, column, cell, e);
      },
      cellEdit(row, item, value, option) {
        this.$emit('cell-edit', row, item, value, option);
      },
      headerClick(column, e) {
        this.$emit('header-click', column, e);
      },
      headerDragend(newWidth, oldWidth, column, e) {
        this.$emit('header-dragend', newWidth, oldWidth, column, e);
      },
      search(init) {
        this.getTableData(1);
      },
      onSearch(val) {
        for (let key in val) {
          if (Object.prototype.hasOwnProperty.call(val, key)) {
            this.params[key] = val[key];
          }
        }
        this.getTableData(1);
      },
    },
  }
</script>
<style scoped lang="scss">
  .basic-page {
    .el-header {
      line-height: 40px;
      font-size: 16px;
      border-bottom: 1px solid #eeeeee;
      padding: 5px 10px;
      white-space: nowrap;
      text-overflow: ellipsis;
      overflow: hidden;
    }
  }
</style>
<style lang="scss">
</style>
