diff --git a/server/services/notificationService.ts b/server/services/notificationService.ts index 7e5eb63..3836bcd 100644 --- a/server/services/notificationService.ts +++ b/server/services/notificationService.ts @@ -163,6 +163,9 @@ export async function createSongSelectedNotification( // 如果用户关闭了此类通知,则不发送 if (settings && !settings.enabled) { + console.warn( + `[Notification] SONG_SELECTED → user ${userId} 跳过:该用户关闭了通知总开关,微信/MeoW/邮件都不会发` + ) return null } @@ -350,7 +353,10 @@ export async function createSongPlayedNotification(songId: number, ipAddress?: s } // 同步发送 微信订阅消息(只有绑了微信、且刚点过授权的用户收得到,见 wechatSubscribeService) try { - await sendWechatSubscribeToUser(targetUserId, 'SONG_PLAYED', { songTitle: song.title, message: userMessage }) + await sendWechatSubscribeToUser(targetUserId, 'SONG_PLAYED', { + songTitle: song.title, + message: userMessage + }) } catch (error) { console.error('发送微信订阅消息失败:', error) } @@ -554,7 +560,11 @@ export async function createSongRejectedNotification( } // 同步发送 微信订阅消息(只有绑了微信、且刚点过授权的用户收得到,见 wechatSubscribeService) try { - await sendWechatSubscribeToUser(userId, 'SONG_REJECTED', { songTitle: songInfo.title, reason: reason, message }) + await sendWechatSubscribeToUser(userId, 'SONG_REJECTED', { + songTitle: songInfo.title, + reason: reason, + message + }) } catch (error) { console.error('发送微信订阅消息失败:', error) } @@ -591,7 +601,9 @@ export async function createSubmissionNoteClearedNotification( ipAddress?: string ) { try { - const uniqueUserIds = [...new Set(userIds.filter((userId) => Number.isInteger(userId) && userId > 0))] + const uniqueUserIds = [ + ...new Set(userIds.filter((userId) => Number.isInteger(userId) && userId > 0)) + ] if (uniqueUserIds.length === 0) { return [] @@ -651,7 +663,10 @@ export async function createSystemNotification( } // 同步发送 微信订阅消息(只有绑了微信、且刚点过授权的用户收得到,见 wechatSubscribeService) try { - await sendWechatSubscribeToUser(userId, 'SYSTEM_NOTICE', { songTitle: title, message: content }) + await sendWechatSubscribeToUser(userId, 'SYSTEM_NOTICE', { + songTitle: title, + message: content + }) } catch (error) { console.error('发送微信订阅消息失败:', error) } diff --git a/server/services/wechatSubscribeService.ts b/server/services/wechatSubscribeService.ts index 064e0d6..55ad8c0 100644 --- a/server/services/wechatSubscribeService.ts +++ b/server/services/wechatSubscribeService.ts @@ -234,7 +234,12 @@ export async function sendWechatSubscribeToUser( ): Promise { try { const conf = getSubscribeTemplates()[kind] - if (!conf || !conf.id) return { ok: false, skipped: 'no-template' } + if (!conf || !conf.id) { + // 这四条跳过路径以前是静默 return,线上排查时日志里什么都没有,只能靠猜。 + // 现在每条都留一行,grep [WeChatSubscribe] 就能看出卡在哪一步。 + console.error(`[WeChatSubscribe] ${kind} → user ${userId} 跳过:没有配置模板 ID(no-template)`) + return { ok: false, skipped: 'no-template' } + } // 用户的通知总开关(与 MeoW / 邮件共用同一份设置) const settings = await db @@ -243,14 +248,24 @@ export async function sendWechatSubscribeToUser( .where(eq(notificationSettings.userId, userId)) .limit(1) if (settings[0] && settings[0].enabled === false) { + console.warn(`[WeChatSubscribe] ${kind} → user ${userId} 跳过:该用户的通知总开关是关的(disabled-by-user)`) return { ok: false, skipped: 'disabled-by-user' } } const openid = await getWechatOpenid(userId) - if (!openid) return { ok: false, skipped: 'no-wechat-openid' } + if (!openid) { + // 用户没有绑定微信(userIdentities 里没有 provider='wechat-mp' 的行)→ 永远发不出去 + console.warn(`[WeChatSubscribe] ${kind} → user ${userId} 跳过:该用户没有绑定微信 openid(no-wechat-openid)`) + return { ok: false, skipped: 'no-wechat-openid' } + } const token = await getMiniAccessToken() - if (!token) return { ok: false, skipped: 'no-access-token' } + if (!token) { + console.error( + `[WeChatSubscribe] ${kind} → user ${userId} 跳过:拿不到小程序 access_token(no-access-token,检查 WECHAT_MINI_APPID / WECHAT_MINI_SECRET)` + ) + return { ok: false, skipped: 'no-access-token' } + } const data = buildTemplateData(conf, Object.assign({ songTitle: '宝一外校园点歌系统' }, vars)) return await postSubscribe(token, openid, conf.id, data, userId, kind)