From fbb660138c1701dee9814008d0c55b82470f2ad5 Mon Sep 17 00:00:00 2001 From: atoz03 Date: Fri, 5 Dec 2025 19:19:52 +0800 Subject: [PATCH] =?UTF-8?q?fix:=E8=B0=83=E6=95=B4=E5=8E=BB=E9=87=8D?= =?UTF-8?q?=E7=AD=96=E7=95=A5=20-=20=E8=B0=83=E6=95=B4=E5=8E=BB=E9=87=8D?= =?UTF-8?q?=E7=AD=96=E7=95=A5=EF=BC=88src/routes/admin/usageStats.js?= =?UTF-8?q?=EF=BC=89=EF=BC=9A=E8=B4=A6=E6=88=B7=E7=AD=9B=E9=80=89=E6=94=B9?= =?UTF-8?q?=E4=B8=BA=E6=8C=89=20accountId=20=E8=81=9A=E5=90=88=E8=AE=B0?= =?UTF-8?q?=E5=BD=95=E6=89=80=E6=9C=89=E5=87=BA=E7=8E=B0=E7=9A=84=20accoun?= =?UTF-8?q?tType=EF=BC=8C=E6=9E=84=E5=BB=BA=20options=20=E6=97=B6=E4=BE=9D?= =?UTF-8?q?=E6=AC=A1=E6=8C=89=E5=8E=86=E5=8F=B2=E7=B1=BB=E5=9E=8B=E8=A7=A3?= =?UTF-8?q?=E6=9E=90=E8=B4=A6=E5=8F=B7=EF=BC=8C=E5=A4=B1=E8=B4=A5=E5=86=8D?= =?UTF-8?q?=E5=85=A8=E9=87=8F=E5=9B=9E=E9=80=80=EF=BC=8C=E6=97=A0=E6=B3=95?= =?UTF-8?q?=E8=A7=A3=E6=9E=90=E4=B9=9F=E4=BF=9D=E7=95=99=E4=B8=BA=E7=AD=9B?= =?UTF-8?q?=E9=80=89=E9=A1=B9=E5=B9=B6=E5=B8=A6=20rawTypes=EF=BC=8C?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E6=B8=A0=E9=81=93=E6=94=B9=E5=90=8D/?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E5=AF=BC=E8=87=B4=E9=80=89=E9=A1=B9=E8=A2=AB?= =?UTF-8?q?=E2=80=9C=E5=8E=BB=20=20=20=20=20=E9=87=8D=E2=80=9D=E4=B8=A2?= =?UTF-8?q?=E5=A4=B1=E3=80=82=20=20=20-=20=E8=A7=A3=E6=9E=90=E5=85=9C?= =?UTF-8?q?=E5=BA=95=EF=BC=88src/routes/admin/usageStats.js=EF=BC=89?= =?UTF-8?q?=EF=BC=9AresolveAccountInfo=20=E5=9C=A8=E4=BC=A0=E5=85=A5?= =?UTF-8?q?=E6=9C=AA=E7=9F=A5=E7=B1=BB=E5=9E=8B=E6=88=96=E8=BF=87=E6=BB=A4?= =?UTF-8?q?=E5=90=8E=E4=B8=BA=E7=A9=BA=E6=97=B6=E5=9B=9E=E9=80=80=E5=B0=9D?= =?UTF-8?q?=E8=AF=95=E5=85=A8=E9=83=A8=E6=9C=8D=E5=8A=A1=EF=BC=8C=E5=87=8F?= =?UTF-8?q?=E8=BD=BB=E6=B8=A0=E9=81=93=E6=94=B9=E5=90=8D=E8=A7=A3=E6=9E=90?= =?UTF-8?q?=E4=B8=8D=E5=88=B0=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/routes/admin/usageStats.js | 59 +++++++++++++++++++++++----------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/src/routes/admin/usageStats.js b/src/routes/admin/usageStats.js index c71a8576..539d6133 100644 --- a/src/routes/admin/usageStats.js +++ b/src/routes/admin/usageStats.js @@ -1942,10 +1942,15 @@ router.get('/api-keys/:keyId/usage-records', authenticateAdmin, async (req, res) return accountCache.get(cacheKey) } - const servicesToTry = type + let servicesToTry = type ? accountServices.filter((svc) => svc.type === type) : accountServices + // 若渠道改名或传入未知类型,回退尝试全量服务,避免漏解析历史账号 + if (!servicesToTry.length) { + servicesToTry = accountServices + } + for (const service of servicesToTry) { try { const account = await service.getter(id) @@ -2055,12 +2060,14 @@ router.get('/api-keys/:keyId/usage-records', authenticateAdmin, async (req, res) } if (record.accountId) { - const key = `${record.accountId}:${record.accountType || 'unknown'}` - if (!accountOptionMap.has(key)) { - accountOptionMap.set(key, { + const normalizedType = record.accountType || 'unknown' + if (!accountOptionMap.has(record.accountId)) { + accountOptionMap.set(record.accountId, { id: record.accountId, - accountType: record.accountType || 'unknown' + accountTypes: new Set([normalizedType]) }) + } else { + accountOptionMap.get(record.accountId).accountTypes.add(normalizedType) } } @@ -2133,23 +2140,37 @@ router.get('/api-keys/:keyId/usage-records', authenticateAdmin, async (req, res) } const accountOptions = [] - const accountIdAdded = new Set() for (const option of accountOptionMap.values()) { - const info = await resolveAccountInfo(option.id, option.accountType) - if (info && info.name) { - if (accountIdAdded.has(option.id)) { - continue + const types = Array.from(option.accountTypes || []) + + // 优先按历史出现的 accountType 解析,若失败则回退全量解析 + let resolvedInfo = null + for (const type of types) { + resolvedInfo = await resolveAccountInfo(option.id, type) + if (resolvedInfo && resolvedInfo.name) { + break } - accountIdAdded.add(option.id) - accountOptions.push({ - id: option.id, - name: info.name, - accountType: info.type, - accountTypeName: accountTypeNames[info.type] || '未知渠道' - }) - } else { - logger.warn(`⚠️ Skipping deleted/invalid account in filter options: ${option.id}`) } + if (!resolvedInfo) { + resolvedInfo = await resolveAccountInfo(option.id) + } + + const chosenType = resolvedInfo?.type || types[0] || 'unknown' + const chosenTypeName = accountTypeNames[chosenType] || '未知渠道' + + if (!resolvedInfo) { + logger.warn( + `⚠️ 保留无法解析的账户筛选项: ${option.id}, types=${types.join(',') || 'none'}` + ) + } + + accountOptions.push({ + id: option.id, + name: resolvedInfo?.name || option.id, + accountType: chosenType, + accountTypeName: chosenTypeName, + rawTypes: types + }) } return res.json({