diff --git a/admin/src/views/Dashboard.vue b/admin/src/views/Dashboard.vue index c3a193c..6b86301 100644 --- a/admin/src/views/Dashboard.vue +++ b/admin/src/views/Dashboard.vue @@ -40,15 +40,20 @@ - - + + - + + + - + diff --git a/server/src/routes/admin.js b/server/src/routes/admin.js index cc25cd6..85c2443 100755 --- a/server/src/routes/admin.js +++ b/server/src/routes/admin.js @@ -1193,7 +1193,7 @@ router.get('/dashboard-v2', requirePermission('dashboard:read'), async (req, res const [ totalUsers, newUsers7d, totalKnowledge, approvedKnowledge, withQuiz, totalTrends, trendsWithExplain, totalFeedbacks, pendingFeedbacks, totalOrders, paidOrders, - totalLits, litUsers, recentLogins, litByDimAgg, aiStatsRaw + totalLits, litUsers, recentLogins, recentVisits, litByDimAgg, aiStatsRaw ] = await Promise.all([ User.countDocuments({}), User.countDocuments({ createdAt: { $gte: new Date(Date.now() - 7 * 86400000) } }), @@ -1208,7 +1208,8 @@ router.get('/dashboard-v2', requirePermission('dashboard:read'), async (req, res Order.countDocuments({ status: 'paid' }), KnowledgeLit.countDocuments({}), KnowledgeLit.distinct('openid'), - LoginLog.find({}).sort({ createdAt: -1 }).limit(10).lean(), + LoginLog.find({}).sort({ createdAt: -1 }).limit(10).populate('userId', 'nickName').lean(), + VisitLog.find({}).sort({ createdAt: -1 }).limit(10).lean(), KnowledgeLit.aggregate([{ $group: { _id: '$dim', count: { $sum: 1 } } }]), AIChatQuota.aggregate([{ $group: { _id: null, used: { $sum: '$usedQuota' }, users: { $sum: 1 } } }]), ]) @@ -1230,16 +1231,34 @@ router.get('/dashboard-v2', requirePermission('dashboard:read'), async (req, res aiChatUsed: ai.used, aiChatUsers: ai.users, }, litByDim: Object.entries(litByDim).map(([dim, count]) => ({ dim: Number(dim), name: DIM_NAMES[dim], count })), - recentLogins: recentLogins.map(l => ({ - openid: l.openid, - type: l.type, - method: l.method, - ip: l.ip, - success: l.success, - failReason: l.failReason, - userAgent: (l.userAgent || '').slice(0, 80), - createdAt: l.createdAt, - })), + recentLogins: [ + // 登录记录(显示昵称) + ...recentLogins.map(l => ({ + kind: 'login', + createdAt: l.createdAt, + userName: l.userId?.nickName || l.openid, + openid: l.openid, + type: l.type === 'register' ? '注册' : '登录', + method: l.method === 'wechat_miniapp' ? '微信小程序' : (l.method || ''), + ip: l.ip, + success: l.success, + failReason: l.failReason, + })), + // 访问埋点(H5 / 小程序 / 直接访问) + ...recentVisits.map(v => ({ + kind: 'visit', + createdAt: v.createdAt, + userName: v.source, + openid: '', + type: '访问', + method: [v.os, v.browser].filter(Boolean).join(' / ') || v.device || '', + ip: v.ip, + path: v.path, + success: true, + })), + ] + .sort((a, b) => new Date(b.createdAt) - new Date(a.createdAt)) + .slice(0, 10), }) } catch (error) { logger.error('获取增强看板失败:', error)