index.vue 13.7 KB
<style>
.eagle-scheme {
  padding: 0px;
}
.eagle-scheme__card {
  border: 1px solid #F5F5F5;
  border-radius: 2px;
  background-color: #fff;
  padding: 10px;
  transition: all .3s ease;
  margin-bottom: 10px;
}
.eagle-scheme__card  .eagle-search {
  padding-top: 20px;
  padding-bottom: 10px;
}
.eagle-scheme__action {
  display: flex;
  align-items: center;
  padding-bottom: 10px;
}
.eagle-scheme__action .eagle-scheme__action-btn:not(:first-child) {
  margin-left: 10px;
}
.eagle-scheme__text-selection {
  font-size: 14px;
}
.eagle-scheme__text-selection-highlight {
  color: #f5222d;
  padding: 0 5px;
}
.eagle-scheme__table .eagle-scheme__table-operation {
  display: flex;
  align-items: center;
}
.eagle-scheme__table .eagle-scheme__table-btn:not(:first-child) {
  padding-left: 10px;
  margin-left: 0px;
}
.eagle-scheme__pagination {
  text-align: right;
  padding-top: 10px;
}
.eagle-scheme__dialog .el-dialog__body {
  padding: 30px 40px;
}
</style>

<template>
  <div class="eagle-scheme">
    <div v-if="!option.showSearch" class="eagle-scheme__card">
      <!-- 搜索表单 -->
      <eagle-search :list="_searchList" v-model="searchModel" @search="handleSearch" :searching="tableLoading">
        <!-- 搜索表单项具名插槽 -->
        <template v-for="item in _searchList">
          <slot v-if="$scopedSlots[`search-${item.key}`] || $slots[`search-${item.key}`]" :name="`search-${item.key}`" :slot="item.key" :model="searchModel"></slot>
        </template>
      </eagle-search>
    </div>
    <!-- 操作按钮栏 -->
    <div v-if="!option.showActionBar" class="eagle-scheme__action" v-loading="tableLoading" element-loading-spinner="none" element-loading-background="rgba(255, 255, 255, 0.6)">
      <el-button class="eagle-scheme__action-btn" type="primary" size="small" @click="handleNew">新增</el-button>
      <el-button v-if="hasSelectionSlot" class="eagle-scheme__action-btn" plain size="small" @click="handleDelete('more')">删除</el-button>
      <div v-if="hasSelectionSlot && tableSelection && tableSelection.length > 0" class="eagle-scheme__action-btn eagle-scheme__text-selection">已选中<span class="eagle-scheme__text-selection-highlight">{{ tableSelection.length }}</span>项</div>
    </div>
    <div class="eagle-scheme__table">
      <!-- 表格 -->
      <eagle-table ref="eagle-table" :list="_tableList" :value="tableData"
        v-loading="tableLoading"
        element-loading-background="rgba(255, 255, 255, 0.6)"
        :tableProps="{ size: 'small', border: true, 'row-key': 'id', ...tableProps }"
        :tableEvents="{
          'selection-change': handleTableSelectionChange,
          ...tableEvents,
        }"
      >
        <slot></slot>
        <!-- 表格具名插槽 -->
        <template v-for="item in _tableList">
          <slot v-if="$scopedSlots[`table-${item.key}`] || $slots[`table-${item.key}`]" :name="`table-${item.key}`" :slot="item.key" :setDialog="setDialog"></slot>
        </template>
        <!-- 表格后置插槽 -->
        <template v-if="$scopedSlots['table-append'] || $slots['table-append']">
          <slot name="table-append" slot="$append"></slot>
        </template>
        <!-- 表格操作栏插槽 - 自定义 -->
        <template v-if="$scopedSlots['table-operation'] || $slots['table-operation']">
          <slot name="table-operation" slot="$end"></slot>
        </template>
        <!-- 表格操作栏插槽 - 默认 -->
        <el-table-column v-else slot="$end" prop="$operation" label="操作" min-width="140" fixed="right">
          <div class="eagle-scheme__table-operation" slot-scope="slotScope">
            <!-- 表格操作栏插槽 - 前置插槽 -->
            <slot v-if="$scopedSlots['table-operation-btn'] || $slots['table-operation-btn']" name="table-operation-btn"></slot>
            <el-button class="eagle-scheme__table-btn" type="text" icon="el-icon-view" title="查看" @click="handleView(slotScope)"></el-button>
            <el-button class="eagle-scheme__table-btn" type="text" icon="el-icon-edit" title="编辑" @click="handleEdit(slotScope)"></el-button>
            <eagle-confirm class="eagle-scheme__table-btn" title="是否删除?" @confirm="handleDelete('one', slotScope)">
              <el-button type="text" icon="el-icon-delete" title="删除"></el-button>
            </eagle-confirm>
            <!-- 表格操作栏插槽 - 后置插槽 -->
            <slot v-if="$scopedSlots['table-operation-btn-append'] || $slots['table-operation-btn-append']" name="table-operation-btn-append"></slot>
          </div>
        </el-table-column>
      </eagle-table>
      <!-- 分页器 -->
      <div v-if="!option.showPagination" class="eagle-scheme__pagination">
        <el-pagination size="small" @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" v-loading="tableLoading" element-loading-spinner="none" element-loading-background="rgba(255, 255, 255, 0.6)"
          :page-size="pageSize" :total="totalCount" v-bind="{ 'page-sizes': [10, 20, 50], layout: 'total, sizes, prev, pager, next, jumper', ...paginationProps }"></el-pagination>
      </div>
    </div>
    <el-dialog :custom-class="dialogProps['custom-class'] || 'eagle-scheme__dialog'" :title="dialogProps.title || dialogTitle" :visible.sync="dialogVisible" v-bind="{ width: '65%', ...dialogProps }">
      <eagle-form v-if="dialogType === 'dialog-form' && !$scopedSlots['dialog-form'] && !$slots['dialog-form']" :list="_formList" v-model="formModel" :span="formProps.span || 12" :formProps="{ size: 'small', 'label-width': '90px', ...formProps }" @submit="handleSubmit" @cancel="handleCancel">
        <!-- 表单分组具名插槽 -->
        <template v-for="key in formGroupSlotsKeys">
          <slot v-if="$scopedSlots[`form-${key}`] || $slots[`form-${key}`]" :name="`form-${key}`" :slot="key" :model="formModel"></slot>
        </template>
        <!-- 表单项具名插槽 -->
        <template v-for="item in _formList">
          <slot v-if="$scopedSlots[`form-item-${item.key}`] || $slots[`form-item-${item.key}`]" :name="`form-item-${item.key}`" :slot="`item-${item.key}`" :model="formModel"></slot>
        </template>
      </eagle-form>
      <eagle-detail v-else-if="dialogType === 'dialog-view' && !$scopedSlots['dialog-view'] && !$slots['dialog-view']" v-model="formModel" :list="_formList">
        <!-- 表单分组具名插槽 -->
        <template v-for="key in formGroupSlotsKeys">
          <slot v-if="$scopedSlots[`view-${key}`] || $slots[`view-${key}`]" :name="`view-${key}`" :slot="key" :model="formModel"></slot>
        </template>
        <!-- 表单项具名插槽 -->
        <template v-for="item in _formList">
          <slot v-if="$scopedSlots[`view-item-${item.key}`] || $slots[`view-item-${item.key}`]" :name="`view-item-${item.key}`" :slot="`item-${item.key}`" :model="formModel"></slot>
        </template>
      </eagle-detail>
      <!-- 自定义弹出框内容插槽 -->
      <slot v-else :name="dialogType" :row="tableCurrentRow"></slot>
    </el-dialog>
  </div>
