| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706 |
- <template>
- <div :class="b()">
- <el-card :class="b('box')">
- <div slot="header"
- :class="b('title')"
- v-if="vaildData(tableOption.title,false) || vaildData(tableOption.dateBtn,config.dateBtn)">
- <span>{{tableOption.title}}</span>
- <date-select @change="dateChange"
- v-if="vaildData(tableOption.dateBtn,config.dateBtn)"
- :default="vaildData(tableOption.dateDefault,config.dateDefault)"
- :size="vaildData(tableOption.dateSize,config.dateBtnSize)">
- </date-select>
- </div>
- <div :class="b('header')">
- <el-collapse-transition>
- <el-form :model="searchForm"
- :inline="true"
- ref="searchForm"
- v-if="searchShow && searchFlag">
- <!-- 循环列搜索框 -->
- <el-form-item :prop="column.prop"
- :label="column.label"
- v-for="(column,index) in columnOption"
- :key="index"
- v-if="column.search">
- <component :size="vaildData(tableOption.searchSize,config.searchComponentSize)"
- :is="getSearchType(column.type)"
- v-model="searchForm[column.prop]"
- :type="getType(column)"
- :props="column.props || tableOption.props"
- :format="column.format"
- :filterable="column.searchFilterable"
- :filter-method="column.searchFilterMethod"
- :value-format="column.valueFormat"
- :multiple="config.searchMultiple.includes(column.type) && vaildData(column.searchMmultiple,false)"
- clearable
- :placeholder="column.label"
- :dic="setDic(column.dicData,DIC[column.dicData])"></component>
- </el-form-item>
- <slot name="search"></slot>
- <el-form-item>
- <el-button type="primary"
- @click="searchChange"
- :icon="config.searchBtnIcon"
- :size="vaildData(tableOption.searchSize,config.searchBtnSize)">{{config.searchBtnTitle}}</el-button>
- <el-button @click="searchReset"
- :icon="config.emptyBtnIcon"
- :size="vaildData(tableOption.searchSize,config.emptyBtnSize)">{{config.emptyBtnTitle}}</el-button>
- <slot name="searchMenu"></slot>
- </el-form-item>
- </el-form>
- </el-collapse-transition>
- </div>
- <!-- 表格功能列 -->
- <div :class="b('menu')">
- <div :class="b('left')">
- <el-button type="primary"
- @click="rowAdd"
- :icon="config.addBtnIcon"
- :size="config.addBtnSize"
- v-if="vaildData(tableOption.addBtn,config.addBtn)">{{config.addBtnTitle}}</el-button>
- <slot name="menuLeft"></slot>
- </div>
- <div :class="b('right')">
- <slot name="menuRight"></slot>
- <el-button :icon="config.refreshBtnIcon"
- circle
- :size="config.refreshBtnSize"
- @click="refreshChange"
- v-if="vaildData(tableOption.refreshBtn,config.refreshBtn)"></el-button>
- <el-button :icon="config.columnBtnIcon"
- circle
- :size="config.columnBtnSize"
- @click="columnBox=true"
- v-if="vaildData(tableOption.columnBtn,config.columnBtn)"></el-button>
- <el-button :icon="config.searchboxBtnIcon"
- circle
- :size="config.searchboxBtnSize"
- @click="searchShow=!searchShow"
- v-if="searchFlag && vaildData(tableOption.searchBtn,config.searchBtn)"></el-button>
- </div>
- </div>
- <el-tag class="avue-tip"
- v-if="vaildData(tableOption.tip,config.tip) && tableOption.selection">
- <i class="el-icon-info avue-tip__icon"> </i>
- <span class="avue-tip__name">
- {{config.tipStartTitle}}
- <span class="avue-tip__name--bold">{{selectLen}}</span> {{config.tipEndTitle}}
- </span>
- <span class="avue-tip__btn"
- @click="selectClear"
- v-if="vaildData(tableOption.selectClearBtn,config.selectClearBtn) && tableOption.selection">
- {{config.tipBtnTitle}}
- </span>
- </el-tag>
- <el-table :data="list"
- :highlight-current-row="tableOption.highlightCurrentRow"
- @current-change="currentRowChange"
- :stripe="tableOption.stripe"
- :show-header="tableOption.showHeader"
- :default-sort="tableOption.defaultSort"
- @row-click="rowClick"
- @row-dblclick="rowDblclick"
- :row-class-name="rowClassName"
- :max-height="tableOption.maxHeight"
- :height="tableOption.height=='auto'?(clientHeight - vaildData(tableOption.calcHeight,config.calcHeight)):tableOption.height"
- ref="table"
- :width="setPx(tableOption.width,config.width)"
- :border="tableOption.border"
- v-loading="tableLoading"
- @selection-change="selectionChange"
- @sort-change="sortChange">
- <!-- 折叠面板 -->
- <el-table-column type="expand"
- width="50"
- fixed="left"
- align="center"
- v-if="tableOption.expand">
- <template slot-scope="props">
- <slot :row="props.row"
- name="expand"></slot>
- </template>
- </el-table-column>
- <!-- 选择框 -->
- <el-table-column v-if="tableOption.selection"
- type="selection"
- width="50"
- fixed="left"
- align="center">
- </el-table-column>
- <!-- 序号 -->
- <el-table-column v-if="tableOption.index"
- :label="vaildData(tableOption.indexLabel,config.indexLabel)"
- type="index"
- width="50"
- :index="indexMethod"
- fixed="left"
- align="center">
- </el-table-column>
- <!-- 循环列 -->
- <el-table-column v-if="columnIndex.indexOf(column.prop)!=-1"
- v-for="(column,index) in columnOption"
- :prop="column.prop"
- :key="index"
- filter-placement="bottom-end"
- :filters="column.filters"
- :filter-method="column.filterMethod"
- :filter-multiple="vaildData(column.filterMultiple,config.filterMultiple)"
- :show-overflow-tooltip="column.overHidden"
- :min-width="column.minWidth"
- :sortable="column.sortable"
- :align="vaildData(column.align,tableOption.align)"
- :header-align="vaildData(column.headerAlign,tableOption.headerAlign)"
- :width="column.width"
- :label="column.label"
- :fixed="column.fixed">
- <crud-components v-if="column.children"
- :columnOption="column.children"
- :tableOption="tableOption"
- :tableForm="tableForm"
- :columnIndex="columnIndex"
- :DIC="DIC">
- <template slot-scope="scope"
- v-for="item in column.children"
- :slot="item.prop">
- <slot :row="scope.row"
- :dic="scope.dic"
- :label="scope.label"
- :name="item.prop"
- v-if="item.solt"></slot>
- </template>
- </crud-components>
- <template slot-scope="scope">
- <template v-if="cellEditFlag(scope.row,column)">
- <component size="small"
- :is="getSearchType(column.type)"
- v-model="tableForm[column.prop]"
- :type="getType(column)"
- clearable
- :placeholder="column.label"
- :dic="setDic(column.dicData,DIC[column.dicData])"></component>
- </template>
- <slot :row="scope.row"
- :dic="setDic(column.dicData,DIC[column.dicData])"
- :label="detail(scope.row,column)"
- :name="column.prop"
- v-else-if="column.solt"></slot>
- <template v-else>
- <span v-html="detail(scope.row,column)"></span>
- </template>
- </template>
- </el-table-column>
- <el-table-column fixed="right"
- v-if="vaildData(tableOption.menu,config.menu)"
- :label="config.menuTitle"
- :align="tableOption.menuAlign"
- :header-align="tableOption.menuHeaderAlign"
- :width="vaildData(tableOption.menuWidth,config.menuWidth)">
- <template slot-scope="scope">
- <el-dropdown split-button
- icon="el-icon-menu"
- type="primary"
- v-if="vaildData(tableOption.menuBtn,config.menuBtn)"
- :size="config.menuBtnSize">
- {{config.menuBtnTitle}}
- <el-dropdown-menu slot="dropdown">
- <el-dropdown-item v-if="vaildData(tableOption.viewBtn,true)"
- @click.native="rowView(scope.row,scope.$index)">{{config.viewBtnTitle}}</el-dropdown-item>
- <el-dropdown-item divided
- v-if="vaildData(tableOption.editBtn,true)"
- @click.native="rowEdit(scope.row,scope.$index)">{{config.editBtnTitle}}</el-dropdown-item>
- <el-dropdown-item divided
- v-if="vaildData(tableOption.delBtn,true)"
- @click.native="rowDel(scope.row,scope.$index)">{{config.delBtnTitle}}</el-dropdown-item>
- <slot name="dropMenu"
- :row="scope.row"
- :dic="scope.dic"
- :label="scope.label"
- :index="scope.$index"></slot>
- </el-dropdown-menu>
- </el-dropdown>
- <el-button type="primary"
- :icon="scope.row.$cellEdit?config.cellSaveBtnIcon:config.cellEditBtnIcon"
- :size="config.cellBtnSize"
- @click.stop="rowCell(scope.row,scope.$index)"
- v-if="vaildData(tableOption.cellBtn ,config.cellBtn)">{{scope.row.$cellEdit?config.cellSaveBtnTitle:config.cellEditBtnTitle}}</el-button>
- <el-button type="success"
- :icon="config.viewBtnIcon"
- :size="config.viewBtnSize"
- @click.stop="rowView(scope.row,scope.$index)"
- v-if="vaildData(tableOption.viewBtn,tableOption.menuBtn?false:config.viewBtn)">{{config.viewBtnTitle}}</el-button>
- <el-button type="primary"
- :icon="config.editBtnIcon"
- :size="config.editBtnSize"
- @click.stop="rowEdit(scope.row,scope.$index)"
- v-if="vaildData(tableOption.editBtn,tableOption.menuBtn?false:config.editBtn)">{{config.editBtnTitle}}</el-button>
- <el-button type="danger"
- :icon="config.delBtnIcon"
- :size="config.delBtnSize"
- @click.stop="rowDel(scope.row,scope.$index)"
- v-if="vaildData(tableOption.delBtn,tableOption.menuBtn?false:config.delBtn)">{{config.delBtnTitle}}</el-button>
- <slot name="menu"
- :row="scope.row"
- :dic="scope.dic"
- :label="scope.label"
- :index="scope.$index"></slot>
- </template>
- </el-table-column>
- </el-table>
- <!-- 分页 -->
- <div :class="b('pagination')"
- v-if="vaildData(tableOption.page,config.page) && listLen">
- <el-pagination :current-page.sync="page.currentPage"
- :background="vaildData(tableOption.pageBackground,config.pageBackground)"
- :page-size="page.pageSize"
- :page-sizes="page.pageSizes"
- @size-change="sizeChange"
- @current-change="currentChange"
- layout="total, sizes, prev, pager, next, jumper"
- :total="page.total"></el-pagination>
- </div>
- </el-card>
- <!-- 表单 -->
- <el-dialog lock-scroll
- :custom-class="vaildData(tableOption.customClass,config.customClass)"
- :fullscreen="vaildData(tableOption.formFullscreen,config.formFullscreen)"
- :modal-append-to-body="false"
- :append-to-body="true"
- :title="dialogTitle"
- :visible.sync="boxVisible"
- :width="vaildData(tableOption.formWidth,config.formWidth)"
- @close="hide">
- <div :class="b('dialog', ['overflow'])">
- <avue-form v-model="tableForm"
- ref="tableForm"
- :disabled="keyBtn"
- :uploadBefore="uploadBefore"
- :uploadAfter="uploadAfter"
- :option="formOption">
- <template slot-scope="scope"
- v-for="item in columnOption"
- :slot="item.prop">
- <slot :value="scope.value"
- :column="scope.column"
- :dic="scope.dic"
- :name="item.prop+'Form'"
- v-if="item.formsolt"></slot>
- </template>
- </avue-form>
- </div>
- <span slot="footer"
- class="dialog-footer">
- <slot name="menuForm"
- :row="tableForm"
- :type="boxType"></slot>
- <el-button type="primary"
- @click="rowUpdate"
- v-if="boxType=='edit'"
- :loading="keyBtn">{{config.updateBtnTitle}}</el-button>
- <el-button type="primary"
- @click="rowSave"
- :loading="keyBtn"
- v-else-if="boxType=='add'">{{config.saveBtnTitle}}</el-button>
- <el-button @click="closeDialog">{{config.cancelBtnTitle}}</el-button>
- </span>
- </el-dialog>
- <!-- 动态列 -->
- <el-dialog lock-scroll
- :modal-append-to-body="false"
- :append-to-body="true"
- :title="config.columnBtnTitle"
- :visible.sync="columnBox">
- <el-checkbox-group v-model="columnIndex">
- <el-row :span="24">
- <el-col :span="6"
- v-for="(item,index) in columnList"
- :key="index">
- <el-checkbox :label="item.prop">{{item.label}}</el-checkbox>
- </el-col>
- </el-row>
- </el-checkbox-group>
- </el-dialog>
- </div>
- </template>
- <script>
- import dateSelect from '../../date-select'
- import create from '../../utils/create';
- import crud from '../../mixins/crud.js';
- import column from '../../mixins/column.js';
- import crudComponents from './crud-components';
- import config from './config.js';
- import {
- validatenull
- } from '../../utils/validate.js';
- import {
- setTimeout
- } from 'timers';
- export default create({
- name: 'crud',
- mixins: [crud(), column()],
- components: {
- crudComponents,
- dateSelect
- },
- data () {
- return {
- clientHeight: document.documentElement.clientHeight,
- defaultForm: {
- tableForm: {},
- searchForm: {}
- },
- defaultParam: ['$index'],
- keyBtn: false,
- config: config,
- list: [],
- searchShow: true,
- searchForm: {},
- boxVisible: false,
- boxType: 'add',
- columnIndex: [],
- columnBox: false,
- columnList: [],
- tableForm: {},
- tableOption: {},
- tableFormRules: {},
- tableIndex: -1,
- tableSelect: []
- };
- },
- created () {
- // 初始化数据
- this.dataInit();
- // 初始化列
- this.columnInit();
- },
- computed: {
- dialogTitle () {
- const key = `${this.boxType}Title`;
- return this.tableOption[key] || this.config[key];
- },
- listLen () {
- return this.list.length !== 0
- },
- columnOption () {
- return this.tableOption.column || [];
- },
- selectLen () {
- return this.tableSelect ? this.tableSelect.length : 0;
- },
- searchSolt () {
- return this.vaildData(this.tableOption.searchsolt, false);
- },
- searchFlag () {
- if (this.searchSolt) return true;
- else return !validatenull(this.searchForm);
- },
- formOption () {
- let option = this.deepClone(this.tableOption);
- option.submitBtn = false;
- option.submitPostion = 'right';
- option.boxType = this.boxType;
- option.dicFlag = false;
- option.dicData = this.DIC;
- option.emptytBtn = false;
- return option;
- }
- },
- watch: {
- columnOption () {
- this.columnInit();
- },
- data () {
- this.dataInit();
- }
- },
- mounted () { },
- props: {
- value: {
- type: Object,
- default: () => {
- return {};
- }
- },
- beforeClose: Function,
- beforeOpen: Function,
- rowClassName: Function,
- uploadBefore: Function,
- uploadAfter: Function,
- page: {
- type: Object,
- default () {
- return {
- total: 0, // 总页数
- currentPage: 0, // 当前页数
- pageSize: 10, // 每页显示多少条
- pageSizes: [10, 20, 30, 40, 50, 100],
- background: true // 背景颜色
- };
- }
- },
- tableLoading: {
- type: Boolean,
- default: false
- },
- data: {
- type: Array,
- required: true,
- default: () => {
- return [];
- }
- }
- },
- methods: {
- closeDialog () {
- this.tableIndex = -1;
- this.tableForm = {};
- this.boxVisible = false;
- this.keyBtn = false;
- },
- selectClear () {
- this.$refs.table.clearSelection();
- },
- indexMethod (index) {
- return (index + 1) + (((this.page.currentPage || 1) - 1) * (this.page.pageSize || 10));
- },
- refreshChange () {
- this.$emit('refresh-change', {
- page: this.page,
- searchForm: this.searchForm
- });
- },
- rulesInit () {
- this.tableFormRules = {};
- this.columnOption.forEach(ele => {
- if (ele.rules) this.tableFormRules[ele.prop] = ele.rules;
- });
- },
- columnInit: function () {
- const safe = this;
- this.columnIndex = [];
- this.columnList = [];
- function addChild (list) {
- list.forEach((ele, index) => {
- const children = ele.children;
- if (!validatenull(children)) {
- safe.tableOption.columnBtn = false;
- addChild(children);
- }
- if (validatenull(ele.hide)) safe.columnIndex.push(ele.prop);
- if (ele.showClomnu !== false) {
- let obj = {
- label: ele.label,
- prop: ele.prop,
- index: index
- };
- safe.columnList.push(safe.deepClone(obj));
- }
- });
- }
- addChild(this.columnOption)
- },
- formVal () {
- Object.keys(this.value).forEach(ele => {
- this.tableForm[ele] = this.value[ele];
- })
- this.$emit('input', this.tableForm);
- },
- dataInit () {
- this.list = [].concat(this.data);
- //初始化序号
- this.list.forEach((ele, index) => {
- ele.$index = index;
- })
- },
- formInit () {
- this.defaultForm = this.formInitVal(this.columnOption);
- this.tableForm = this.deepClone(this.defaultForm.tableForm);
- this.searchForm = this.deepClone(this.defaultForm.searchForm);
- this.searchShow = this.vaildData(this.tableOption.searchShow, this.config.searchShow);
- this.formVal();
- },
- // 搜索清空
- searchReset () {
- this.$refs['searchForm'].resetFields();
- this.$emit('search-reset');
- },
- // 页大小回调
- sizeChange (val) {
- this.$emit('size-change', val);
- },
- //日期组件回调
- dateChange (val) {
- this.$emit('date-change', val);
- },
- // 页码回调
- currentChange (val) {
- this.$emit('current-change', val);
- },
- //设置单选
- currentRowChange (currentRow, oldCurrentRow) {
- this.$emit('current-row-change', currentRow, oldCurrentRow);
- },
- //设置多选选中
- setCurrentRow (row) {
- this.$refs.table.setCurrentRow(row);
- },
- // 选中实例
- toggleSelection (rows) {
- if (rows) {
- rows.forEach(row => {
- this.$refs.table.toggleRowSelection(row);
- });
- } else {
- this.$refs.table.clearSelection();
- }
- },
- // 选择回调
- selectionChange (val) {
- this.tableSelect = val;
- this.$emit('selection-change', this.tableSelect);
- },
- // 排序回调
- sortChange (val) {
- this.$emit('sort-change', val);
- },
- // 搜索回调
- searchChange () {
- this.$emit('search-change', this.searchForm);
- },
- // 行双击
- rowDblclick (row, event) {
- this.$emit('row-dblclick', row, event);
- },
- // 行单机
- rowClick (row, event, column) {
- this.$emit('row-click', row, event, column);
- },
- // 新增
- rowAdd () {
- this.boxType = 'add';
- this.tableForm = this.deepClone(this.defaultForm.tableForm);
- this.clearDefaultParam();
- this.$emit('input', this.tableForm);
- this.show();
- },
- rowCell (row, index) {
- if (row.$cellEdit) this.rowCellUpdate(row, index)
- else this.rowCellEdit(row, index)
- },
- // 单元格编辑
- rowCellEdit (row, index) {
- if (this.tableIndex != -1) {
- this.$message.error('先保存当前编辑的数据');
- return;
- }
- this.tableIndex = index;
- this.tableForm = this.deepClone(row);
- this.$emit('input', this.tableForm);
- row.$cellEdit = !row.$cellEdit;
- this.$set(this.list, index, row);
- },
- // 编辑
- rowEdit (row, index) {
- this.tableForm = this.deepClone(row);
- this.clearDefaultParam();
- this.$emit('input', this.tableForm);
- this.tableIndex = index;
- this.boxType = 'edit';
- this.show();
- },
- //查看
- rowView (row, index) {
- this.tableForm = this.deepClone(row);
- this.clearDefaultParam();
- this.$emit('input', this.tableForm);
- this.tableIndex = index;
- this.boxType = 'view';
- this.keyBtn = true;
- this.show();
- },
- rowCellUpdate (row, index) {
- const form = this.deepClone(this.tableForm);
- this.$emit('input', form);
- this.$emit(
- 'row-update',
- form,
- index,
- () => {
- row.$cellEdit = !row.$cellEdit;
- this.tableForm = {};
- this.tableIndex = -1;
- this.$set(this.list, index, form);
- }
- );
- },
- // 删除
- rowDel (row, index) {
- this.$emit('row-del', row, index);
- },
- // 保存
- rowSave () {
- this.$refs['tableForm'].validate().then(() => {
- this.keyBtn = true;
- this.$emit('row-save', this.deepClone(this.tableForm), this.closeDialog,
- () => {
- this.keyBtn = false;
- });
- });
- },
- // 更新
- rowUpdate () {
- this.$refs['tableForm'].validate().then(() => {
- this.keyBtn = true;
- const index = this.tableIndex;
- this.$emit(
- 'row-update',
- this.deepClone(this.tableForm),
- index,
- this.closeDialog,
- () => {
- this.keyBtn = false;
- }
- );
- });
- },
- // 显示表单
- show (cancel) {
- const callack = () => {
- if (cancel !== true) {
- this.$nextTick(() => {
- this.$refs['tableForm'].clearValidate();
- this.$refs['tableForm'].cascadeInit();
- });
- this.boxVisible = true;
- }
- };
- if (typeof this.beforeOpen === 'function') this.beforeOpen(callack, this.boxType);
- else callack();
- },
- // 隐藏表单
- hide (cancel) {
- const callack = () => {
- if (cancel !== false) {
- this.$refs['tableForm'].resetForm();
- this.$refs['tableForm'].clearValidate();
- }
- };
- if (typeof this.beforeClose === 'function') this.beforeClose(callack, this.boxType);
- else callack();
- },
- //清空多余字段
- clearDefaultParam () {
- this.defaultParam.forEach(ele => {
- delete this.tableForm[ele];
- })
- },
- resetForm () {
- this.$refs['tableForm'].resetForm();
- this.$emit('input', this.tableForm);
- }
- }
- });
- </script>
|