feat: 完善接口19-顶部通知铃铛与站内通知中心
All checks were successful
构建并部署前端到测试环境 / build-and-deploy (push) Successful in 4m5s

This commit is contained in:
luo
2026-07-25 10:20:53 +08:00
parent eb13763020
commit 9289a6e940
37 changed files with 1264 additions and 226 deletions

View File

@@ -1,6 +1,6 @@
<template>
<div class="console">
开发中敬请期待...
<ExpiringAssetStats />
<!--<CardList></CardList>-->
<!--<el-row :gutter="20">-->
@@ -29,13 +29,7 @@
</template>
<script setup lang="ts">
import CardList from './widget/CardList.vue'
import ActiveUser from './widget/ActiveUser.vue'
import SalesOverview from './widget/SalesOverview.vue'
import NewUser from './widget/NewUser.vue'
import Dynamic from './widget/Dynamic.vue'
import TodoList from './widget/TodoList.vue'
import AboutProject from './widget/AboutProject.vue'
import ExpiringAssetStats from './widget/ExpiringAssetStats.vue'
import { useCommon } from '@/composables/useCommon'
defineOptions({ name: 'Console' })

View File

@@ -0,0 +1,102 @@
<template>
<ElCard shadow="never" class="expiring-asset-stats">
<template #header>
<div class="card-header">
<span>临期资产</span>
<ElButton link type="primary" @click="() => goToList()">查看列表</ElButton>
</div>
</template>
<div class="stats-grid">
<div class="stat-item stat-item--card" @click="() => goToList('card')">
<div class="stat-label">临期网卡</div>
<div class="stat-value">{{ counts.card.toLocaleString() }}</div>
</div>
<div class="stat-item stat-item--device" @click="() => goToList('device')">
<div class="stat-label">临期设备</div>
<div class="stat-value">{{ counts.device.toLocaleString() }}</div>
</div>
</div>
</ElCard>
</template>
<script setup lang="ts">
import { onMounted, reactive } from 'vue'
import { useRouter } from 'vue-router'
import { AssetService } from '@/api/modules'
import type { AssetType } from '@/types/api'
import { RoutesAlias } from '@/router/routesAlias'
defineOptions({ name: 'ExpiringAssetStats' })
const router = useRouter()
const counts = reactive<Record<AssetType, number>>({ card: 0, device: 0 })
const loadCount = async (assetType: AssetType) => {
try {
const response = await AssetService.getExpiringAssets({
asset_type: assetType,
page: 1,
size: 1
})
if (response.code === 0 && response.data) counts[assetType] = response.data.total || 0
} catch {
counts[assetType] = 0
}
}
const goToList = (assetType?: AssetType) => {
router.push({
path: RoutesAlias.ExpiringAssets,
query: assetType ? { asset_type: assetType } : {}
})
}
onMounted(() => void Promise.all([loadCount('card'), loadCount('device')]))
</script>
<style scoped lang="scss">
.expiring-asset-stats {
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
font-weight: 600;
}
.stats-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 16px;
}
.stat-item {
padding: 20px;
cursor: pointer;
border-radius: 8px;
transition: transform 0.2s ease;
&:hover {
transform: translateY(-2px);
}
}
.stat-item--card {
background: #fff0f6;
}
.stat-item--device {
background: #f4ecff;
}
.stat-label {
color: var(--el-text-color-secondary);
}
.stat-value {
margin-top: 8px;
font-size: 28px;
font-weight: 700;
color: var(--el-text-color-primary);
}
}
</style>