index.vue 3.81 KB
<template>
  <z-schema-form ref="form" class="z-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>
  </z-schema-form>
</template>

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

export default {
  name: 'SchemaFilter',
  mixins: [MIX_FORM],
  props: {
    value: Object,
    schema: {
      type: Object,
      default() {
        return {};
      },
    },
    size: String,
    loading: Boolean,
    display: {
      type: Number,
      default: 3,
    },
    span: {
      type: Number,
      default: 6,
    },
    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: {
    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 || 'small', ...(this.schema.props || {}) },
        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>