/**
* Description: 数据列表过滤器 返回过滤条件
*/

<template>
  <div class="list-filter-bar">
    <el-form :label-width="labelWidth">
      <el-row :gutter="20">
        <template v-for="(item, index) in filters">
          <slot
            name="front"
            v-if="$slots.front && isShowCustomView(index)"
          ></slot>

          <el-col
            :span="itemSpan(item)"
            :key="index"
          >
            <el-form-item :label="item.label" :label-width="item.labelWidth">
              <el-date-picker
                v-if="item.type === 'timePickerRange'"
                class="time-picker-item"
                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="(value) => handleChange(value, item)"
              >
              </el-date-picker>
              <el-input
                class="input"
                v-else-if="item.type === 'input'"
                :placeholder="item.placeholder"
                :size="size"
                v-model="filterData[item.fieldName]"
                :clearable="item.clearable"
                @change="(value) => handleChange(value, item)"
              />
              <el-input-number
                :size="size"
                v-else-if="item.type === 'inputNumber'"
                :placeholder="item.placeholder"
                v-model="filterData[item.fieldName]"
                @change="(value) => handleChange(value, item)"
              />

              <el-select
                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"
                :collapse-tags="item.collapse"
                @change="(value) => handleChange(value, item)"
              >
                <template v-for="(option, i) in filterData[item.fieldName + 'Options']">
                  <el-option
                    v-if="option"
                    :key="i"
                    :label="item.labelKey ? option[item.labelKey] : option.name"
                    :value="item.valueKey ? option[item.valueKey] : option.value"
                  >
                  </el-option>
                </template>

              </el-select>

              <section
                v-else-if="item.type === 'numberRange'"
                class="number-range-container"
              >
                <el-input-number
                  :placeholder="item.startPlaceholder"
                  v-model="filterData[item.fieldName][0]"
                  :size="size"
                  @change="(value) => handleChange(value, item)"
                />
                <span class="normal-text range-separator">{{item.rangeSeparator || '至'}}</span>
                <el-input-number
                  :placeholder="item.endPlaceholder"
                  v-model="filterData[item.fieldName][1]"
                  :size="size"
                  @change="(value) => handleChange(value, 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"
                :collapse-tags="item.collapse"
                :cascaderData="item.cascaderData"
                :checkStrictly="item.checkStrictly"
                :cascaderValue="filterData[item.fieldName]"
                :placeholder="item.placeholder"
                :nodeFieldName="item.nodeFieldName"
                :nodeValueFieldName="item.nodeValueFieldName"
                :dataKeyFieldName="item.dataKeyFieldName"
                @onChange="(selection) => handleCascaderChange(selection, item)"
              />

              <slot :name="item.fieldName" v-else-if="item.type === 'template'"></slot>

            </el-form-item>
          </el-col>
          <slot
            name="back"
            v-if="$slots.back && isShowCustomView(index)"
          ></slot>
        </template>
        <el-col
          :span="buttonCol"
          style="text-align: right; min-height:30px;"
        >
          <slot
            name="otherbutton"
            v-if="$slots.otherbutton"
          ></slot>
          <slot
            name="buttonFirst"
            v-if="$slots.buttonFirst"
          ></slot>
          <el-button
            :size="size"
            type="primary"
            @click="handleFilter"
          >{{searchText}}</el-button>
          <el-button
            v-if="clearable"
            :size="size"
            @click="handleReset"
          >{{resetText}}</el-button>
          <slot
            name="buttonLast"
            v-if="$slots.buttonLast"
          ></slot>
        </el-col>
      </el-row>
    </el-form>
  </div>
</template>

<script>
import Cascader from '../cascader/Cascader.vue';
import _ from 'loadsh';
export default {
  name: "ListFilterBar",
  components: { Cascader },
  props: {
    filters: {
      type: Array,
      default: function () {
        return []
      }
    },
    clearable: {
      type: Boolean,
      default: function () {
        return true
      }
    },
    labelWidth: {
      type: String,
      default: function () {
        return 'auto'
      }
    },
    searchText: {
      type: String,
      default: function () {
        return '搜索'
      }
    },
    resetText: {
      type: String,
      default: function () {
        return '重置'
      }
    },
    size: {
      type: String,
      default: function () {
        return 'small'
      }
    },
    buttonCol: {
      type: Number,
      default: function () {
        return 24
      }
    },
  },
  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: {
    itemSpan(item) {
      let span = 8;
      if (item.span) {
        span = Number(item.span)
      }
      return span
    },
    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);
      }
    },

    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)
        }
      }
      this.handleChange(selection, item)
    },

    handleChange(value, item){
      this.$emit('onChange', item.fieldName);
    }
  }
}
</script>

<style lang='scss' scoped>
.list-filter-bar{
  ::v-deep .el-col {
    min-height: 52px;
  }
  ::v-deep .el-form-item{
    margin-bottom: 12px;
    .number-range-container{
      display: flex;
      align-items: center;
      justify-content: space-between;
      .range-separator{
        margin: 0px 4px;
      }
    }
  }
  // 日期区间组件，宽度保持与其他输入框一致
  ::v-deep .el-date-editor--daterange.el-input__inner{
      width: 100%;
    }
  
}
</style>