From c5e12c67facffe796d060bce9b3b7cf058df11e6 Mon Sep 17 00:00:00 2001 From: Hermes Agent Date: Wed, 16 Sep 2026 06:49:39 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20=E7=9C=8B=E6=9D=BF=E6=9C=80=E8=BF=91?= =?UTF-8?q?=E8=AE=BF=E9=97=AE=E8=AE=B0=E5=BD=95=E5=90=88=E5=B9=B6=E7=99=BB?= =?UTF-8?q?=E5=BD=95+=E8=AE=BF=E9=97=AE=E5=9F=8B=E7=82=B9(=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E6=98=B5=E7=A7=B0/=E6=9D=A5=E6=BA=90/=E7=BB=88?= =?UTF-8?q?=E7=AB=AF/=E8=B7=AF=E5=BE=84)=EF=BC=8C=E4=BF=AE=E5=A4=8D?= =?UTF-8?q?=E5=8F=AA=E6=98=BE=E7=A4=BA=E7=99=BB=E5=BD=95=E6=97=A5=E5=BF=97?= =?UTF-8?q?=E7=9C=8B=E4=B8=8D=E5=88=B0=E6=9C=80=E6=96=B0=E8=AE=BF=E9=97=AE?= =?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin/src/views/Dashboard.vue | 15 ++++++++---- server/src/routes/admin.js | 43 +++++++++++++++++++++++++---------- 2 files changed, 41 insertions(+), 17 deletions(-) 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)