</template>

<script>
import { generateListSpace } from './parser';

export default {
  name: 'Scheme',
  props: {
    // 配置列表
    list: Array,
    // 配置选项
    option: {
      type: Object,
      default() { return {} }
    },
    // 搜索表单配置
    searchList: Array,
    // 表单配置
    formList: Array,
    // 表格配置
    tableList: Array,
    // 表格参数
    tableProps: {
      type: Object,
      default() { return {} }
    },
    // 表格事件
    tableEvents: {
      type: Object,
      default() { return {} }
    },
    // 表单参数
    formProps: {
      type: Object,
      default() { return {} }
    },
    // 分页参数
    paginationProps: {
      type: Object,
      default() { return {} }
    },
    // 弹出框参数
    dialogProps: {
      type: Object,
      default() { return {} }
    }
  },
  data() {
    return {
      // 搜索表单配置
      _searchList: [],
      // 搜索表单值
      searchModel: {},
      // 表单配置
      _formList: [],
      // 表单值
      formModel: {},
      // 表格配置
      _tableList: [],
      // 当前页
      currentPage: 1,
      // 每页最大数据量
      pageSize: 10,
      // 数据总量
      totalCount: 0,
      // 弹出框状态
      dialogVisible: false,
      // 弹出框标题
      dialogTitle: '',
      // 弹出框类型
      dialogType: '',
      // 表格数据
      tableData: [
        { name: '赵伯', code: 'U00001', type: 'admin', sort: 0, status: 'active' },
        { name: '钱仲', code: 'U00002', type: 'user', sort: 1, status: 'active' },
        { name: '孙叔', code: 'U00003', type: 'user', sort: 2, status: 'active' },
        { name: '李季', code: 'U00004', type: 'user', sort: 3, status: 'active' },
        { name: '赵伯', code: 'U00001', type: 'admin', sort: 0, status: '' },
        { name: '钱仲', code: 'U00002', type: 'user', sort: 1, status: 'active' },
        { name: '孙叔', code: 'U00003', type: 'user', sort: 2, status: '' },
        { name: '李季', code: 'U00004', type: 'user', sort: 3, status: 'active' },
        { name: '赵伯', code: 'U00001', type: 'admin', sort: 0, status: 'active' },
        { name: '钱仲', code: 'U00002', type: 'user', sort: 1, status: 'active' },
        { name: '孙叔', code: 'U00003', type: 'user', sort: 2, status: '' },
        { name: '李季', code: 'U00004', type: 'user', sort: 3, status: '' },
        { name: '赵伯', code: 'U00001', type: 'admin', sort: 0, status: 'active' },
        { name: '钱仲', code: 'U00002', type: 'user', sort: 1, status: '' },
        { name: '孙叔', code: 'U00003', type: 'user', sort: 2, status: '' },
        { name: '李季', code: 'U00004', type: 'user', sort: 3, status: '' },
      ],
      // 表格选中项
      tableSelection: [],
      // 表格加载状态
      tableLoading: false,
      // 表格当前操作列
      tableCurrentRow: null,
    };
  },
  created() {
    if (this.list instanceof Array) { // 如果有总配置列表,则根据总配置列表生成作用域数据
      const { search = [], form = [], table = [] } = generateListSpace(this.list);
      this._searchList = search;
      this._formList = form;
      this._tableList = table;
    } else { // 没有总配置列表时,单独传入作用域列表
      this._searchList = this.searchList || [];
      this._formList = this.formList || [];
      this._tableList = this.tableList || [];
    }
    this.totalCount = this.tableData.length;
  },
  mounted() {
    this.$axios.get('http://47.110.137.80:7102/article/categoryCode')
      .then((response) => {
        // handle success
        console.log(response);
      });
  },
  computed: {
    // 解析表单组件分组具名插槽名称
    formGroupSlotsKeys() {
      const keys = [...new Set([...Object.keys(this.$scopedSlots), ...Object.keys(this.$slots)])];
      return keys.filter(key => key.indexOf('form-group') > -1).map(key => key.substr(5));
    },
    // 判断设置全选插槽
    hasSelectionSlot() {
      const slots = this.$slots || {};
      const defaultSlot = slots.default || [];
      let result = false;
      for (let slot of defaultSlot) {
        if (slot.componentOptions && slot.componentOptions.tag === 'el-table-column' && slot.componentOptions.propsData && slot.componentOptions.propsData.type === 'selection') {
          result = true;
          break;
        }
      }
      return result;
    }
  },
  methods: {
    // 查询数据
    handleSearch(param) {
      this.tableLoading = true;
      setTimeout(() => {
        this.tableLoading = false;
        console.log({
          param,
          searchModel: this.searchModel,
          currentPage: this.currentPage,
          pageSize: this.pageSize
        });
      }, 2000);
    },
    // 查看按钮
    handleView({ row }) {
      this.dialogTitle = '详情';
      this.dialogType = 'dialog-view';
      this.tableCurrentRow = row;
      this.formModel = {};
      // 设置表单值
      Object.keys(row).forEach(key => {
        this.formModel[key] = row[key];
      });
      this.showDialog();
    },
    // 新增按钮
    handleNew({ row }) {
      this.dialogTitle = '新增';
      this.dialogType = 'dialog-form';
      this.tableCurrentRow = row;
      this.formModel = {};
      this.showDialog();
    },
    // 编辑按钮
    handleEdit({ row }) {
      this.dialogTitle = '编辑';
      this.dialogType = 'dialog-form';
      this.tableCurrentRow = row;
      this.formModel = {};
      // 设置表单值
      Object.keys(row).forEach(key => {
        this.formModel[key] = row[key];
      });
      this.showDialog();
    },
    // 删除按钮
    handleDelete(type, scope) {
      if (type === 'one') {
        console.log(type, [scope.row]);
      } else if (type === 'more') {
        console.log(type, this.tableSelection);
      }
    },
    // 改变每页总数大小
    handleSizeChange(val) {
      this.currentPage = 1;
      this.pageSize = val;
      this.handleSearch();
    },
    // 改变当前页数
    handleCurrentChange(val) {
      this.currentPage = val;
      this.handleSearch();
    },
    // 表单提交
    handleSubmit(param) {
      console.log({ param });
    },
    // 表单取消
    handleCancel() {
      this.hideDialog();
    },
    // 表格选择
    handleTableSelectionChange(selection) {
      this.tableSelection = selection;
      console.log(selection);
    },
    // 显示弹出框
    showDialog() {
      this.dialogVisible = true;
    },
    // 隐藏弹出框
    hideDialog() {
      this.dialogVisible = false;
      this.tableSelection = [];
      this.tableLoading = false;
      this.tableCurrentRow = null;
      this.formModel = {};
      this.dialogTitle = '';
      this.dialogType = '';
    },
    // 设置弹出框模式
    setDialog({ title, type }) {
      this.dialogTitle = title;
      this.dialogType = type;
      this.dialogVisible = true;
    }
  }
};
</script>