1.组件,BaseTable 下有两个文件,index.vue ,extend.js
index.vue代码
<template>
<div class="crud">
<!--crud头部,包含列表标题和可操作按钮-->
<el-row class="crud-header">
<!--<el-col :span="8">{{formTitle}}列表</el-col>-->
<el-col :span="24">
<el-button type="success" size="mini" v-if="gridBtnConfig.create" @click="createOrUpdate(null)">
<i class="el-icon-plus"></i> 新增
</el-button>
<!-- 标记为single的按钮不需要禁用,不依赖选择数据-->
<el-button :disabled="!item.single && multipleSelection.length === 0" size="mini"
@click="handleEmit(item.emitName,'outer')"
v-for="(item,index) in outerButton" :key="index" :type="item.type?item.type:'primary'">
<svg-icon v-if="item.icon" :icon-class="item.icon"></svg-icon>
{{item.name}}
</el-button>
<el-button :disabled="multipleSelection.length === 0" size="mini" v-if="gridBtnConfig.delete" type="danger"
@click="remove(2)">
<svg-icon icon-class="delete"></svg-icon>
删除
</el-button>
</el-col>
</el-row>
<!--crud主体内容区,展示表格内容-->
<el-table
ref="multipleTable"
v-loading="listLoading" element-loading-text="请等待"
:data="showGridData"
@selection-change="handleSelectionChange"
border
:stripe="true"
:header-cell-style="{'textAlign':'center'}"
style="width: 100%">
<el-table-column
v-if="!hideMultiple"
fixed="left"
type="selection"
width="55">
</el-table-column>
<el-table-column
v-if="hideMultiple"
fixed="left"
label="序号"
type="index"
width="55">
</el-table-column>
<el-table-column
v-for="(item,index) in gridConfig"
:key="index"
:prop="item.prop"
:label="item.label"
:align="nameLeft(item.label)"
show-overflow-tooltip
:width="item.width?item.width:''">
<template slot-scope="scope">
<span v-if="item.filter" ref="yifutian">{{walkProperty(item.prop,scope.row)||walkProperty(item.prop,scope.row)==0? item.filter(walkProperty(item.prop,scope.row)) : '--'}}</span>
<Cell
v-if="item.render"
:row="scope.row"
:column="item"
:index="scope.$index"
:render="item.render"></Cell>
<span v-if="!item.render&&!item.filter">
<span v-if="!item.template" ref="yifutian">{{walkProperty(item.prop,scope.row)||walkProperty(item.prop,scope.row)==0 ? walkProperty(item.prop,scope.row) : '--'}}</span>
<a style="color: #1582cf;cursor: pointer;" v-else @click="handleEmit(item.emitName,'inner',scope.row)">{{walkProperty(item.prop,scope.row)||walkProperty(item.prop,scope.row)==0 ? walkProperty(item.prop,scope.row) : '--'}}</a>
</span>
</template>
</el-table-column>
<el-table-column v-if="!hideEditArea" label="操作" :width="gridEditWidth?gridEditWidth:200" fixed="right">
<template slot-scope="scope">
<el-tooltip v-if="gridBtnConfig.update" effect="dark" content="修改" placement="top">
<span style="color: #409EFF" class="edit-icon" @click="createOrUpdate(scope.row)"><svg-icon
icon-class="xg"></svg-icon></span>
</el-tooltip>
<el-tooltip v-if="gridBtnConfig.view" effect="dark" content="查看" placement="top">
<span style="color: #409EFF" class="edit-icon" @click="viewDetail(scope.row)"><svg-icon
icon-class="view"></svg-icon></span>
</el-tooltip>
<!--扩展按钮,如果扩展按钮设置了动态显示隐藏的条件,则需要根据条件显示隐藏-->
<el-tooltip v-for="(item,index) in innerButton" :key="index" :type="item.type?item.type:'primary'"
v-if="(!item.hideJudge)||(item.hideJudge && walkProperty(item.hideJudge.key,scope.row) === item.hideJudge.val && (item.hideJudge.key2 ? walkProperty(item.hideJudge.key2,scope.row) === item.hideJudge.val2 : true))"
effect="dark" :content="item.name" placement="top">
<span :style="{color:item.iconColor?item.iconColor:'#409EFF'}" class="edit-icon"
@click="handleEmit(item.emitName,'inner',scope.row)"><svg-icon
:icon-class="item.icon?item.icon:'xg'"></svg-icon></span>
</el-tooltip>
<el-tooltip v-if="gridBtnConfig.singleDelete" effect="dark" content="删除" placement="top">
<span style="color: #F56C6C" class="edit-icon" @click="remove(1,scope.row)"><svg-icon
icon-class="delete"></svg-icon></span>
</el-tooltip>
</template>
</el-table-column>
</el-table>
<!--crud的分页组件-->
<div class="crud-pagination">
<!--如果不是异步请求展示数据,需要隐藏分页-->
<el-pagination
v-if="isAsync"
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="currentPage"
:page-sizes="pageSizes?pageSizes:[10, 20, 30, 40]"
:page-size="currentPageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="dataTotal">
</el-pagination>
</div>
<!--crud按钮触发的表单弹窗-->
<BaseDialogForm :width="dialogWidth" :label-width="dialogLabelWidth" :title="dialogTitle" ref="dialogForm"
:config="formConfig"
:form-data="formModel"
@submit="dialogSubmit"></BaseDialogForm>
<!--查看详情模态框-->
<gx-dialog
title="查看详情"
:visible.sync="detailDialogVisible"
:width="dialogWidth ? dialogWidth : '1300px'">
<ViewDetail :config="infoConfig?infoConfig:formConfig" :data="detailData"></ViewDetail>
</gx-dialog>
<el-dialog
title="提示"
:close-on-click-modal="false"
:visible.sync="deletess"
width="400px">
<i class="el-icon-info" style="color:#E6A23C;"></i>
<span>此操作将永久删除数据, 是否继续?</span>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="deletes" size="mini">确 定</el-button>
<el-button @click="qxss" size="mini">取 消</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import BaseDialogForm from '@/components/BaseDialogForm/index.vue'
import ViewDetail from '@/components/ViewDetail/index.vue'
import GxDialog from "../GxDialog/index"
/*用render渲染自定义template*/
import Cell from './expand';
export default {
name: "base-crud",
components: {
BaseDialogForm,
ViewDetail,
GxDialog,
Cell
},
props: [
//
'pageSizes',
// 表单标题,例如用户、角色
'formTitle',
// 表单配置
'formConfig',
//详情的字段配置
'infoConfig',
// 表单的model数据
'formData',
// 表格配置
'gridConfig',
// 表格按钮配置
'gridBtnConfig',
// 表格死数据
'gridData',
// 数据接口
'apiService',
// 判断是否是异步数据
'isAsync',
// 表格编辑区域宽度
'gridEditWidth',
// 是否隐藏表格操作
'hideEditArea',
// 自定义新增和修改操作,覆盖组件内的新增和删除逻辑
'selfCreateAndUpdate',
//是否显示多选,若不显示多选,则显示列表序号
'hideMultiple',
//数据的id标识字符串
'idKey',
//表格获取数据默认传入的参数
'gridParams',
//
'Update',
// 禁止删除的条件配置
'forbiddenData',
// 操作的模态框宽度
'dialogWidth',
// 操作模态框中的表单label宽度
'dialogLabelWidth',
// 状态颜色区别配置数组:[[未处理],[已处理],[已过期],[其它状态]]
'statusobj'
],
data() {
return {
// 新增修改模态框title
dialogTitle: '',
// 展示的表格数据,数据来源可能是父组件传递的固定数据,可能是接口请求数据
showGridData: [],
// 当前页码
currentPage: 1,
// 每页显示数量
currentPageSize: 10,
// 列表数据总数
dataTotal: 0,
// 选中行数据
selectedRow: '',
// 表单数据
formModel: {},
// 保留多选的表格数据
multipleSelection: [],
// 扩展按钮,包括表格内按钮和表格外的批量操作按钮
innerButton: [],
outerButton: [],
// 详情数据
detailData: {},
detailDialogVisible: false,
// 是否是新增
isCreate: true,
// 数据加载
listLoading: false,
// 查询参数
searchParams: {},
//删除的数据
ids: [],
//删除的弹框
deletess: false,
color: true,
statusObj: ''
}
},
mounted() {
//初始化扩展按钮
if (this.gridBtnConfig.expands && this.gridBtnConfig.expands.length > 0) {
//内部按钮,只操作单行数据
this.innerButton = this.gridBtnConfig.expands.filter(item => item.editType === 'inner');
//外部按钮,操作批量数据
this.outerButton = this.gridBtnConfig.expands.filter(item => item.editType === 'outer');
}
this.getData();
this.statusObj = this.statusobj ? this.statusobj : [['未提交'], ['已提交', '已批复', '审批通过', '待上报', '已批复', '已撤回'], ['审核中', '返回修改'], ['已上报', '待批复'], ['审批不通过']];
},
methods: {
nameLeft(name) {
let a = name.substr(name.length - 2, 2);
// console.log(name.indexOf('名称'),a);
if (a == '名称') {
return 'left'
} else {
return 'center'
}
},
// 获取列表数据
getData() {
this.listLoading = true;
//没有定义api,直接返回,不进行请求
if (!this.apiService) {
this.listLoading = false;
this.showGridData = this.gridData;
return;
}
let params = {
current: this.currentPage,
size: this.currentPageSize
};
params = Object.assign({}, params, this.gridParams, this.searchParams);
this.apiService.list(params).then(res => {
this.showGridData = res.page.list;
this.dataTotal = res.page.totalCount;
this.listLoading = false;
//请求数据完成
this.$emit('getDataOver', res.page.list);
});
},
//查询
search(params) {
this.currentPage = 1
this.currentPageSize = 10
this.searchParams = Object.assign({}, params);
this.getData();
},
//清空查询
clearSearch() {
this.searchParams = {};
this.getData();
},
// 查看详情
viewDetail(row) {
this.detailData = Object.assign({}, row);
this.detailDialogVisible = true;
},
createOrUpdate(item) {
// 如果配置了覆盖组件内新增和修改按钮时执行
if (this.selfCreateAndUpdate) {
this.$emit('createOrUpdate', item);
return;
}
this.$refs.dialogForm.resetForm();
this.formModel = item ? Object.assign({}, item) : Object.assign({}, this.formData);
this.dialogTitle = (item ? '修改' : '新增') + this.formTitle;
this.isCreate = !item;
this.$refs.dialogForm.showDialog();
},
// 处理相应父组件的事件方法
handleEmit(emitName, type, row) {
// 如果是表格内按钮,只需要回传单行数据,表格外按钮,则需要回传批量数据
if (type === 'inner') {
this.$emit(emitName, row);
}
else {
this.$emit(emitName, this.multipleSelection);
}
},
handleCurrentChange(page) {
this.currentPage = page;
this.getData();
},
handleSizeChange(size) {
this.currentPageSize = size;
this.getData();
},
// 处理点击行
handleRowClick(row, event, column) {
this.selectedRow = Object.assign({}, row);
},
// 模态框数据提交
dialogSubmit(data) {
if (this.Update) {
this.$emit('Update', data);
return;
}
this.apiService[this.isCreate ? 'create' : 'update'](data).then(res => {
this.$message.success(this.dialogTitle + '成功!');
this.getData();
this.$refs.dialogForm.hideDialog();
})
},
hideDialog() {
this.$refs.dialogForm.hideDialog();
},
//处理多选改变时
handleSelectionChange(val) {
this.multipleSelection = val;
},
// 切换当前行的选中状态
toggleSelection(rows) {
if (rows) {
this.$nextTick(()=>{
rows.forEach(row => {
this.$refs.multipleTable.toggleRowSelection(row);
});
})
} else {
this.$refs.multipleTable.clearSelection();
}
},
//删除方法
remove(type, data) {
this.ids = [];
//type为1代表单个删除,2代表批量删除
if (type === 1) {
this.ids = [data[this.idKey ? this.idKey : 'id']];
} else {
//如果上传了禁止删除的条件,进入下面条件处理
if (this.forbiddenData) {
let key = this.forbiddenData.key;
let arr = this.forbiddenData.data;
let boolean = false;
this.multipleSelection.forEach(item => {
arr.forEach(val => {
if (val === item[key]) {
return (boolean = true);
}
});
//如果已经有禁止删除项,退出遍历,优化性能
if (boolean) {
return false;
}
});
if (boolean) {
return this.$notify({
title: '警告',
message: '您选择的数据包含禁止删除项,请重新选择数据进行删除!!!',
type: 'warning',
position: 'top-left',
duration: 2000
});
}
}
this.ids = this.multipleSelection.map(item => item[this.idKey ? this.idKey : 'id']);
}
// this.$confirm('此操作将永久删除数据, 是否继续?', '提示', {
// showCancelButton: true,
// confirmButtonText: '确定',
// cancelButtonText: '取消',
// confirmButtonClass:'confirmButtonClass',
// type: 'warning'
// }).then(() => {
// this.apiService.delete(ids).then(res => {
// this.$message({
// type: 'success',
// message: '删除成功!'
// });
//
// this.getData();
// })
// }).catch(() => {
// this.$message({
// type: 'info',
// message: '已取消删除'
// });
//
//
// });
this.deletess = true
},
deletes() {
this.apiService.delete(this.ids).then(res => {
this.$message({
type: 'success',
message: '删除成功!'
});
this.getData();
this.deletess = false
})
},
qxss() {
this.deletess = false
this.$message({
type: 'info',
message: '已取消删除'
});
},
walkProperty(prop, data) {
//a.b
if (prop && prop.indexOf('.') !== -1) {
let path = prop.split('.'), i, v = data;//[a, b]
while (i = path.shift()) {
if (v && v[i]) {
v = v[i];
}
else {
v = '';
}
}
return v;
}
else {
return data[prop];
}
},
//清空多选
clearSelection() {
//清空多选的选中
this.$refs.multipleTable && this.$refs.multipleTable.clearSelection();
},
shangse() {
let i = 1;
let elementArrays = this.$refs.yifutian;
if (!elementArrays) {
return;
}
this.statusObj.forEach(obj => {
obj.forEach(obj2 => {
elementArrays.forEach(item => {
let str = item.innerText;
if (str === obj2) {
item.setAttribute('class', 'class' + i);
}
})
});
i++;
});
},
setGridParams(data) {
this.search(data);
}
},
watch: {
// 防止表格预置数据不成功,涉及生命周期问题
gridData() {
this.showGridData = this.gridData;
this.dataTotal = this.showGridData.length;
},
showGridData: function () {
this.$nextTick(function () {
this.shangse();
})
}
},
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.crud {
.crud-header {
margin-bottom: 10px;
line-height: 40px;
}
.crud-pagination {
text-align: right;
margin-top: 10px;
}
/*表格内编辑图标*/
.edit-icon {
font-size: 20px;
margin-right: 10px;
cursor: pointer;
}
/*未处理*/
.class1 {
color: #999999;
padding: 5px;
}
/*已处理*/
.class2 {
color: #06AC4D;
padding: 5px;
}
/*已过期*/
.class3 {
color: #FBBE42;
padding: 5px;
}
/*其它状态*/
.class4 {
color: #3DB5FC;
padding: 5px;
}
.class5 {
color: #FC5454;
padding: 5px;
}
}
</style>
<style>
.confirmButtonClass {
color: #fff;
background-color: #0597D2 !important;
border-color: #0597D2 !important;
}
</style>
--extend.js代码
export default {
name: 'TableExpand',
functional: true,
props: {
row: Object,
render: Function,
index: Number,
column: {
type: Object,
default: null
}
},
render: (h, ctx) => {
const params = {
row: ctx.props.row,
index: ctx.props.index
};
if (ctx.props.column) params.column = ctx.props.column;
return ctx.props.render(h, params);
}
};
2.以上是两个组件的代码,下面将介绍调用及传入数据的格式
--调用组件
引入组件,且注册组件
import BaseTable from '@/components/BaseTable/index.vue'
注册加入components
components: {
BaseTable
},
调用组件
<BaseTable :api-service="informationApi" :grid-config="INFO_CONFIG.gridConfig"
:grid-btn-config="INFO_CONFIG.gridBtnConfig"
ref="crud" :grid-edit-width="80"
:is-async="true" :hide-edit-area="true">
</BaseTable>
传入数据的Js数据格式:
const INFO_CONFIG = {
gridConfig: [
{label: '设备代码', prop: 'sbdm', width: '150'},
{label: '设备名称', prop: 'sbmc'},
{label: '型号规格', prop: 'xh'},
{label: '计量单位', prop: 'jldw', filter: equipmentUnitFilter},
{label: '类型', prop: 'lx'},
{label: '厂家', prop: 'cj'},
{label: '是否是计量设备', prop: 'sfjlsb', filter: filterJLSB},
{label: '筹供单位', prop: 'cgdw', filter: filterGCDW},
{label: '使用年限(月)', prop: 'synx'},
],
//操作按钮
gridBtnConfig: {
create: false, update: false, delete: false, view: false
}
}
注意informationApi:是API 调用地址,如果需要直接传入数据,需要更组件中的逻辑,apiService传入true,不需要请求数据,出入gridData=[],即表格显示的数据,组件中传入的参数都写了注释,根据需做出更改吧
关注博客,后期更新Vue表单组件。
来源:oschina
链接:https://my.oschina.net/u/4351661/blog/4479833