Files
nuttyreading-master-html/src/views/modules/statisticsBusiness/vipStatistics/expiresStatisticsBase.vue
chenghuan f51dfda073 style(统计业务): 优化VIP统计页面表格样式和布局
- 为所有VIP统计页面的表格添加了统一的类名以便于样式管理
- 调整表格的最小高度,确保在不同数据情况下的显示效果
- 修改统计卡片的布局,采用flex布局以提高响应式表现
- 移除不必要的overflow属性,简化样式结构
2026-03-17 15:32:47 +08:00

294 lines
7.5 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<template>
<div class="vip-expires-statistics" v-loading="loading">
<div class="summary-section">
<div class="section-title">汇总统计</div>
<div class="summary-grid">
<div
v-for="item in summaryCards"
:key="item.key"
class="summary-card"
>
<div class="summary-card__label">{{ item.label }}</div>
<div class="summary-card__value">{{ item.value }}</div>
</div>
</div>
</div>
<div class="detail-section">
<div class="detail-header">
<div class="detail-title">{{ detailTitle }}</div>
<el-button
type="success"
size="small"
:loading="exportLoading"
@click="exportData"
>下载报表</el-button>
</div>
<div ref="tableContainer" class="table-container">
<el-table
class="statistics-table"
:data="dataList"
border
:header-cell-style="{ textAlign: 'center', padding: '6px 0' }"
:cell-style="{ textAlign: 'center', padding: '6px 0' }"
:max-height="tableHeight"
>
<el-table-column type="index" label="序号" width="70" />
<el-table-column prop="time" label="办理时间" min-width="140" />
<el-table-column prop="name" label="姓名" min-width="120">
<template slot-scope="scope">
{{ scope.row.name || '--' }}
</template>
</el-table-column>
<el-table-column prop="tel" label="注册电话" min-width="140" />
<el-table-column prop="vipType" label="VIP类型" min-width="160" />
<el-table-column prop="year" label="年限" min-width="100">
<template slot-scope="scope">
{{ formatYear(scope.row.year) }}
</template>
</el-table-column>
<el-table-column prop="price" label="缴费金额" min-width="120">
<template slot-scope="scope">
{{ formatAmount(scope.row.price) }}
</template>
</el-table-column>
<el-table-column prop="endTime" label="到期时间" min-width="140" />
</el-table>
</div>
</div>
</div>
</template>
<script>
import http from '@/utils/httpRequest'
export default {
props: {
title: {
type: String,
required: true
},
month: {
type: [String, Number],
required: true
}
},
data() {
return {
loading: false,
exportLoading: false,
tableHeight: null,
dataList: [],
summaryData: {
total: 0,
zyCount: 0,
zjcount: 0,
zxhtCount: 0,
zlcount: 0,
xlCount: 0,
yxSuperCount: 0,
gxSuperCount: 0
}
}
},
computed: {
detailTitle() {
return `${this.title}明细(${this.summaryData.total || 0}`
},
summaryCards() {
return [
{ key: 'total', label: '总人数', value: this.summaryData.total },
{ key: 'zyCount', label: '中医学', value: this.summaryData.zyCount },
{ key: 'zjcount', label: '针灸学', value: this.summaryData.zjcount },
{ key: 'zxhtCount', label: '中西汇通学', value: this.summaryData.zxhtCount },
{ key: 'zlcount', label: '肿瘤学', value: this.summaryData.zlcount },
{ key: 'xlCount', label: '心理学', value: this.summaryData.xlCount },
{ key: 'yxSuperCount', label: '医学超级', value: this.summaryData.yxSuperCount },
{ key: 'gxSuperCount', label: '国学心理学超级', value: this.summaryData.gxSuperCount }
]
}
},
activated() {
this.getDataList()
this.$nextTick(() => {
this.calculateTableHeight()
})
},
mounted() {
window.addEventListener('resize', this.handleResize)
this.$nextTick(() => {
this.calculateTableHeight()
})
},
beforeDestroy() {
window.removeEventListener('resize', this.handleResize)
},
methods: {
handleResize() {
this.calculateTableHeight()
},
calculateTableHeight() {
if (this.$refs.tableContainer) {
this.tableHeight = this.$refs.tableContainer.offsetHeight || 500
} else {
this.tableHeight = 500
}
},
getRequestData() {
return {
month: String(this.month)
}
},
getDataList() {
this.loading = true
http({
url: http.adornUrl('/master/statisticsBusinessVip/getExpiresByMonth'),
method: 'post',
data: http.adornData(this.getRequestData())
}).then(({ data }) => {
if (data && data.code === 0) {
const countData = data.count || {}
this.dataList = data.resultList || []
this.summaryData = {
total: data.total || 0,
zyCount: countData.zyCount || 0,
zjcount: countData.zjCount || countData.zjcount || 0,
zxhtCount: countData.zxhtCount || 0,
zlcount: countData.zlCount || countData.zlcount || 0,
xlCount: countData.xlCount || 0,
yxSuperCount: countData.yxSuperCount || 0,
gxSuperCount: countData.gxSuperCount || 0
}
this.$nextTick(() => {
this.calculateTableHeight()
})
}
}).finally(() => {
this.loading = false
})
},
exportData() {
this.exportLoading = true
http({
url: http.adornUrl('/master/statisticsBusinessVip/exportExpiresByMonth'),
method: 'post',
data: http.adornData(this.getRequestData()),
responseType: 'blob'
}).then((response) => {
const blob = new Blob([response.data])
const link = document.createElement('a')
link.href = URL.createObjectURL(blob)
link.download = `${this.title}VIP统计报表.xlsx`
link.click()
URL.revokeObjectURL(link.href)
}).finally(() => {
this.exportLoading = false
})
},
formatYear(year) {
if (year === '' || year === null || year === undefined) {
return '--'
}
return `${year}`
},
formatAmount(amount) {
if (amount === '' || amount === null || amount === undefined) {
return '--'
}
return Number(amount).toFixed(2).replace(/\.00$/, '')
}
}
}
</script>
<style scoped lang="less">
/deep/ .el-table .cell,
/deep/ .el-table th > .cell {
padding-top: 4px;
padding-bottom: 4px;
line-height: 20px;
}
/deep/ .statistics-table {
min-height: 500px;
}
/deep/ .statistics-table .el-table__body-wrapper,
/deep/ .statistics-table .el-table__empty-block {
min-height: 452px;
}
.vip-expires-statistics {
display: flex;
flex-direction: column;
gap: 8px;
}
.summary-section,
.detail-section {
background: #fff;
border-radius: 4px;
padding: 8px;
}
.detail-section {
display: flex;
flex: 1;
flex-direction: column;
}
.section-title {
margin-bottom: 16px;
font-size: 16px;
font-weight: 700;
color: #303133;
}
.summary-grid {
display: flex;
flex-wrap: wrap;
gap: 12px;
}
.summary-card {
flex: 1 1 120px;
width: 120px;
min-width: 120px;
padding: 16px;
border: 1px solid #ebeef5;
border-radius: 8px;
background: linear-gradient(180deg, #f7fbff 0%, #ffffff 100%);
box-shadow: 0 4px 12px rgba(31, 45, 61, 0.06);
}
.summary-card__label {
margin-bottom: 8px;
font-size: 14px;
color: #606266;
}
.summary-card__value {
font-size: 24px;
font-weight: 700;
color: #1f2d3d;
}
.detail-header {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 16px;
}
.detail-title {
font-size: 16px;
font-weight: 700;
color: #303133;
}
.table-container {
flex: 1;
}
</style>