
<template>
  <div class="filter-base-bar">
    <el-form
      ref="filterForm"
      :label-position="labelPosition"
      :label-width="labelWidth"
      :size="size"
      class="el-form-filter"
      @keyup.enter.native="handleFilter()"
      :inline="false"
    >

      <el-row :gutter="20">
        <el-col
          v-for="(item, index) in filters"
          :key="index"
          :span="item.col ? item.col : 8"
          :offset="item.offset || 0"
        >
          <el-form-item :label="item.label">
            <el-date-picker
              v-if="item.type === 'timePickerRange'"
              class="filter-full-width"
              v-model="filterData[item.fieldName]"
              :size="size"
              :type="item.timePickerRangeType || 'daterange'"
              :format="item.format"
              :value-format="item.valueFormat||'timestamp'"
              :range-separator="item.rangeSeparator || '至'"
              :start-placeholder="item.startPlaceholder"
              :end-placeholder="item.endPlaceholder"
              :default-time="item.defaultTime ||['00:00:00', '00:00:00']"
              @change="itemChange(filterData[item.fieldName],item)"
            >
            </el-date-picker>

            <el-input
              class="filter-full-width"
              v-else-if="item.type === 'input'"
              :placeholder="item.placeholder"
              :size="size"
              v-model="filterData[item.fieldName]"
              :clearable="item.clearable"
              @change="itemChange(filterData[item.fieldName],item)"
            />

            <el-input-number
              class="filter-full-width"
              :size="size"
              v-else-if="item.type === 'inputNumber'"
              :placeholder="item.placeholder"
              v-model="filterData[item.fieldName]"
              @change="itemChange(filterData[item.fieldName],item)"
            />

            <el-select
              class="filter-full-width"
              v-else-if="item.type === 'select'"
              v-model="filterData[item.fieldName]"
              :placeholder="item.placeholder"
              :size="size"
              :clearable="item.clearable"
              :filterable="item.filterable"
              :multiple="item.multiple"
              @change="itemChange(filterData[item.fieldName],item)"
            >

              <template v-for="(option, i) in filterData[item.fieldName + 'Options']">
                <el-option
                  v-if="option"
                  :key="i"
                  :label="option.name"
                  :value="option.value"
                >
                </el-option>
              </template>
            </el-select>

            <section
              v-else-if="item.type === 'numberRange'"
              class="number-range-container filter-full-width"
            >
              <el-input-number
                :placeholder="item.startPlaceholder"
                v-model="filterData[item.fieldName][0]"
                :size="size"
                @change="itemChange(filterData[item.fieldName],item)"
              />
              <span class="normal-text">{{item.rangeSeparator || '至'}}</span>
              <el-input-number
                :placeholder="item.endPlaceholder"
                v-model="filterData[item.fieldName][1]"
                :size="size"
                @change="itemChange(filterData[item.fieldName],item)"
              />
            </section>

            <Cascader
              :size="size"
              ref="cascader"
              v-else-if="item.type === 'cascader'"
              :lazy="item.lazy"
              :filterable="item.filterable"
              :options="item.options"
              :multiple="item.multiple"
              :cascaderData="item.cascaderData"
              :checkStrictly="item.checkStrictly"
              :cascaderValue="filterData[item.fieldName]"
              :placeholder="item.placeholder"
              :nodeFieldName="item.nodeFieldName"
              :nodeValueFieldName="item.nodeValueFieldName"
              :dataKeyFieldName="item.dataKeyFieldName"
              @onCascaderChange="(selection) => handleCascaderChange(selection, item)"
            />
          </el-form-item>
        </el-col>

        <el-col
          :span="buttonCol"
          class="button-box"
        >
          <el-button
            :size="size"
            type="primary"
            @click="handleFilter"
          >{{searchText}}</el-button>
          <el-button
            v-if="clearable"
            :size="size"
            type="info"
            @click="handleReset"
          >{{resetText}}</el-button>
          <slot name="otherButton"></slot>
        </el-col>

      </el-row>
    </el-form>
  </div>
</template>

