<template>
|
<el-card shadow="never">
|
<!--工具条-->
|
<div v-if="!myTable.isTopFrame" class="table-tool-bar" style="overflow: hidden">
|
<!--自定义工具-->
|
<my-button
|
v-for="(custom, idx) in myTable.tools.custom"
|
:key="idx"
|
site="tools"
|
:type="custom.myType"
|
:check-permission="custom.checkPermission"
|
:name="custom.name"
|
@click="custom.click"
|
/>
|
<!--导出-->
|
<el-popover v-model="visible" placement="right-start" width="250" trigger="click">
|
<el-form ref="exportParams" :model="exportParams" :rules="rules" label-position="right" size="mini" label-width="65px">
|
<el-form-item label="名称" prop="fileName"><el-input v-model="exportParams.fileName" /></el-form-item>
|
<el-form-item label="格式" class="require">
|
<el-radio-group v-model="exportParams.fileFormat" size="mini"><el-radio label=".xls">.xls</el-radio></el-radio-group>
|
</el-form-item>
|
<el-form-item label="数据" class="require">
|
<el-radio-group v-model="exportParams.page" size="mini" @change="changePageSize">
|
<el-radio label="1">本页</el-radio>
|
<el-radio label="2">全部</el-radio>
|
</el-radio-group>
|
</el-form-item>
|
<el-form-item label="页码" style="display: none;" prop="pageNum"><el-input v-model="exportParams.pageNum" /></el-form-item>
|
<el-form-item label="步长" style="display: none;" prop="pageSize"><el-input v-model="exportParams.pageSize" /></el-form-item>
|
</el-form>
|
<div style="text-align: right; margin: 0">
|
<el-button size="mini" type="default" @click="visible = false">取消</el-button>
|
<el-button type="primary" size="mini" @click="_export_">确定</el-button>
|
</div>
|
<my-button v-if="myTable.tools.generalExport.show" slot="reference" site="tools" name="导出" />
|
</el-popover>
|
|
<!--列控制-->
|
<el-popover v-if="myTable.tools.columnsCtrl.show" style="float: right;" trigger="click" placement="bottom" width="150">
|
<el-form label-width="10px" style="max-height: 500px;overflow-y: auto;">
|
<el-form-item label="">
|
<el-checkbox-group v-model="checkColumns" @change="changeColumns">
|
<el-checkbox v-for="(column, index) in myTable.columns" :key="index" :label="index">{{ column.title }}</el-checkbox>
|
</el-checkbox-group>
|
</el-form-item>
|
</el-form>
|
<el-button slot="reference" icon="el-icon-setting" size="mini">设置列</el-button>
|
</el-popover>
|
</div>
|
<!--table列表-->
|
<el-table
|
:key="timeStamp"
|
:ref="myTable.ref"
|
v-loading="myTable.loading"
|
:data="myTable.rows"
|
:max-height="myTable.maxHeight"
|
:height="myTable.height"
|
:size="myTable.size"
|
:fit="false"
|
:highlight-current-row="true"
|
border
|
>
|
<!--详情-->
|
<el-table-column v-if="myTable.expand" width="50" type="expand">
|
<template slot-scope="{ row }">
|
<el-form size="mini" label-position="left" :inline="false" class="demo-table-expand">
|
<el-form-item v-for="(more, index) in columnHidden" :key="index" size="mini" :label="more.title + ':'">
|
<template v-if="more.tag">
|
<el-tag size="mini" :type="more.tag(row).type">{{ more.tag(row).value }} {{ more }}</el-tag>
|
</template>
|
<template v-else>
|
<span v-if="more.formatter">{{ more.formatter(row).value }}</span>
|
<span v-else-if="more.switch">{{ more.switch(row).label }}</span>
|
<span v-else>{{ row[more.field] }}</span>
|
</template>
|
</el-form-item>
|
</el-form>
|
</template>
|
</el-table-column>
|
|
<!--序号 有分页时-->
|
<el-table-column v-if="myTable.showIndex && myTable.paging.page.pageSize != undefined" label="序号" align="center" width="60">
|
<template slot-scope="scope">
|
<span>{{ scope.$index + (myTable.paging.page.pageNum - 1) * myTable.paging.page.pageSize + 1 }}</span>
|
</template>
|
</el-table-column>
|
|
<!--序号 无分页时-->
|
<el-table-column v-if="myTable.showIndex && myTable.paging.page.pageSize == undefined" type="index" align="center" label="序号" width="60" />
|
<template v-for="(column,index) in columnNotHidden">
|
<!--列内容-->
|
<el-table-column
|
v-if="!(column.hidden||false)"
|
:key="index"
|
:sortable="column.sortable"
|
:label="column.title"
|
:type="column.type"
|
:min-width="column.width"
|
:align="column.align"
|
:header-align="column.align"
|
>
|
<template slot-scope="scope">
|
<!--开关(生成开关按钮)-->
|
<template v-if="column.switch">
|
<my-switch
|
:value="column.switch(scope.row).value"
|
:check-permission="column.checkPermission"
|
:disabled="column.switch(scope.row).disabled"
|
@click="switchClick(column.switch(scope.row).click)"
|
/>
|
</template>
|
<template v-else-if="column.tag">
|
<el-tag size="mini" :type="column.tag(scope.row).type">{{ column.tag(scope.row).value }}</el-tag>
|
</template>
|
<template v-else-if="column.img">
|
<preview-picture img-style="width:40px;height:40px;" :imgs="column.img(scope.row).imgs" />
|
</template>
|
<!--格式化(显示颜色,内容,点击事件控制)-->
|
<template v-else-if="column.formatter">
|
<span slot="reference" class="content-text" :style="setStyle(column.formatter(scope.row))" @click="handleClick(column.formatter(scope.row))" v-html="column.formatter(scope.row).value" />
|
</template>
|
<template v-else>
|
<!--点击弹出单元格内容-->
|
<el-popover placement="top-start" trigger="click" :content="getPopoverContent(scope.row, column)">
|
<!-- <span slot="reference" class="content-text">{{ scope.row[column.field] }}</span>-->
|
<span slot="reference" class="content-text">{{ splitField(scope.row, column.field) }}</span>
|
</el-popover>
|
</template>
|
</template>
|
</el-table-column>
|
</template>
|
|
<!--操作列-->
|
<el-table-column
|
v-if="myTable.operation.show"
|
label="操作"
|
align="center"
|
:min-width="myTable.operation.width"
|
fixed="right"
|
>
|
<template slot-scope="scope">
|
<template v-for="(operation, index) in myTable.operation.attr">
|
<my-button-v2
|
v-if="!(operation.hidden && operation.hidden(scope.row))"
|
:key="index"
|
:name="operation.title"
|
site="operation"
|
:type="operation.type"
|
:check-permission="operation.checkPermission"
|
@click="operation.events(scope.row)"
|
/>
|
</template>
|
<template v-if="myTable.operation.more && myTable.operation.more.length > 0">
|
<el-dropdown style="margin-left: 5px;" trigger="click">
|
<el-button size="small" type="text">
|
更多
|
<i class="el-icon-arrow-down el-icon--right" />
|
</el-button>
|
<el-dropdown-menu slot="dropdown">
|
<template v-for="(m, i) in myTable.operation.more">
|
<el-dropdown-item v-if="!(m.hidden && m.hidden(scope.row))" :key="i">
|
<my-button-v2
|
:name="m.title"
|
site="operation"
|
:type="m.type"
|
:check-permission="m.checkPermission"
|
@click="m.events(scope.row)"
|
/>
|
</el-dropdown-item>
|
</template>
|
</el-dropdown-menu>
|
</el-dropdown>
|
</template>
|
</template>
|
</el-table-column>
|
</el-table>
|
<el-pagination
|
:small="myTable.paging.page.small"
|
:current-page="myTable.paging.page.pageNum"
|
:page-sizes="[5, 10, 20, 50, 100, 200, 300, 400, 500]"
|
:page-size="myTable.paging.page.pageSize"
|
layout="total, sizes, prev, pager, next, jumper"
|
:total="myTable.paging.page.total"
|
@size-change="handleSizeChange"
|
@current-change="handleCurrentChange"
|
/>
|
</el-card>
|
</template>
|
|
<script>
|
import myButtonV2 from '@/views/components/myButtonV2'
|
import myButton from '@/views/components/myButton'
|
import mySwitch from './mySwitch'
|
import request from '@/utils/request'
|
import * as valid from '@/utils/validate'
|
import previewPicture from '@/views/components/previewPicture'
|
|
export default {
|
components: { myButtonV2, myButton, mySwitch, previewPicture },
|
props: {
|
table: {
|
type: Object,
|
default() {
|
return null
|
}
|
},
|
// 当点击重置按钮时,filter指向改变时不需要手动调用search方法, 仅改变filter内部值时需手动调用search
|
// 如: this.filter = {} 不需要调用search this.filter.name = null 时需调用search
|
filter: {
|
type: Object,
|
default() {
|
return null
|
}
|
}
|
},
|
data() {
|
const validatepageNumber = (rule, value, callback) => {
|
if (!valid.isNotEmpty(this.exportParams.pageNum)) {
|
callback(new Error('请输入页码'))
|
} else if (!valid.isInteger(this.exportParams.pageNum)) {
|
callback(new Error('页码为正整数'))
|
} else {
|
callback()
|
}
|
}
|
const validatepageSize = (rule, value, callback) => {
|
if (!valid.isNotEmpty(this.exportParams.pageSize)) {
|
callback(new Error('请输入步长'))
|
} else if (!valid.isInteger(this.exportParams.pageSize)) {
|
callback(new Error('步长为正整数'))
|
} else if (this.exportParams.pageSize > 20000 || this.exportParams.pageSize < 1) {
|
callback(new Error('单次导出步长范围1~20000'))
|
} else {
|
callback()
|
}
|
}
|
const validatefileName = (rule, value, callback) => {
|
if (!valid.isNotEmpty(this.exportParams.fileName)) {
|
callback(new Error('请输入文件名称'))
|
} else if (this.exportParams.fileName.length < 1 || this.exportParams.fileName.length > 10) {
|
callback(new Error('文件名称长度范围1~10'))
|
} else {
|
callback()
|
}
|
}
|
return {
|
/** table列表数据*/
|
myTable: {
|
autoLoad: true,
|
url: '',
|
params: {},
|
showIndex: true, // 是否显示序号
|
expand: true, // 是否显示详情数据
|
loading: false, // 加载效果
|
// height: 500, // 默认高度自动单位px
|
// maxHeight: 500, //默认不设置单位px
|
size: 'medium', // Table 的尺寸 medium / small / mini
|
showCheckBox: false, // 是否显示复选框
|
// 工具条
|
tools: {
|
columnsCtrl: {
|
// 列控制按钮
|
show: false
|
},
|
generalExport: {
|
// 通用导出按钮
|
show: false
|
},
|
custom: [] // 自定义工具条按钮
|
},
|
columns: [], // 列属性配置custom
|
operation: {
|
// 操作列
|
show: false, // 显示操作列
|
showMoreSize: 3, // 超出几个显示更多按钮
|
width: '250', // 宽度
|
align: 'center',
|
attr: [], // 操作
|
more: [] // 更多
|
},
|
rows: [], // 列表数据
|
paging: {
|
show: true, // 显示分页
|
// 分页信息
|
page: {
|
small: false,
|
pageNum: 1,
|
pageSize: 10,
|
total: 0
|
}
|
}
|
},
|
checkColumns: [], // 记录列控制中选中的列
|
// 导出功能所需参数
|
visible: false, // 控制导出表单的隐藏
|
exportParams: {
|
fileName: '',
|
fileFormat: '.xls',
|
page: '2',
|
pageNum: 1,
|
pageSize: 20000
|
},
|
// 导出表单校验
|
rules: {
|
fileName: [{ required: true, validator: validatefileName, trigger: 'blur' }],
|
pageNum: [{ required: true, validator: validatepageNumber, trigger: 'blur' }],
|
pageSize: [{ required: true, validator: validatepageSize, trigger: 'blur' }]
|
},
|
timeStamp: new Date().getTime()
|
}
|
},
|
computed: {
|
// 通过计算属性过滤掉列表中不需要显示的项目
|
columnHidden: function() {
|
return this.myTable.columns.filter(function(x) {
|
return x.hidden
|
})
|
},
|
columnNotHidden: function() {
|
return this.myTable.columns.filter(function(x) {
|
return !x.hidden
|
})
|
},
|
operButtons() {
|
const that = this
|
return function(row) {
|
const arr = []
|
that.myTable.operation.attr.map(item => {
|
if (!(item.hidden && item.hidden(row)) && item.checkPermission) {
|
arr.push(item)
|
}
|
})
|
return arr
|
}
|
}
|
},
|
watch: {
|
filter(val) {
|
this.search({ pageNum: 1 })
|
}
|
},
|
created() {
|
const that = this
|
|
window.onresize = function() {
|
that.timeStamp = new Date().getTime()
|
}
|
this.initTable()
|
},
|
methods: {
|
/**
|
* 解决:field中属性套属性的情况。2023-04-25
|
* @param row
|
* @param field
|
*/
|
splitField(row, field){
|
if(field.indexOf('.') > -1){
|
const arr = field.split('.');
|
let fieldStr = '';
|
for(let i=0, len=arr.length; i<len; i++){
|
if(i == len - 1){
|
fieldStr += arr[i];
|
} else {
|
fieldStr += arr[i] + '.';
|
}
|
}
|
return eval('row.' + fieldStr);
|
} else {
|
return row[field];
|
}
|
},
|
|
initTable() {
|
if (this.table !== null) {
|
Object.assign(this.myTable, this.table)
|
if (this.myTable.paging.page === undefined) {
|
this.$set(this.myTable.paging, 'page', {
|
small: false,
|
pageNum: 1,
|
pageSize: 10,
|
total: 0
|
})
|
}
|
this.myTable.columns.forEach((column, idx) => {
|
if (!column.hidden) {
|
this.checkColumns.push(idx)
|
}
|
})
|
this.$nextTick(() => {
|
if (this.myTable.autoLoad) {
|
this.search({ pageNum: 1 })
|
}
|
})
|
}
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 10:52
|
* @Description : 列表搜索
|
*/
|
search(param) {
|
this.$nextTick(() => {
|
this.myTable.loading = true
|
const params = Object.assign({}, this.filter)
|
params.pageSize = this.myTable.paging.page.pageSize
|
if (param && param.pageNum) {
|
this.myTable.paging.page.pageNum = param.pageNum
|
}
|
params.pageNum = this.myTable.paging.page.pageNum
|
request({
|
url: this.myTable.url,
|
method: 'get',
|
params: params
|
}).then(res => {
|
if (res.data) {
|
this.$set(this.myTable, 'rows', res.data.datas);
|
}
|
this.$set(
|
this.myTable.paging,
|
'page',
|
Object.assign(this.myTable.paging.page, {
|
pageSize: res.data.pageSize,
|
pageNum: res.data.pageIndex,
|
total: res.data.totalRows
|
})
|
)
|
this.myTable.loading = false
|
// this.$refs[this.myTable.ref].doLayout()
|
}).catch(() => {
|
this.myTable.loading = false
|
})
|
})
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 10:48
|
* @Description : 获取设置列表弹层内容
|
*/
|
getPopoverContent(row, column) {
|
if (column.formatterHigh) {
|
return column.formatterHigh(row).value + ''
|
} else if (column.formatter) {
|
return column.formatter(row) + ''
|
} else {
|
return row[column.field] + ''
|
}
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 11:39
|
* @Description :单元格内容格式化样式
|
*/
|
setStyle(format) {
|
let styles = ''
|
if (format.click != undefined) {
|
styles += 'cursor: pointer;'
|
}
|
if (format.type != undefined) {
|
if (format.type == 'primary') {
|
styles += 'color:#409EFF;'
|
} else if (format.type == 'danger') {
|
styles += 'color:#F56C6C;'
|
} else if (format.type == 'success') {
|
styles += 'color:#67C23A;'
|
} else if (format.type == 'warning') {
|
styles += 'color:#E6A23C;'
|
} else if (format.type == 'info') {
|
styles += 'color:#909399;'
|
}
|
}
|
return styles
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 12:20
|
* @Description : formatter 点击事件
|
*/
|
handleClick(format) {
|
if (format.click != undefined) {
|
format.click()
|
}
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 12:21
|
* @Description : 开关点击事件
|
*/
|
switchClick(click) {
|
if (typeof click === 'function') {
|
click()
|
}
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 14:22
|
* @Description :切换pageSize
|
*/
|
handleSizeChange(pageSize) {
|
this.myTable.paging.page.pageSize = pageSize
|
this.search({ pageNum: 1 })
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 14:22
|
* @Description :切换pageNumber
|
*/
|
handleCurrentChange(pageNum) {
|
this.myTable.paging.page.pageNum = pageNum
|
this.search({ pageNum: pageNum })
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 14:52
|
* @Description :列控制
|
*/
|
changeColumns() {
|
this.myTable.columns.forEach((column, idx) => {
|
if (this.checkColumns.includes(idx)) {
|
column.hidden = false
|
} else {
|
column.hidden = true
|
}
|
this.$set(this.myTable.columns, idx, column)
|
})
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-23 10:44
|
* @Description : 修改导出 pageSize
|
*/
|
changePageSize() {
|
if (this.exportParams.page == 1) {
|
this.exportParams.pageSize = this.myTable.paging.page.pageSize
|
} else if (this.exportParams.page == 2) {
|
this.exportParams.pageSize = 20000
|
}
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-17 16:38
|
* @Description :通用导出
|
*/
|
_export_() {
|
this.$refs['exportParams'].validate(valid => {
|
if (valid) {
|
// 判断总条数是否大于最大支持条数
|
if (this.myTable.paging.page.total > 20000) {
|
this.$confirm(`当前筛选数据条数${this.myTable.paging.page.total},最大支持导出条数20000,是否继续导出?`, '提示', {
|
confirmButtonText: '是',
|
cancelButtonText: '否',
|
type: 'warning'
|
})
|
.then(() => {
|
this._export_m()
|
})
|
.catch(() => {
|
return false
|
})
|
} else {
|
this._export_m()
|
}
|
} else {
|
return false
|
}
|
})
|
},
|
/*
|
* @Author : liu.q [916000612@qq.com]
|
* @Date : 2019-07-23 11:22
|
* @Description : 真正的导出
|
*/
|
_export_m() {
|
const loading = this.$loading({
|
lock: true,
|
text: '正在导出...',
|
spinner: 'el-icon-loading',
|
background: 'rgba(0, 0, 0, 0.7)'
|
})
|
|
this.visible = false
|
const params = {}
|
params.url = this.myTable.url
|
const columns = []
|
this.myTable.columns.forEach(c => {
|
if (!c.hidden || c.export) {
|
columns.push({
|
title: c.title,
|
field: c.field
|
})
|
}
|
})
|
params.columns = encodeURI(JSON.stringify(columns))
|
params.filter = encodeURI(
|
JSON.stringify(
|
Object.assign(
|
{
|
pageNum: this.exportParams.pageNum,
|
pageSize: this.exportParams.pageSize
|
},
|
this.filter
|
)
|
)
|
)
|
params.fileName = encodeURI(this.exportParams.fileName)
|
if (this.myTable.tools.generalExport.formatter) {
|
params.formatter = encodeURI(JSON.stringify(this.myTable.tools.generalExport.formatter))
|
}
|
|
request({
|
url: globalConf.baseUrl + '/v1/base/pc/export/generalExport3', // 请求地址,
|
method: 'post',
|
data: params
|
}).then(response => {
|
if (response.code == 10000) {
|
const link = globalConf.baseUrl + `/v1/base/web/common/downExcel?key=${response.data}`
|
window.location.href = link
|
} else {
|
this.$message({
|
message: '哎呀,出意外了。。。',
|
type: 'warning'
|
})
|
}
|
loading.close()
|
})
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
>>> .el-table__header {
|
width: 100% !important;
|
}
|
>>> .el-table__body {
|
width: 100% !important;
|
}
|
|
/*详情表单*/
|
.demo-table-expand .el-form-item{
|
width: 100%;
|
}
|
|
/*列表内文字过长加省略*/
|
.content-text{
|
overflow:hidden;
|
text-overflow:ellipsis;
|
white-space:nowrap
|
}
|
|
/*分页上边距*/
|
.el-pagination {
|
white-space: nowrap;
|
padding: 2px 5px;
|
color: #303133;
|
font-weight: 700;
|
margin-top: 10px;
|
}
|
.el-radio {
|
margin-right: 10px;
|
}
|
.el-radio__label {
|
font-size: 14px;
|
padding-left: 2px !important;
|
}
|
/deep/.el-table__empty-block {
|
width: 100%;
|
text-align: center;
|
margin: 0 auto;
|
}
|
.table-tool-bar{
|
margin-bottom: 20px;
|
}
|
</style>
|