Files
shop-toy/src/pagesBank/dashboard/index.vue

354 lines
8.0 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.

<script lang="ts" setup>
import { useUserStore } from '@/store/user'
import { useBankStore } from '@/store/bank'
definePage({
style: {
navigationBarTitleText: '银行工作台',
},
})
const userStore = useUserStore()
const bankStore = useBankStore()
// 快捷操作
const quickActions = [
{ icon: 'i-carbon-task-approved', label: '待审核', path: '/pagesBank/audit/list' },
{ icon: 'i-carbon-group', label: '客户管理', path: '/pagesBank/customer/list' },
{ icon: 'i-carbon-calendar', label: '拜访计划', path: '/pagesBank/visit/list' },
{ icon: 'i-carbon-add', label: '创建拜访', path: '/pagesBank/visit/create' },
{ icon: 'i-carbon-settings', label: '设置', path: '/pagesBank/me/index' },
]
function handleAction(path: string) {
if (!path) {
uni.showToast({ title: '功能开发中', icon: 'none' })
return
}
uni.navigateTo({ url: path })
}
onMounted(() => {
bankStore.fetchStats()
})
</script>
<template>
<view class="dashboard-page">
<view class="header-bg"></view>
<!-- 头部欢迎 -->
<view class="header-content">
<view class="welcome">
<text class="greeting">您好{{ userStore.userInfo?.nickname || '银行管理员' }}</text>
<text class="sub-text">欢迎回到银行端管理系统</text>
</view>
</view>
<!-- 关键指标卡片 -->
<view class="stats-overview">
<view class="total-amount-card">
<text class="label">累计放款金额 ()</text>
<view class="amount-box">
<text class="unit">¥</text>
<text class="value">{{ (bankStore.stats?.totalLoanAmount || 0).toLocaleString() }}</text>
</view>
</view>
<view class="stats-grid">
<view class="stat-card" @click="handleAction('/pagesBank/audit/list')">
<view class="stat-info">
<text class="stat-value warning">{{ bankStore.stats?.pendingAuditWithdraw || 0 }}</text>
<text class="stat-label">待审核</text>
</view>
<view class="stat-icon warning">
<text class="i-carbon-wallet"></text>
</view>
</view>
<view class="stat-card">
<view class="stat-info">
<text class="stat-value success">{{ bankStore.stats?.todayApprovedCount || 0 }}</text>
<text class="stat-label">今日审批</text>
</view>
<view class="stat-icon success">
<text class="i-carbon-checkmark-outline"></text>
</view>
</view>
<view class="stat-card" @click="handleAction('/pagesBank/customer/list')">
<view class="stat-info">
<text class="stat-value">{{ bankStore.stats?.activeCustomerCount || 0 }}</text>
<text class="stat-label">活跃用户</text>
</view>
<view class="stat-icon">
<text class="i-carbon-user-activity"></text>
</view>
</view>
<view class="stat-card">
<view class="stat-info">
<text class="stat-value">{{ bankStore.stats?.pendingAuditStore || 0 }}</text>
<text class="stat-label">待审入驻</text>
</view>
<view class="stat-icon">
<text class="i-carbon-store"></text>
</view>
</view>
</view>
</view>
<!-- 快捷操作 -->
<view class="section">
<view class="section-header">
<text class="section-title">快捷操作</text>
</view>
<view class="quick-actions">
<view
v-for="item in quickActions"
:key="item.label"
class="action-item"
@click="handleAction(item.path)"
>
<view class="action-icon">
<text :class="item.icon"></text>
</view>
<text class="action-label">{{ item.label }}</text>
</view>
</view>
</view>
<!-- 最近动态 (Placeholder) -->
<view class="section">
<view class="section-header">
<text class="section-title">最近动态</text>
<text class="more">更多 ></text>
</view>
<view class="empty-dynamic">
<text class="i-carbon-reminder-attendance"></text>
<text>暂无新的审核动态</text>
</view>
</view>
</view>
</template>
<style lang="scss" scoped>
.dashboard-page {
min-height: 100vh;
background: #f8f9fa;
padding-bottom: 40rpx;
}
.header-bg {
position: absolute;
top: 0;
left: 0;
right: 0;
height: 480rpx; /* 稍微增高一点以容纳更多内容 */
background: linear-gradient(135deg, #00c05a 0%, #34d19d 100%);
border-bottom-left-radius: 40rpx;
border-bottom-right-radius: 40rpx;
z-index: 0;
}
.header-content {
position: relative;
padding: 60rpx 40rpx 20rpx;
z-index: 1;
.welcome {
color: #fff;
.greeting {
font-size: 40rpx;
font-weight: 700;
display: block;
margin-bottom: 12rpx;
}
.sub-text {
font-size: 26rpx;
opacity: 0.9;
}
}
}
.stats-overview {
position: relative;
margin: 0 30rpx;
z-index: 1;
.total-amount-card {
background: #fff;
border-radius: 24rpx;
padding: 40rpx;
box-shadow: 0 8rpx 30rpx rgba(0, 0, 0, 0.05);
margin-bottom: 24rpx;
.label {
font-size: 26rpx;
color: #999;
display: block;
margin-bottom: 16rpx;
}
.amount-box {
display: flex;
align-items: baseline;
.unit {
font-size: 32rpx;
font-weight: 600;
color: #333;
margin-right: 8rpx;
}
.value {
font-size: 56rpx;
font-weight: 700;
color: #333;
}
}
}
}
.stats-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 20rpx;
.stat-card {
background: #fff;
border-radius: 20rpx;
padding: 30rpx;
display: flex;
justify-content: space-between;
align-items: center;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.03);
.stat-info {
.stat-value {
font-size: 36rpx;
font-weight: 700;
color: #333;
display: block;
margin-bottom: 4rpx;
&.warning { color: #ff8f0d; }
&.success { color: #00c05a; }
}
.stat-label {
font-size: 24rpx;
color: #999;
}
}
.stat-icon {
width: 72rpx;
height: 72rpx;
border-radius: 16rpx;
background: #f5f5f5;
display: flex;
align-items: center;
justify-content: center;
text {
font-size: 36rpx;
color: #666;
}
&.warning {
background: rgba(255, 143, 13, 0.1);
text { color: #ff8f0d; }
}
&.success {
background: rgba(0, 192, 90, 0.1);
text { color: #00c05a; }
}
}
}
}
.section {
margin: 30rpx;
background: #fff;
border-radius: 24rpx;
padding: 30rpx;
box-shadow: 0 4rpx 20rpx rgba(0, 0, 0, 0.02);
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 30rpx;
.section-title {
font-size: 32rpx;
font-weight: 700;
color: #333;
}
.more {
font-size: 24rpx;
color: #999;
}
}
}
.quick-actions {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 20rpx;
.action-item {
display: flex;
flex-direction: column;
align-items: center;
gap: 16rpx;
.action-icon {
width: 96rpx;
height: 96rpx;
background: #f8f9fa;
border-radius: 24rpx;
display: flex;
align-items: center;
justify-content: center;
transition: all 0.2s;
text {
font-size: 44rpx;
color: #00c05a;
}
&:active {
background: #e9ecef;
transform: scale(0.95);
}
}
.action-label {
font-size: 24rpx;
color: #495057;
}
}
}
.empty-dynamic {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
padding: 40rpx 0;
color: #adb5bd;
gap: 16rpx;
text:first-child {
font-size: 64rpx;
}
text:last-child {
font-size: 26rpx;
}
}
</style>