feat: 订阅消息通知体系——登录后请求订阅授权(额度记账)+服务端subscribe/send(access_token缓存/原子扣减/失败回补/发送记录)+管理后台通知推送页;版本v1.4.4

This commit is contained in:
Hermes Agent
2026-09-19 19:28:40 +08:00
parent 9ea09c95f2
commit 6d463b9296
11 changed files with 297 additions and 4 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
{
"name": "宇之然AI维度",
"appid": "wxdad62baf4ccd09e3",
"versionName": "1.4.3",
"versionName": "1.4.4",
"versionCode": "100",
"description": "AI 知识探索社区 — 从5个维度系统理解人工智能",
"uni-app": {
+3
View File
@@ -129,6 +129,7 @@
</template>
<script setup>
import { askSubscribe } from '../../utils/notify'
import { onShareAppMessage, onShareTimeline } from '@dcloudio/uni-app'
import { ref } from 'vue'
@@ -217,6 +218,7 @@ const wechatLogin = async () => {
loading.value = true
await userStore.login(loginRes.code, {})
uni.showToast({ title: '登录成功', icon: 'success' })
setTimeout(() => askSubscribe(), 800) // 登录成功后请求订阅授权(接受新版通知等)
setTimeout(() => uni.switchTab({ url: '/pages/index/index' }), 1000)
} catch (err) {
const msg = (err && (err.message || err.errMsg)) || ''
@@ -245,6 +247,7 @@ const handleLogin = async () => {
: { username: identifier, password: loginForm.value.password }
await userStore.h5Login(loginData)
uni.showToast({ title: '登录成功', icon: 'success' })
setTimeout(() => askSubscribe(), 800) // 登录成功后请求订阅授权(接受新版通知等)
setTimeout(() => uni.switchTab({ url: '/pages/index/index' }), 1000)
} catch (err) {
uni.showToast({ title: err.message || '登录失败', icon: 'none' })
+35
View File
@@ -0,0 +1,35 @@
import { request } from './api'
import { getToken } from './api'
// 订阅消息模板ID(微信公众平台→订阅消息→我的模板)
const TMPL_IDS = [
(typeof import.meta !== 'undefined' && import.meta.env && import.meta.env.VITE_NOTIFY_TMPL) || '',
].filter(Boolean)
/**
* 请求订阅授权(在用户完成关键动作后调用,此时微信允许弹授权框)
* 返回接受的模板数(失败静默0)
*/
export async function askSubscribe() {
// #ifdef MP-WEIXIN
if (!TMPL_IDS.length) return 0
try {
const res = await new Promise((resolve) => {
uni.requestSubscribeMessage({
tmplIds: TMPL_IDS,
success: resolve,
fail: () => resolve(null),
})
})
if (!res) return 0
const accepted = TMPL_IDS.filter(id => res[id] === 'accept').length
if (accepted > 0 && getToken()) {
request('PUT', '/api/auth/subscribe-report', { accepted }, getToken()).catch(() => {})
}
return accepted
} catch { return 0 }
// #endif
// #ifndef MP-WEIXIN
return 0
// #endif
}