461 lines
10 KiB
Vue
461 lines
10 KiB
Vue
<script lang="ts" setup>
|
||
import { downloadReport } from '@/pagesBank/api'
|
||
import { DateDimension } from '@/typings/bank'
|
||
|
||
definePage({
|
||
style: {
|
||
navigationBarTitleText: '报表下载',
|
||
},
|
||
})
|
||
|
||
// 从路由参数获取报表信息
|
||
const reportId = ref('')
|
||
const reportName = ref('')
|
||
|
||
// 日期维度选项
|
||
const dimensionOptions = [
|
||
{ label: '按日', value: DateDimension.DAY },
|
||
{ label: '按月', value: DateDimension.MONTH },
|
||
{ label: '按季', value: DateDimension.QUARTER },
|
||
{ label: '自定义', value: DateDimension.CUSTOM },
|
||
]
|
||
|
||
// 当前选中的日期维度
|
||
const activeDimension = ref(DateDimension.DAY)
|
||
|
||
// 当前选中的日期
|
||
const selectedDate = ref('2025-12-25')
|
||
|
||
// 日期选择器显示状态
|
||
const showDatePicker = ref(false)
|
||
|
||
// 下载中状态
|
||
const downloading = ref(false)
|
||
|
||
// 获取日期维度标签
|
||
function getDimensionLabel(dimension: DateDimension) {
|
||
const option = dimensionOptions.find(opt => opt.value === dimension)
|
||
return option?.label || ''
|
||
}
|
||
|
||
// 切换日期维度
|
||
function handleDimensionChange(dimension: DateDimension) {
|
||
activeDimension.value = dimension
|
||
// 根据维度更新默认日期
|
||
updateDefaultDate(dimension)
|
||
}
|
||
|
||
// 根据维度更新默认日期
|
||
function updateDefaultDate(dimension: DateDimension) {
|
||
const now = new Date()
|
||
const year = now.getFullYear()
|
||
const month = String(now.getMonth() + 1).padStart(2, '0')
|
||
const day = String(now.getDate()).padStart(2, '0')
|
||
|
||
switch (dimension) {
|
||
case DateDimension.DAY:
|
||
selectedDate.value = `${year}-${month}-${day}`
|
||
break
|
||
case DateDimension.MONTH:
|
||
selectedDate.value = `${year}-${month}`
|
||
break
|
||
case DateDimension.QUARTER:
|
||
const quarter = Math.floor(now.getMonth() / 3) + 1
|
||
selectedDate.value = `${year}-Q${quarter}`
|
||
break
|
||
case DateDimension.CUSTOM:
|
||
selectedDate.value = `${year}-${month}-${day}`
|
||
break
|
||
}
|
||
}
|
||
|
||
// 显示日期选择器
|
||
function showDateSelector() {
|
||
showDatePicker.value = true
|
||
}
|
||
|
||
// 日期选择确认
|
||
function handleDateConfirm(e: any) {
|
||
const { value } = e
|
||
const date = new Date(value)
|
||
const year = date.getFullYear()
|
||
const month = String(date.getMonth() + 1).padStart(2, '0')
|
||
const day = String(date.getDate()).padStart(2, '0')
|
||
|
||
if (activeDimension.value === DateDimension.MONTH) {
|
||
selectedDate.value = `${year}-${month}`
|
||
} else {
|
||
selectedDate.value = `${year}-${month}-${day}`
|
||
}
|
||
|
||
showDatePicker.value = false
|
||
}
|
||
|
||
// 下载报表
|
||
async function handleDownload() {
|
||
if (downloading.value) return
|
||
|
||
downloading.value = true
|
||
try {
|
||
await downloadReport({
|
||
reportId: reportId.value,
|
||
dimension: activeDimension.value,
|
||
date: selectedDate.value
|
||
})
|
||
|
||
uni.showToast({
|
||
title: '下载成功',
|
||
icon: 'success'
|
||
})
|
||
} catch (error) {
|
||
uni.showToast({
|
||
title: '下载失败',
|
||
icon: 'none'
|
||
})
|
||
} finally {
|
||
downloading.value = false
|
||
}
|
||
}
|
||
|
||
onLoad((options: any) => {
|
||
if (options.reportId) {
|
||
reportId.value = options.reportId
|
||
}
|
||
if (options.reportName) {
|
||
reportName.value = decodeURIComponent(options.reportName)
|
||
}
|
||
})
|
||
</script>
|
||
|
||
<template>
|
||
<view class="download-page">
|
||
<!-- 报表信息卡片 -->
|
||
<view class="report-info-card">
|
||
<view class="report-icon">
|
||
<text class="i-carbon-document"></text>
|
||
</view>
|
||
<view class="report-details">
|
||
<text class="report-name">{{ reportName }}</text>
|
||
<text class="report-id">报表编号: {{ reportId }}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 日期维度筛选 -->
|
||
<view class="dimension-section">
|
||
<view class="section-title">选择日期维度</view>
|
||
<view class="dimension-tabs">
|
||
<view
|
||
v-for="option in dimensionOptions"
|
||
:key="option.value"
|
||
class="dimension-tab"
|
||
:class="{ active: activeDimension === option.value }"
|
||
@click="handleDimensionChange(option.value)"
|
||
>
|
||
{{ option.label }}
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 日期选择 -->
|
||
<view class="date-section">
|
||
<view class="section-title">选择日期</view>
|
||
<view class="date-picker" @click="showDateSelector">
|
||
<view class="date-display">
|
||
<text class="i-carbon-calendar"></text>
|
||
<text class="date-value">{{ selectedDate }}</text>
|
||
</view>
|
||
<text class="i-carbon-chevron-right"></text>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 下载区域 -->
|
||
<view class="download-section">
|
||
<view class="format-tag">EXCEL</view>
|
||
<button
|
||
class="download-btn"
|
||
:class="{ loading: downloading }"
|
||
:disabled="downloading"
|
||
@click="handleDownload"
|
||
>
|
||
<text v-if="downloading" class="i-carbon-circle-dash loading-icon"></text>
|
||
<text>{{ downloading ? '下载中...' : '点击下载' }}</text>
|
||
</button>
|
||
</view>
|
||
|
||
<!-- 使用帮助 -->
|
||
<view class="help-section">
|
||
<view class="help-title">
|
||
<text class="i-carbon-help"></text>
|
||
<text>Excel格式: 使用帮助</text>
|
||
</view>
|
||
<view class="help-content">
|
||
<view class="help-item">
|
||
<text class="help-number">1</text>
|
||
<text class="help-text">选择要下载报表的日期</text>
|
||
</view>
|
||
<view class="help-item">
|
||
<text class="help-number">2</text>
|
||
<text class="help-text">点击下载按钮进行下载</text>
|
||
</view>
|
||
<view class="help-item">
|
||
<text class="help-number">3</text>
|
||
<text class="help-text">下载后自动打开文件,可以点击手机右上角的【...】进行转发或保存文件</text>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
|
||
<!-- 日期选择器弹窗 -->
|
||
<wd-datetime-picker
|
||
v-model="selectedDate"
|
||
v-model:show="showDatePicker"
|
||
type="date"
|
||
@confirm="handleDateConfirm"
|
||
@cancel="showDatePicker = false"
|
||
/>
|
||
</view>
|
||
</template>
|
||
|
||
<style lang="scss" scoped>
|
||
.download-page {
|
||
min-height: 100vh;
|
||
background: #f8f9fa;
|
||
padding: 30rpx;
|
||
}
|
||
|
||
.report-info-card {
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 30rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 24rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.02);
|
||
|
||
.report-icon {
|
||
width: 96rpx;
|
||
height: 96rpx;
|
||
background: linear-gradient(135deg, #00c05a 0%, #34d19d 100%);
|
||
border-radius: 20rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
|
||
text {
|
||
font-size: 48rpx;
|
||
color: #fff;
|
||
}
|
||
}
|
||
|
||
.report-details {
|
||
flex: 1;
|
||
|
||
.report-name {
|
||
font-size: 32rpx;
|
||
font-weight: 700;
|
||
color: #333;
|
||
display: block;
|
||
margin-bottom: 8rpx;
|
||
}
|
||
|
||
.report-id {
|
||
font-size: 24rpx;
|
||
color: #999;
|
||
}
|
||
}
|
||
}
|
||
|
||
.dimension-section,
|
||
.date-section {
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 30rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.02);
|
||
}
|
||
|
||
.section-title {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
margin-bottom: 24rpx;
|
||
}
|
||
|
||
.dimension-tabs {
|
||
display: flex;
|
||
gap: 16rpx;
|
||
|
||
.dimension-tab {
|
||
flex: 1;
|
||
height: 72rpx;
|
||
background: #f8f9fa;
|
||
border-radius: 12rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
transition: all 0.2s;
|
||
|
||
&.active {
|
||
background: #00c05a;
|
||
color: #fff;
|
||
font-weight: 600;
|
||
}
|
||
}
|
||
}
|
||
|
||
.date-picker {
|
||
display: flex;
|
||
justify-content: space-between;
|
||
align-items: center;
|
||
padding: 24rpx;
|
||
background: #f8f9fa;
|
||
border-radius: 16rpx;
|
||
|
||
.date-display {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 16rpx;
|
||
|
||
text:first-child {
|
||
font-size: 36rpx;
|
||
color: #00c05a;
|
||
}
|
||
|
||
.date-value {
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
}
|
||
|
||
text:last-child {
|
||
font-size: 28rpx;
|
||
color: #adb5bd;
|
||
}
|
||
}
|
||
|
||
.download-section {
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 40rpx 30rpx;
|
||
margin-bottom: 24rpx;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.02);
|
||
display: flex;
|
||
flex-direction: column;
|
||
align-items: center;
|
||
gap: 30rpx;
|
||
|
||
.format-tag {
|
||
font-size: 24rpx;
|
||
color: #00c05a;
|
||
background: rgba(0, 192, 90, 0.1);
|
||
padding: 8rpx 24rpx;
|
||
border-radius: 8rpx;
|
||
font-weight: 600;
|
||
}
|
||
|
||
.download-btn {
|
||
width: 100%;
|
||
height: 96rpx;
|
||
background: linear-gradient(135deg, #00c05a 0%, #34d19d 100%);
|
||
border-radius: 16rpx;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
gap: 12rpx;
|
||
font-size: 32rpx;
|
||
font-weight: 600;
|
||
color: #fff;
|
||
border: none;
|
||
transition: all 0.2s;
|
||
|
||
&:active:not(:disabled) {
|
||
opacity: 0.8;
|
||
transform: scale(0.98);
|
||
}
|
||
|
||
&:disabled {
|
||
opacity: 0.6;
|
||
}
|
||
|
||
&.loading {
|
||
opacity: 0.8;
|
||
}
|
||
|
||
.loading-icon {
|
||
font-size: 32rpx;
|
||
animation: spin 1s linear infinite;
|
||
}
|
||
}
|
||
}
|
||
|
||
@keyframes spin {
|
||
from {
|
||
transform: rotate(0deg);
|
||
}
|
||
to {
|
||
transform: rotate(360deg);
|
||
}
|
||
}
|
||
|
||
.help-section {
|
||
background: #fff;
|
||
border-radius: 24rpx;
|
||
padding: 30rpx;
|
||
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.02);
|
||
|
||
.help-title {
|
||
display: flex;
|
||
align-items: center;
|
||
gap: 12rpx;
|
||
margin-bottom: 24rpx;
|
||
|
||
text:first-child {
|
||
font-size: 32rpx;
|
||
color: #4d80f0;
|
||
}
|
||
|
||
text:last-child {
|
||
font-size: 28rpx;
|
||
font-weight: 600;
|
||
color: #333;
|
||
}
|
||
}
|
||
|
||
.help-content {
|
||
.help-item {
|
||
display: flex;
|
||
align-items: flex-start;
|
||
gap: 16rpx;
|
||
margin-bottom: 20rpx;
|
||
|
||
&:last-child {
|
||
margin-bottom: 0;
|
||
}
|
||
|
||
.help-number {
|
||
width: 40rpx;
|
||
height: 40rpx;
|
||
background: #4d80f0;
|
||
color: #fff;
|
||
border-radius: 50%;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
font-size: 22rpx;
|
||
font-weight: 600;
|
||
flex-shrink: 0;
|
||
}
|
||
|
||
.help-text {
|
||
flex: 1;
|
||
font-size: 26rpx;
|
||
color: #666;
|
||
line-height: 1.6;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style> |