index.vue
4.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
<script setup lang="ts">
import { ElMessage } from 'element-plus'
import { DemoApi, type DemoStatusVO } from '@/api/demo'
import { useUserStore } from '@/store'
import { formatDateTime } from '@/utils'
/**
* 首页
*
* 这里承担「端到端联调自检」的职责:调用一次 /admin-api/demo/status,
* 把后端应用名、数据库时间、Redis 连通性显示出来,用来证明
* 「登录 → Bearer token → /admin-api → MySQL/Redis」这条链路是通的。
*/
defineOptions({ name: 'Dashboard' })
const userStore = useUserStore()
const loading = ref(false)
const status = ref<DemoStatusVO | null>(null)
const errorMsg = ref('')
async function loadStatus() {
loading.value = true
errorMsg.value = ''
try {
status.value = await DemoApi.getStatus()
} catch (e: any) {
errorMsg.value = e?.message || '自检接口调用失败'
} finally {
loading.value = false
}
}
onMounted(loadStatus)
const nickname = computed(() => userStore.userInfo?.nickname || userStore.userInfo?.username || '-')
</script>
<template>
<div class="app-container">
<el-card shadow="never" class="mb-3">
<div class="welcome">
<el-avatar :size="42">{{ nickname.charAt(0) }}</el-avatar>
<div class="welcome-text">
<div class="welcome-title">你好,{{ nickname }}</div>
<div class="welcome-sub">
当前角色:{{ userStore.roles.join('、') || '无' }} ·
已授权权限点:{{ userStore.permissions.length }} 个
</div>
</div>
</div>
</el-card>
<el-row :gutter="12">
<el-col :xs="24" :md="12">
<el-card shadow="never">
<template #header>
<div class="card-header">
<span>后端联调自检</span>
<el-button link type="primary" :loading="loading" @click="loadStatus">刷新</el-button>
</div>
</template>
<el-alert v-if="errorMsg" :title="errorMsg" type="error" :closable="false" class="mb-3" />
<el-descriptions v-else :column="1" border size="small">
<el-descriptions-item label="应用名称">
{{ status?.applicationName || '-' }}
</el-descriptions-item>
<el-descriptions-item label="登录用户 ID">
{{ status?.loginUserId ?? '-' }}
</el-descriptions-item>
<el-descriptions-item label="数据库时间">
{{ status?.dbTime ? formatDateTime(status.dbTime) : '-' }}
</el-descriptions-item>
<el-descriptions-item label="服务端时间">
{{ status?.serverTime ? formatDateTime(status.serverTime) : '-' }}
</el-descriptions-item>
<el-descriptions-item label="Redis 连通">
<el-tag :type="status?.redisPing ? 'success' : 'danger'" size="small">
{{ status?.redisPing ? '正常' : '异常' }}
</el-tag>
</el-descriptions-item>
</el-descriptions>
</el-card>
</el-col>
<el-col :xs="24" :md="12">
<el-card shadow="never">
<template #header>工程进度</template>
<el-timeline>
<el-timeline-item timestamp="P0 · 已完成" type="success" placement="top">
后端骨架:单 Jar + 模块化单体 + 统一契约(已跑通)<br />
前端骨架:登录 / 动态菜单路由 / 请求层
</el-timeline-item>
<el-timeline-item timestamp="P1 · 已完成" type="success" placement="top">
系统管理域(用户/角色/菜单/组织/字典/日志)真实接口接入
</el-timeline-item>
<el-timeline-item timestamp="P2 · 下一步" type="primary" placement="top">
停车/订单/支付/计费四模块原子合并,六库合一
</el-timeline-item>
<el-timeline-item timestamp="P3+" placement="top">
充电模块 → 前端逐页迁移 → 政务平台并入 → 大屏重写
</el-timeline-item>
</el-timeline>
</el-card>
</el-col>
</el-row>
</div>
</template>
<style scoped lang="scss">
.welcome {
display: flex;
align-items: center;
gap: 14px;
}
.welcome-title {
font-size: 16px;
font-weight: 600;
}
.welcome-sub {
margin-top: 4px;
font-size: 12px;
color: $text-color-secondary;
}
.card-header {
display: flex;
align-items: center;
justify-content: space-between;
}
</style>