Files
shop-toy/src/pagesBank/report/list.vue
2025-12-25 17:18:12 +08:00

217 lines
4.5 KiB
Vue

<script lang="ts" setup>
import { getReportList } from '@/pagesBank/api'
import type { ReportType } from '@/typings/bank'
import { ReportCategory } from '@/typings/bank'
import { reportCategoryInfo } from '@/pagesBank/mock'
// i-carbon-chart-cluster-bar
// i-carbon-user-multiple
// i-carbon-ibm-watson-natural-language-understanding
// i-carbon-gift
definePage({
style: {
navigationBarTitleText: '报表下载',
},
})
const reports = ref<ReportType[]>([])
const loading = ref(false)
// 按分类分组报表
const groupedReports = computed(() => {
const groups: Record<string, ReportType[]> = {}
reports.value.forEach(report => {
if (!groups[report.category]) {
groups[report.category] = []
}
groups[report.category].push(report)
})
return groups
})
// 获取分类信息
function getCategoryInfo(category: ReportCategory) {
return reportCategoryInfo[category] || { name: '未知', icon: '', color: '#999' }
}
// 点击报表跳转到下载页
function handleReportClick(report: ReportType) {
uni.navigateTo({
url: `/pagesBank/report/download?reportId=${report.id}&reportName=${encodeURIComponent(report.name)}`
})
}
async function loadData() {
loading.value = true
try {
const res = await getReportList()
reports.value = res
} finally {
loading.value = false
}
}
onMounted(() => {
loadData()
})
</script>
<template>
<view class="report-list-page">
<view v-if="loading && reports.length === 0" class="loading-state">
<text>加载中...</text>
</view>
<view v-else class="report-container">
<view
v-for="(groupReports, category) in groupedReports"
:key="category"
class="report-category"
>
<view class="category-header">
<view class="category-info">
<text :class="['category-icon', getCategoryInfo(category as ReportCategory).icon]"></text>
<text class="category-name">{{ getCategoryInfo(category as ReportCategory).name }}</text>
</view>
<view class="category-count">{{ groupReports.length }} 个报表</view>
</view>
<view class="report-grid">
<view
v-for="report in groupReports"
:key="report.id"
class="report-item"
@click="handleReportClick(report)"
>
<view class="report-icon">
<text :class="getCategoryInfo(report.category).icon"></text>
</view>
<text class="report-name">{{ report.name }}</text>
<view class="report-arrow">
<text class="i-carbon-chevron-right"></text>
</view>
</view>
</view>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.report-list-page {
min-height: 100vh;
background: #f8f9fa;
padding-bottom: 30rpx;
}
.loading-state {
display: flex;
align-items: center;
justify-content: center;
padding: 100rpx 0;
color: #adb5bd;
text {
font-size: 28rpx;
}
}
.report-container {
padding: 24rpx 30rpx;
}
.report-category {
background: #fff;
border-radius: 24rpx;
padding: 30rpx;
margin-bottom: 24rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.02);
}
.category-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24rpx;
padding-bottom: 20rpx;
border-bottom: 1rpx solid #f1f3f5;
.category-info {
display: flex;
align-items: center;
gap: 16rpx;
.category-icon {
font-size: 36rpx;
color: #00c05a;
}
.category-name {
font-size: 32rpx;
font-weight: 700;
color: #333;
}
}
.category-count {
font-size: 24rpx;
color: #999;
}
}
.report-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 20rpx;
}
.report-item {
background: #f8f9fa;
border-radius: 16rpx;
padding: 30rpx 24rpx;
display: flex;
flex-direction: column;
align-items: center;
gap: 16rpx;
position: relative;
transition: all 0.2s;
&:active {
background: #e9ecef;
transform: scale(0.98);
}
.report-icon {
width: 80rpx;
height: 80rpx;
background: #fff;
border-radius: 16rpx;
display: flex;
align-items: center;
justify-content: center;
text {
font-size: 40rpx;
color: #00c05a;
}
}
.report-name {
font-size: 26rpx;
color: #333;
text-align: center;
font-weight: 500;
}
.report-arrow {
position: absolute;
top: 20rpx;
right: 20rpx;
text {
font-size: 24rpx;
color: #adb5bd;
}
}
}
</style>