<script>
import Cascader from '../cascader/Cascader.vue';
import _ from 'loadsh';
export default {
  name: "FilterBaseBar",
  components: { Cascader },
  props: {
    labelPosition: {
      type: String,
      default: function () {
        return 'right'
      }
    },
    labelWidth: {
      type: String,
      default: function () {
        return '120px'
      }
    },
    filters: {
      type: Array,
      default: function () {
        return []
      }
    },
    buttonCol: {
      type: Number,
      default: function () {
        return 8
      }
    },
    clearable: {
      type: Boolean,
      default: function () {
        return true
      }
    },
    searchText: {
      type: String,
      default: function () {
        return '搜索'
      }
    },
    resetText: {
      type: String,
      default: function () {
        return '重置'
      }
    },
    size: {
      type: String,
      default: function () {
        return 'mini'
      }
    }
  },
  data() {
    return {
      filterData: this.initData(this.filters)
    };
  },

  watch: {
    filters: {
      deep: true,
      handler(val) {
        this.filterData = this.initData(val)
        this.getSelectOptions();
      }
    }
  },

  computed: {
    isShowCustomView() {
      return function (viewIndex) {
        let show = false
        let slotView = this.$slots.front || this.$slots.back
        if (slotView && slotView.length > 0) {
          const { index } = slotView[0].data.attrs
          if (viewIndex == index) {
            show = true
          }
        }
        return show
      }
    }
  },

  mounted() {
    this.getSelectOptions();
  },

  methods: {
    getSelectOptions() {
      this.filters.forEach(async item => {
        if (item.type === 'select') {
          let options = item.options || [];
          if (item.optionApi && typeof (item.optionApi) == 'function') {
            const data = await item.optionApi(item.queryParams);
            if (data) {
              options = data.rows
            }
          }
          this.filterData[item.fieldName + 'Options'] = options
        }
      });
    },

    initData(filters) {
      const filterData = {};
      if (filters) {
        filters.forEach(item => {
          if (item.type === 'select') {
            filterData[item.fieldName + 'Options'] = item.options || [];
            filterData[item.fieldName] = item.defaultValue ? item.defaultValue : undefined;
          } else if (item.type === 'numberRange' || item.type === 'timePickerRange') {
            filterData[item.fieldName] = item.defaultValue ? item.defaultValue : [];
          } else {
            filterData[item.fieldName] = item.defaultValue ? item.defaultValue : undefined;
          }
        });
      }
      return filterData;
    },

    clear() {
      Object.keys(this.filterData).forEach(key => {
        if (key.indexOf('Options') >= 0 && (this.filterData[key] instanceof Array)) {
          return true
        } else if (this.filterData[key] instanceof Array) {
          this.filterData[key] = [];
        } else {
          this.filterData[key] = undefined;
        }
      });
      if (this.$refs['cascader'] && this.$refs['cascader'][0]) {
        this.$refs['cascader'][0].clearSelection();
      }
    },

    handleReset() {
      this.clear();
      this.$emit('onReset');
    },

    getPrivateFilterData() {
      const filtersParams = {};
      for (let i = 0;i < this.filters.length;i++) {
        const item = this.filters[i];
        const filterValue = this.filterData[item.fieldName];
        if (item.type === 'timePickerRange') {
          if (!_.isEmpty(filterValue)) {
            filtersParams[item.fieldName] = [
              filterValue[0],
              filterValue[1],
            ]
          }
          continue;
        }
        filtersParams[item.fieldName] = (!filterValue || filterValue !== null) && filterValue !== '' ? filterValue : undefined;
      }
      return filtersParams;
    },

    getFilterData() {
      const filtersParams = {};
      for (let i = 0;i < this.filters.length;i++) {
        const item = this.filters[i];
        const filterValue = this.filterData[item.fieldName];
        filtersParams[item.fieldName] = filterValue;
      }
      return filtersParams;
    },

    handleFilter() {
      const filterData = this.getPrivateFilterData();
      if (!_.isEmpty(filterData)) {
        this.$emit('onFilter', filterData);
      }else{
        this.$emit('onAllFilter');
      }
    },

    handleCascaderChange(selection, item) {
      if (selection && item) {
        if (selection.length > 0) {
          this.$set(this.filterData, item.fieldName, selection)
        } else {
          this.$set(this.filterData, item.fieldName, undefined)
        }
      }
    },

    itemChange(val, item) {
      let param = {
        value: val,
        ...item
      }
      this.$emit('itemChange', param);
    }
  }
}
</script>

<style lang='scss' scoped>
  .filter-base-bar {
    .filter-full-width{
      width: 100%;
    }
    
    .number-range-container {
      display: flex;
      align-items: center;
      span {
        margin: 0 5px;
      }
    }

    .button-box{
      float: right;
      text-align: right;
    }

  }
</style>
