Files
l2-g30/src/views/l2/report/components/body.vue
砂糖 48001db94a style(components): 调整浮动面板的z-index并移除body.vue中多余的元素
移除body.vue中未使用的概览栏元素,同时调整FloatingPanel的z-index值以避免可能的层叠冲突
2026-01-03 09:46:47 +08:00

275 lines
5.8 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="report-body">
<!-- Action row / 操作行 -->
<div class="report-actions">
<el-button type="primary" @click="exportReport" icon="el-icon-download" size="small">Export Report</el-button>
<!-- 导出报表 -->
</div>
<h1 class="report-body-title">Overview Data</h1>
<!-- 总览数据 -->
<div class="summary-cards" v-if="summary.length > 0">
<div v-for="(item, index) in summary" :key="index">
<span class="card-title">{{ item.label }}</span>
<span class="card-value">{{ item.value }}</span>
</div>
</div>
<div class="table-container">
<div v-if="dataset.length" class="excel-table-wrapper">
<table class="excel-table">
<thead>
<tr>
<th v-for="(item, index) in columns" :key="index">
{{ item.label }}
</th>
</tr>
</thead>
<tbody>
<tr v-for="(row, rowIndex) in dataset" :key="rowIndex">
<td v-for="(column, colIndex) in columns" :key="colIndex">
{{ formatCell(row[column.prop]) }}
</td>
</tr>
</tbody>
</table>
</div>
<el-empty v-else description="No data" />
<!-- 暂无数据 -->
</div>
</div>
</template>
<script>
import * as XLSX from 'xlsx';
export default {
name: 'ReportBody',
props: {
title: {
type: String,
required: true
},
summary: {
type: Array,
required: true
},
dataset: {
type: Array,
required: true
},
columns: {
type: Array,
required: true
},
overviewInfo: {
type: Object,
default: () => ({
reportLabel: '',
rangeText: ''
})
}
},
methods: {
formatCell(value) {
if (value === null || value === undefined || value === '') {
return '-'
}
return value
},
exportReport() {
// Create workbook / 创建工作簿
const workbook = XLSX.utils.book_new();
// Prepare export data array / 准备导出数据数组
const exportData = [];
// Process table data, ensure export in order and labels defined by columns / 处理表格数据确保按columns定义的顺序和标签导出
const tableData = this.dataset.map(row => {
const formattedRow = {};
this.columns.forEach(col => {
formattedRow[col.label] = row[col.prop];
});
return formattedRow;
});
// Add table data / 添加表格数据
exportData.push(...tableData);
// Create worksheet / 创建工作表
const worksheet = XLSX.utils.json_to_sheet(exportData);
// Adjust column width / 调整列宽
const columnWidths = this.columns.map(col => ({ wch: Math.max(col.label.length * 1.5, 10) }));
worksheet['!cols'] = columnWidths;
// Add worksheet to workbook / 添加工作表到工作簿
XLSX.utils.book_append_sheet(workbook, worksheet, 'Report Data'); // 报表数据
// Generate file name / 生成文件名
const exportFileName = this.fileName || `${this.title.replace(/[\\/*?:"<>|]/g, '')}_${new Date().toLocaleDateString()}.xlsx`;
// Export file / 导出文件
XLSX.writeFile(workbook, exportFileName);
}
}
}
</script>
<style lang="scss" scoped>
.report-body {
height: 100%;
display: flex;
flex-direction: column;
background: #ffffff;
border: 1px solid #d4d4d4;
border-radius: 2px;
padding: 15px;
overflow: hidden;
}
.report-actions {
margin-bottom: 15px;
display: flex;
justify-content: flex-end;
}
.overview-bar {
display: flex;
justify-content: space-between;
align-items: center;
padding: 12px 15px;
background: #f9f9f9;
border: 1px solid #e0e0e0;
border-radius: 2px;
margin-bottom: 15px;
.overview-left {
display: flex;
flex-direction: column;
.overview-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin-bottom: 6px;
}
.overview-meta {
font-size: 13px;
color: #555;
span {
margin-right: 15px;
}
}
}
}
.report-body-title {
font-size: 18px;
font-weight: 600;
color: #333;
margin: 10px 0 20px 0;
padding-bottom: 10px;
border-bottom: 2px solid #e0e0e0;
}
.summary-cards {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 12px;
margin-bottom: 20px;
padding: 15px;
background: #f8f8f8;
border: 1px solid #e0e0e0;
border-radius: 2px;
> div {
display: flex;
flex-direction: column;
padding: 10px;
background: #ffffff;
border: 1px solid #e0e0e0;
border-radius: 2px;
}
}
.card-title {
font-size: 12px;
color: #666;
margin-bottom: 8px;
font-weight: 500;
}
.card-value {
font-size: 18px;
font-weight: 600;
color: #333;
}
.card-unit {
font-size: 11px;
color: #999;
}
.table-container {
flex: 1;
min-height: 0;
overflow: auto;
background: #ffffff;
border: 1px solid #e0e0e0;
border-radius: 2px;
padding: 0 10px 10px;
&::-webkit-scrollbar {
width: 6px;
height: 6px;
}
&::-webkit-scrollbar-thumb {
background: #c0c0c0;
border-radius: 3px;
}
&::-webkit-scrollbar-track {
background: #f0f0f0;
}
}
.excel-table-wrapper {
min-width: 100%;
overflow: auto;
}
.excel-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
color: #333;
table-layout: fixed;
thead th {
background: #f5f5f5;
font-weight: 600;
text-align: center;
padding: 8px;
border: 1px solid #dcdcdc;
}
tbody td {
border: 1px solid #e4e4e4;
padding: 8px;
text-align: center;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
tbody tr:nth-child(even) {
background: #fafafa;
}
tbody tr:hover {
background: #f0f6ff;
}
}
</style>