index.vue 4.3 KB
<template>
  <eagle-schema-form ref="form" class="eagle-schema-filter" v-model="model" :schema="formattedSchema">
    <template v-for="key in slotKeys">
      <slot :name="key" :slot="key" v-bind="slotProps"></slot>
    </template>
    <el-button-group v-if="!slotKeys.includes('operation')" slot="operation" style="display: flex; justify-content: flex-end">
      <el-button type="primary" @click="onSearch" :loading="loading" icon="el-icon-search">查询</el-button>
      <el-button @click="onReset">重置</el-button>
      <el-button v-if="showCollapsed" @click="onCollapse">{{ collapsed ? '收起' : '展开' }}</el-button>
    </el-button-group>
  </eagle-schema-form>
</template>

<script>
import MIX_FORM from '../mixins/form';
import { cloneDeep, get } from '../utils';

export default {
  name: 'SchemaFilter',
  mixins: [MIX_FORM],
  props: {
    value: Object,
    schema: {
      required: true,
      type: Object,
      default() {
        return {};
      },
    },
    size: String,
    loading: Boolean,
    display: Number,
    span: Number,
    collapsedSpan: Number,
    uncollapsedSpan: Number,
  },
  data() {
    return {
      collapsed: false,
      model: this.value,
      originData: {},
    };
  },
  watch: {
    value(val = {}) {
      this.model = val;
    },
    model(val) {
      this.$emit('input', val);
    },
  },
  computed: {
    _display() {
      return this.display || get(this.schema, 'props.display') || 3;
    },
    _span() {
      return this.span || get(this.schema, 'props.span') || 6;
    },
    _collapsedSpan() {
      return this.collapsedSpan || get(this.schema, 'props.collapsedSpan');
    },
    _uncollapsedSpan() {
      return this.uncollapsedSpan || get(this.schema, 'props.uncollapsedSpan');
    },
    _schemaProps() {
      const { display, collapsedSpan, uncollapsedSpan, loading, ...other } = this.schema.props || {};
      return other;
    },
    filterSize() {
      return this.size || (this.$ELEMENT || {}).size;
    },
    formattedItems() {
      const items = this.schema.items || [];
      const result = [];
      const visibleNumber = this._display - 1;
      items.forEach((item, index) => {
        if (!this.collapsed && index > visibleNumber && index < items.length) {
          result.push({ ...item, if: true, show: false });
        } else {
          result.push({ ...item, if: true, show: true });
        }
      });
      return result;
    },
    formattedSchema() {
      return {
        props: { span: this._span, 'label-width': '75px', size: this.filterSize, ...this._schemaProps },
        items: [...this.formattedItems, { prop: 'operation', label: '', labelWidth: '0px', span: this.operationSpan }],
      };
    },
    rowItemCount() {
      return parseInt(24 / this._span);
    },
    rowItemRemain() {
      return this.formattedItems.length % this.rowItemCount;
    },
    operationSpan() {
      if (this.collapsed) {
        if (this._collapsedSpan) {
          return this._collapsedSpan;
        }
        return (this.rowItemCount - this.rowItemRemain) * this._span;
      } else {
        if (this._uncollapsedSpan) {
          return this._uncollapsedSpan;
        }
        if (this.formattedItems.length < this._display) {
          return this._span * (this.rowItemCount - this.rowItemRemain);
        }
        if (this._display < this.rowItemCount - 1) {
          return this._span * this._display;
        }
        return this._span;
      }
    },
    showCollapsed() {
      return this.formattedItems.length > this._display;
    },
    slotKeys() {
      return Object.keys(this.$scopedSlots);
    },
    slotProps() {
      return {
        size: this.size,
        search: this.onSearch,
        reset: this.onReset,
        collapse: this.onCollapse,
        collapsed: this.collapsed,
        loading: this.loading,
      };
    },
  },
  created() {
    const { originData, ...other } = this._data;
    this.originData = cloneDeep(other);
  },
  methods: {
    // 搜索
    onSearch() {
      this.$refs.form.validate(valid => {
        if (valid) {
          this.$emit('search', this.model);
        }
      });
    },
    // 重置
    onReset() {
      this.model = cloneDeep(this.originData).model;
      this.$refs.form.resetFields();
      this.$emit('reset');
    },
    // 折叠
    onCollapse() {
      this.collapsed = !this.collapsed;
    },
  },
};
</script>