<template>
|
<div class="list-table" :class="{'padding-right': isPaddingRight}">
|
<SectionTitle v-if="title" :title="title"></SectionTitle>
|
<el-table
|
:data="list"
|
:style="{width: showWidth, ...tableStyle}"
|
v-loading="loading"
|
stripe
|
:show-summary="isShowSummary"
|
:summary-method="getSummaries"
|
ref="commTable"
|
@selection-change="handleSelectionChange"
|
:max-height="maxHeight"
|
class="list-table-content"
|
>
|
<!-- 序号 -->
|
<el-table-column
|
v-if="isShowCheckbox"
|
type="selection"
|
width="55"
|
:selectable="handleDisable"
|
></el-table-column>
|
|
<!-- 序号 -->
|
<el-table-column v-if="isShowColumn" v-bind="mixIndexColumnInfo" type="index"></el-table-column>
|
|
<el-table-column
|
v-for="(item, index) in header"
|
:key="index"
|
:prop="item.prop"
|
:label="item.label"
|
:class-name="requiredIndexList.includes(index) ? 'table-required-label' : ''"
|
v-bind="typeof item.attrs === 'object' ? {...columnAttrs, width: propsWidth[item.label] ? `${propsWidth[item.label]}px` : columnWidth, ...item.attrs} : {width: propsWidth[item.label] ? `${propsWidth[item.label]}px` : columnWidth,...columnAttrs}"
|
>
|
<div slot-scope="scope" class="item-inner">
|
<!-- 文本固定的情况, 从header中获取 -->
|
<p v-if="item.type ==='links'" class="table-links">
|
<el-link
|
:underline="false"
|
type="text"
|
v-for="(link, linkIndex) in item.links"
|
@click="$emit('doAction', linkIndex, scope.row, scope.$index)"
|
:key="linkIndex"
|
>{{ link }}</el-link>
|
</p>
|
<!-- 文本动态的情况, 从列表中获取 -->
|
<div v-else-if="item.type ==='buttons'" class="table-buttons">
|
<el-button
|
type="text"
|
v-if="scope.row[item.prop].buttons.length > 0"
|
@click="$emit('doAction', scope.row[item.prop].buttons[0], scope.row, scope.$index)"
|
>{{scope.row[item.prop].buttons[0].text}}</el-button>
|
<!-- 按钮只有做一个,且按钮可能显示,也可能不显示 -->
|
<span
|
v-if="scope.row[item.prop].disable"
|
:class="!scope.row[item.prop].disable ? '' : 'button-select-disabled'"
|
>{{scope.row[item.prop].disable[0]}}</span>
|
<span
|
class="button-select-disabled"
|
v-if="scope.row[item.prop].buttons.length === 1 && isShowMore"
|
>更多</span>
|
<el-button
|
type="text"
|
v-if="scope.row[item.prop].buttons.length === 2"
|
@click="$emit('doAction', scope.row[item.prop].buttons[1], scope.row, scope.$index)"
|
>{{scope.row[item.prop].buttons[1].text}}</el-button>
|
<!-- :offset="60" -->
|
<el-popover
|
placement="bottom-start"
|
popper-class="table-buttons-popover"
|
trigger="hover"
|
v-if="scope.row[item.prop].buttons.length > 2 && isShowMore"
|
>
|
<p class="more-buttons">
|
<el-link
|
:underline="false"
|
type="text"
|
v-for="(buttonItem, buttonIndex) in scope.row[item.prop].buttons.filter((but, butInd)=> butInd > 0)"
|
:key="buttonIndex"
|
@click="$emit('doAction', buttonItem, scope.row, scope.$index)"
|
>{{buttonItem.text}}</el-link>
|
</p>
|
<span class="button-select" slot="reference">
|
更多
|
<i class="el-icon-arrow-down el-icon--right"></i>
|
</span>
|
</el-popover>
|
</div>
|
<div v-else-if="typeof scope.row[item.prop] === 'object'" class="column-input">
|
<CommInput
|
:info="scope.row[item.prop]"
|
@updateValue="(...args)=> updateValue(...args, scope.$index)"
|
></CommInput>
|
</div>
|
<div v-else class="column-text">
|
<TableText
|
:propsWidth="propsWidth"
|
:columnWidth="columnWidth"
|
:text="scope.row[item.prop]"
|
:header="item"
|
></TableText>
|
</div>
|
</div>
|
</el-table-column>
|
</el-table>
|
<div v-if="Object.keys(pageInfo).length > 0" class="pagination">
|
<el-pagination
|
v-bind="mixPaginationInfo"
|
@size-change="handleSizeChange"
|
@current-change="handleCurrentChange"
|
:current-page="pageInfo.currentPage"
|
:page-size="pageInfo.size"
|
:total="total"
|
></el-pagination>
|
</div>
|
</div>
|
</template>
|
|
<script>
|
import dayjs from 'dayjs'
|
import SectionTitle from '@/components/SectionTitle'
|
import propsWidth from '@/utils/tablePropsWidth'
|
import CommInput from '@/components/CommInput'
|
import TableText from '@/components/TableText'
|
|
export default {
|
components: {
|
SectionTitle,
|
CommInput,
|
TableText
|
},
|
props: {
|
// 标题
|
title: {
|
type: String,
|
default: ''
|
},
|
|
loading: {
|
type: Boolean,
|
default: false
|
},
|
|
// 表格样式
|
tableStyle: {
|
type: Object,
|
default: () => {
|
return {}
|
}
|
},
|
|
/**
|
* 列表信息
|
* @example
|
* [{"curoperateorgname": "信贷产品部", "serialNo": "2019070900000001"}]
|
*/
|
list: {
|
type: Array,
|
default: () => []
|
},
|
|
/**
|
* 字段映射说明头
|
* @example
|
* [ { "prop": "serialNo", "label": "申请编号", "width": "300px", "fixed": true, "type": "link" }]
|
*/
|
header: {
|
type: Array,
|
default: () => []
|
},
|
|
// page信息
|
pageInfo: {
|
type: Object,
|
default: () => {
|
return {
|
// currentPage: 1,
|
// pageSize: 10
|
}
|
}
|
},
|
|
// 总页数
|
total: {
|
type: Number,
|
default: 0
|
},
|
|
// 分页配置
|
paginationInfo: {
|
type: Object,
|
default: () => {
|
return {}
|
}
|
},
|
|
// 是否展示合计栏
|
isShowSummary: {
|
type: Boolean,
|
default: false
|
},
|
|
// 序号配置(''为不显示)
|
columnIndexInfo: {
|
type: [Object, String],
|
default: () => {
|
return {}
|
}
|
},
|
|
// 是否展示更多按钮
|
isShowMore: {
|
type: Boolean,
|
default: true
|
},
|
|
// 是否显示checkbox
|
isShowCheckbox: {
|
type: Boolean,
|
default: false
|
},
|
|
// 标题
|
dateFormate: {
|
type: String,
|
default: 'YYYY/MM/DD'
|
},
|
|
// 是否右边有padding值
|
isPaddingRight: {
|
type: Boolean,
|
default: true
|
},
|
|
pageId: {
|
type: String,
|
default: ''
|
},
|
|
maxHeight: {
|
type: [Number, String],
|
default: 710
|
}
|
},
|
data() {
|
return {
|
columnWidth: '150px',
|
defaultIndexColumnInfo: {
|
fixed: false,
|
label: ' ',
|
width: '50px',
|
type: 'index'
|
},
|
defaultPaginationInfo: {
|
background: true,
|
'page-sizes': [10, 20, 50, 100],
|
layout: 'prev, pager, next, jumper, total, sizes'
|
},
|
columnAttrs: {
|
// width: '150px',
|
align: 'left',
|
fixed: false
|
},
|
propsWidth
|
}
|
},
|
methods: {
|
handleSizeChange(val) {
|
this.$emit('handleSizeChange', val)
|
},
|
handleCurrentChange(val) {
|
this.$emit('handleCurrentChange', val)
|
},
|
// 合计数据处理
|
getSummaries() {
|
const { list, header, isShowSummary, isShowColumn } = this
|
let result = []
|
if (isShowSummary) {
|
// 合计处理
|
result = header.reduce((pre, { prop, isMoney, isSummary }, index) => {
|
let str = ''
|
if (
|
isSummary === true ||
|
(typeof isSummary === 'undefined' && isMoney)
|
) {
|
str = list.reduce((listPre, listItem) => {
|
const temp = isNaN(listItem[prop]) ? 0 : Number(listItem[prop])
|
return Number(listPre) + temp
|
}, 0)
|
// str = this.getMoney(Number(str.toFixed(2)))
|
}
|
pre.push(str)
|
return pre
|
}, [])
|
}
|
if (isShowColumn) {
|
result = ['小计', ...result]
|
} else {
|
result[0] = '小计'
|
}
|
return result
|
},
|
// clickButton(info) {
|
// const { prop, row, item } = info
|
// this.$emit('doAction', prop, row, item)
|
// },
|
handleSelectionChange(checkedRecords) {
|
this.$emit('handleSelectionChange', checkedRecords)
|
},
|
handleDisable(checkRow) {
|
const { pageId } = this
|
const { status } = checkRow
|
if (pageId === '110') {
|
if (status === '1' || status === '2') {
|
return true
|
} else {
|
return false
|
}
|
} else {
|
return true
|
}
|
},
|
/**
|
* updateValue 更新表单数据
|
* val 输入的值
|
* item 输入项配置
|
* parentName 输入项父级名称
|
* index 对应表格数据id
|
*/
|
updateValue(val, item, parentName, index) {
|
this.$emit(
|
'updateValue',
|
this.computedValue(val, item),
|
item,
|
parentName,
|
index
|
)
|
},
|
|
validate(valueInfo) {
|
const { header } = this
|
let err = ''
|
const values = Object.keys(valueInfo).reduce((pre, curr) => {
|
const { value = '', rules = [] } = valueInfo[curr]
|
if (rules.length > 0) {
|
const val = this.formatInput(value)
|
pre[curr] = val
|
|
if (!err && rules.length > 0) {
|
rules.forEach(rule => {
|
const tempRule =
|
typeof rule === 'string' ? { [rule]: true } : rule
|
const tempValue = Array.isArray(val) ? val : [val]
|
if (
|
tempRule.required &&
|
tempValue.some(v => String(v).trim() === '')
|
) {
|
const h = header.find(({ prop }) => prop === curr)
|
err = h ? `${h.label}不能为空` : ''
|
}
|
})
|
}
|
}
|
|
return pre
|
}, {})
|
return [err, values]
|
},
|
|
// 统一输出数据格式,如日期格式化
|
formatInput(val) {
|
const { dateFormate } = this
|
if (Array.isArray(val)) {
|
return val.reduce((pre, curr) => {
|
pre.push(this.formatInput(curr))
|
return pre
|
}, [])
|
}
|
return val instanceof Date ? dayjs(val).format(dateFormate) : val
|
},
|
|
// 输入格式错误校验
|
computedValue(val, item) {
|
const { isMoney } = item
|
if (isMoney && typeof val !== 'object') {
|
if (/[,,]/.test(String(val))) {
|
val = String(val).replace(/[,,]/g, '')
|
}
|
// 非数字
|
if (isNaN(val) || Number(val) < 0 || /^0+\d/.test(val)) {
|
return ''
|
}
|
// 去除多余2位小数后的数字
|
if (/\.\d{3,}$/.test(String(val))) {
|
const arr = String(val).split('.')
|
return `${arr[0]}.${arr[1].substring(0, 2)}`
|
}
|
}
|
return val
|
}
|
},
|
computed: {
|
// 序号栏配置
|
mixIndexColumnInfo() {
|
const { defaultIndexColumnInfo, columnIndexInfo = {} } = this
|
if (typeof columnIndexInfo === 'object') {
|
return { ...defaultIndexColumnInfo, ...columnIndexInfo }
|
}
|
return {}
|
},
|
// 是否显示序号栏
|
isShowColumn() {
|
const { mixIndexColumnInfo } = this
|
return Object.keys(mixIndexColumnInfo).length > 0
|
},
|
// 分页配置
|
mixPaginationInfo() {
|
const { defaultPaginationInfo, paginationInfo = {} } = this
|
return { ...defaultPaginationInfo, ...paginationInfo }
|
},
|
showWidth() {
|
const {
|
header,
|
columnWidth,
|
isShowColumn,
|
mixIndexColumnInfo,
|
propsWidth
|
} = this
|
const { width: indexItemWidth } = mixIndexColumnInfo
|
let totalWidth = header.reduce((pre, { label, attrs = {} }) => {
|
const tempWidth = attrs.width
|
? attrs.width
|
: propsWidth[label] || columnWidth
|
if (tempWidth === 'auto' || isNaN(pre)) {
|
pre = '100%'
|
} else {
|
const matchNum = tempWidth.toString().match(/^\d+/)
|
const realWidth = Array.isArray(matchNum) ? parseInt(matchNum[0]) : 0
|
pre = pre + realWidth
|
}
|
|
return pre
|
}, 0)
|
if (totalWidth === 0) {
|
return '100%'
|
}
|
if (isShowColumn) {
|
totalWidth = totalWidth + parseInt(indexItemWidth)
|
}
|
if (isNaN(totalWidth)) {
|
return 'auto'
|
}
|
return totalWidth > 1200 ? '100%' : `${totalWidth + 1}px`
|
},
|
requiredIndexList() {
|
const { list } = this
|
const result = list.reduce((pre, curr) => {
|
Object.keys(curr).forEach((key, index) => {
|
if (
|
!pre.includes(index) &&
|
typeof curr[key] === 'object' &&
|
Array.isArray(curr[key].rules)
|
) {
|
if (
|
curr[key].rules.some(
|
rule =>
|
(typeof rule === 'object' && rule.required) ||
|
rule === 'required'
|
)
|
) {
|
pre.push(index)
|
}
|
}
|
})
|
return pre
|
}, [])
|
return [...result]
|
}
|
}
|
}
|
</script>
|
<style lang="postcss" scoped>
|
.padding-right {
|
padding-right: 40px;
|
}
|
.list-table {
|
& thead {
|
border-radius: 4px 4px 0px 0px;
|
}
|
& >>> .el-table th {
|
background: #fafafa;
|
color: #222222;
|
padding: 0;
|
/* border: none; */
|
border-color: #ebeef5;
|
}
|
& >>> .el-table tr {
|
height: 48px;
|
line-height: 48px;
|
}
|
& >>> .el-table tr th {
|
line-height: 44px;
|
}
|
& >>> .el-table td {
|
color: #666666;
|
border-color: #eee;
|
padding: 0;
|
height: 48px;
|
& .cell {
|
line-height: 18px;
|
}
|
}
|
& a {
|
color: #0081f0;
|
cursor: pointer;
|
}
|
& .table-links {
|
color: #0081f0;
|
& >>> .el-link {
|
margin-right: 20px;
|
&:last-child {
|
margin: 0;
|
}
|
}
|
}
|
& >>> .item-inner p {
|
padding: 0;
|
margin: 0;
|
}
|
& >>> .item-inner p .el-button + .el-button {
|
padding-left: 10px;
|
}
|
& >>> .item-inner .table-buttons .el-button--text:nth-child(1) {
|
margin-right: 20px;
|
}
|
& >>> .item-inner .table-buttons .el-button--text:nth-child(2) {
|
margin-left: 0px;
|
}
|
& >>> .el-table__body-wrapper {
|
&::-webkit-scrollbar {
|
height: 10px;
|
width: 10px;
|
}
|
&::-webkit-scrollbar-track-piece {
|
}
|
&::-webkit-scrollbar-track-piece {
|
}
|
&::-webkit-scrollbar-track {
|
border-radius: 1em;
|
/* background-color: rgba(50, 50, 50, 0.1); */
|
background-color: #ffffff;
|
}
|
&::-webkit-scrollbar-thumb {
|
border-radius: 1em;
|
/* background-color: rgba(50, 50, 50, 0.2); */
|
background-color: rgba(0, 0, 0, 0.5);
|
}
|
}
|
& .pagination {
|
padding: 20px 0;
|
color: #666666;
|
& >>> .el-pagination__total {
|
margin-left: 20px;
|
font-size: 14px;
|
color: #666666;
|
}
|
& >>> .el-pager li {
|
/* width: 32px; */
|
height: 32px;
|
background: rgba(255, 255, 255, 1);
|
border-radius: 4px;
|
border: 1px solid rgba(238, 238, 238, 1);
|
font-size: 14px;
|
color: #666666;
|
font-weight: normal;
|
min-width: 32px;
|
}
|
& >>> .el-pagination__jump {
|
font-size: 14px;
|
color: #666666;
|
}
|
& >>> .btn-next,
|
& >>> .btn-prev {
|
width: 32px;
|
height: 32px;
|
background: rgba(255, 255, 255, 1);
|
border-radius: 4px;
|
border: 1px solid rgba(238, 238, 238, 1);
|
font-size: 14px;
|
color: #666666;
|
}
|
& >>> .btn-next:disabled,
|
& >>> .btn-prev:disabled {
|
opacity: 0.6;
|
}
|
}
|
& .button-select {
|
cursor: pointer;
|
color: #0081f0;
|
}
|
& .button-select-disabled {
|
color: #c5c5c5;
|
/* padding-right: 2em; */
|
}
|
& .table-buttons {
|
display: flex;
|
/* justify-content: space-between; */
|
justify-content: flex-start;
|
align-items: center;
|
/* padding-right: 10px; */
|
& .el-button--text {
|
color: #0081f0;
|
}
|
}
|
& .column-text {
|
/* display: -webkit-box;
|
overflow: hidden;
|
-webkit-line-clamp: 2;
|
text-overflow: ellipsis;
|
-webkit-box-orient: vertical;
|
word-wrap: break-word;
|
word-break: break-all; */
|
}
|
}
|
|
.list-table-content {
|
& .column-input {
|
& .el-date-editor {
|
width: 100%;
|
}
|
& .el-input--small {
|
font-size: 14px;
|
}
|
& .el-select {
|
width: 100%;
|
}
|
}
|
|
& >>> .el-input {
|
width: 100%;
|
}
|
|
& >>> .el-tag--info {
|
max-width: 94%;
|
overflow: hidden;
|
}
|
& >>> .el-select__tags-text {
|
display: inline-block;
|
max-width: 110px;
|
overflow: hidden;
|
white-space: nowrap;
|
text-overflow: ellipsis;
|
}
|
& >>> .el-tag__close {
|
top: -5px;
|
right: -6px;
|
}
|
& >>> .el-form-item__label {
|
color: #888888;
|
}
|
& >>> .el-input__icon {
|
line-height: 32px;
|
}
|
& >>> .el-input__inner {
|
border-color: #eeeeee;
|
color: #222222;
|
height: 32px;
|
line-height: 32px;
|
}
|
& .long-lable >>> .el-form-item__label {
|
line-height: 1.3em;
|
padding-top: 0;
|
}
|
& .textarea {
|
width: 100%;
|
& >>> textarea {
|
height: 100%;
|
}
|
}
|
& .range-separato {
|
width: 10px;
|
display: inline-block;
|
text-align: center;
|
}
|
& .range-input-item {
|
display: inline-block;
|
}
|
}
|
</style>
|