|
@@ -132,12 +132,21 @@
|
|
|
</template>
|
|
</template>
|
|
|
|
|
|
|
|
<script setup lang="ts">
|
|
<script setup lang="ts">
|
|
|
-import { ref, onMounted, onUnmounted, computed } from 'vue'
|
|
|
|
|
|
|
+import { ref, onMounted, computed } from 'vue'
|
|
|
import { onShow, onHide } from '@dcloudio/uni-app'
|
|
import { onShow, onHide } from '@dcloudio/uni-app'
|
|
|
|
|
|
|
|
import CustomNav from '@/components/custom-nav.vue'
|
|
import CustomNav from '@/components/custom-nav.vue'
|
|
|
import { getMedicationListByPatientId } from '@/api/patientMedication'
|
|
import { getMedicationListByPatientId } from '@/api/patientMedication'
|
|
|
import { getPatientReminderOverview, savePatientReminder } from '@/api/patientReminder'
|
|
import { getPatientReminderOverview, savePatientReminder } from '@/api/patientReminder'
|
|
|
|
|
+import type { SubscriptionAvailability } from '@/api/patientReminder'
|
|
|
|
|
+
|
|
|
|
|
+// fetchSubscriptionSettings 返回类型
|
|
|
|
|
+type FetchSubscriptionInfo = {
|
|
|
|
|
+ mainSwitch: boolean | null
|
|
|
|
|
+ templateStatus: string | null
|
|
|
|
|
+ raw?: any
|
|
|
|
|
+ error?: any
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
// 定义各个提醒项的状态
|
|
// 定义各个提醒项的状态
|
|
|
const bloodPressureReminder = ref({
|
|
const bloodPressureReminder = ref({
|
|
@@ -167,8 +176,8 @@ const TEMPLATE_NO = '7536'
|
|
|
// 全局消息开关
|
|
// 全局消息开关
|
|
|
const notificationsEnabled = ref<boolean>(false)
|
|
const notificationsEnabled = ref<boolean>(false)
|
|
|
|
|
|
|
|
-// 一次性订阅开关
|
|
|
|
|
-const subscriptionAvailable = ref<boolean>(true)
|
|
|
|
|
|
|
+// 订阅可用性('NONE' | 'ONCE' | 'MULTI')
|
|
|
|
|
+const subscriptionAvailable = ref<SubscriptionAvailability>('NONE')
|
|
|
|
|
|
|
|
// 是否显示权限引导
|
|
// 是否显示权限引导
|
|
|
const showPermissionGuide = ref<boolean>(false)
|
|
const showPermissionGuide = ref<boolean>(false)
|
|
@@ -419,30 +428,7 @@ onHide(() => {
|
|
|
console.log('[reminder] 页面/应用进入后台(onHide)', { entrySource: entrySource.value })
|
|
console.log('[reminder] 页面/应用进入后台(onHide)', { entrySource: entrySource.value })
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
-// H5 平台兼容:document.visibilityState
|
|
|
|
|
-const handleVisibilityChange = () => {
|
|
|
|
|
- try {
|
|
|
|
|
- const state = (document as any).visibilityState
|
|
|
|
|
- if (state === 'hidden') {
|
|
|
|
|
- console.log('[reminder][visibilitychange] H5 页面变为 hidden(退到后台/切换窗口)')
|
|
|
|
|
- } else if (state === 'visible') {
|
|
|
|
|
- console.log('[reminder][visibilitychange] H5 页面变为 visible(回到前台)')
|
|
|
|
|
- }
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- // 忽略在非 H5 环境下的错误
|
|
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
onMounted(() => {
|
|
onMounted(() => {
|
|
|
- // 注册 H5 可见性变更监听
|
|
|
|
|
- try {
|
|
|
|
|
- if (typeof document !== 'undefined' && typeof document.addEventListener === 'function') {
|
|
|
|
|
- document.addEventListener('visibilitychange', handleVisibilityChange)
|
|
|
|
|
- }
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- // 忽略
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
// 额外注册 uni 全局的 App 前后台事件(部分平台需要)
|
|
// 额外注册 uni 全局的 App 前后台事件(部分平台需要)
|
|
|
try {
|
|
try {
|
|
|
if ((uni as any) && typeof (uni as any).onAppShow === 'function') {
|
|
if ((uni as any) && typeof (uni as any).onAppShow === 'function') {
|
|
@@ -460,16 +446,6 @@ onMounted(() => {
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
-onUnmounted(() => {
|
|
|
|
|
- try {
|
|
|
|
|
- if (typeof document !== 'undefined' && typeof document.removeEventListener === 'function') {
|
|
|
|
|
- document.removeEventListener('visibilitychange', handleVisibilityChange)
|
|
|
|
|
- }
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- // 忽略
|
|
|
|
|
- }
|
|
|
|
|
-})
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
* 加载提醒设置
|
|
* 加载提醒设置
|
|
|
*/
|
|
*/
|
|
@@ -503,9 +479,9 @@ const loadReminders = async () => {
|
|
|
times: medicationReminder.value.times // 保留已加载的用药时间点
|
|
times: medicationReminder.value.times // 保留已加载的用药时间点
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 更新全局消息开关和一次性订阅开关
|
|
|
|
|
|
|
+ // 更新全局消息开关和订阅可用性(后端返回字符串 'NONE'|'ONCE'|'MULTI')
|
|
|
notificationsEnabled.value = reminderData.notificationEnabled
|
|
notificationsEnabled.value = reminderData.notificationEnabled
|
|
|
- subscriptionAvailable.value = reminderData.subscriptionAvailable
|
|
|
|
|
|
|
+ subscriptionAvailable.value = (reminderData.subscriptionAvailable as SubscriptionAvailability) || 'NONE'
|
|
|
|
|
|
|
|
try {
|
|
try {
|
|
|
const remindersToSave = {
|
|
const remindersToSave = {
|
|
@@ -622,98 +598,187 @@ const loadMedicationTimes = async () => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const checkSubscriptionStatus = (passive = false) => {
|
|
|
|
|
- // 使用 uni.getSetting 检查用户授权状态
|
|
|
|
|
- if (typeof (uni as any).getSetting === 'function') {
|
|
|
|
|
- (uni as any).getSetting({
|
|
|
|
|
- withSubscriptions: true, // 启用订阅设置查询
|
|
|
|
|
- success: (res: any) => {
|
|
|
|
|
- console.log('[checkSubscriptionStatus] 用户设置:', res)
|
|
|
|
|
- try {
|
|
|
|
|
- // 额外输出可序列化的 JSON 版本,方便在日志中完整查看返回结构
|
|
|
|
|
- console.log('[checkSubscriptionStatus] 用户设置(JSON):', JSON.stringify(res, null, 2))
|
|
|
|
|
- } catch (err) {
|
|
|
|
|
- console.error('[checkSubscriptionStatus] 无法序列化 getSetting 返回值:', err)
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 仅获取订阅设置(不做任何状态修改)
|
|
|
|
|
+ * 返回对象:{ mainSwitch: boolean|null, templateStatus: string|null, raw?: any, error?: any }
|
|
|
|
|
+ */
|
|
|
|
|
+const fetchSubscriptionSettings = async (): Promise<FetchSubscriptionInfo> => {
|
|
|
|
|
+ return new Promise((resolve: (v: FetchSubscriptionInfo) => void) => {
|
|
|
|
|
+ if (typeof (uni as any).getSetting === 'function') {
|
|
|
|
|
+ (uni as any).getSetting({
|
|
|
|
|
+ withSubscriptions: true,
|
|
|
|
|
+ success: (res: any) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const subs = res.subscriptionsSetting
|
|
|
|
|
+ const mainSwitch = subs ? subs.mainSwitch : null
|
|
|
|
|
+ const itemSettings = subs ? subs.itemSettings || {} : {}
|
|
|
|
|
+ const templateStatus = itemSettings[TEMPLATE_ID] || null
|
|
|
|
|
+ resolve({ mainSwitch, templateStatus, raw: res })
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ resolve({ mainSwitch: null, templateStatus: null, raw: res })
|
|
|
|
|
+ }
|
|
|
|
|
+ },
|
|
|
|
|
+ fail: (err: any) => {
|
|
|
|
|
+ resolve({ mainSwitch: null, templateStatus: null, error: err })
|
|
|
}
|
|
}
|
|
|
|
|
+ })
|
|
|
|
|
+ } else {
|
|
|
|
|
+ resolve({ mainSwitch: null, templateStatus: null })
|
|
|
|
|
+ }
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
|
|
|
- try {
|
|
|
|
|
- // 检查订阅消息设置
|
|
|
|
|
- const subs = res.subscriptionsSetting
|
|
|
|
|
- if (subs) {
|
|
|
|
|
- console.log('[checkSubscriptionStatus] 订阅设置详情:', JSON.stringify(subs, null, 2))
|
|
|
|
|
-
|
|
|
|
|
- // 检查主开关
|
|
|
|
|
- const mainSwitch = subs.mainSwitch
|
|
|
|
|
- console.log(`[checkSubscriptionStatus] 订阅主开关状态: ${mainSwitch ? '已开启(用户允许接收通知)' : '已关闭(用户禁止接收所有通知)'}`)
|
|
|
|
|
-
|
|
|
|
|
- // 检查针对特定模板的设置
|
|
|
|
|
- const itemSettings = subs.itemSettings || {}
|
|
|
|
|
- const templateStatus = itemSettings[TEMPLATE_ID]
|
|
|
|
|
- console.log(`[checkSubscriptionStatus] 模板 ${TEMPLATE_ID} 状态:`, templateStatus)
|
|
|
|
|
- // console.log输出subscriptionAvailable
|
|
|
|
|
- console.log(`[checkSubscriptionStatus] 一次性订阅开关状态: ${subscriptionAvailable.value}`)
|
|
|
|
|
-
|
|
|
|
|
- // 若主开关关闭或模板为 'reject'、'ban' ,则主动关闭本地通知开关
|
|
|
|
|
- if (mainSwitch === false || templateStatus === 'reject' || templateStatus === 'ban') {
|
|
|
|
|
- console.log('[checkSubscriptionStatus] 发现订阅被关闭或本模板被拒绝,更新本地开关并尝试同步到服务器')
|
|
|
|
|
- notificationsEnabled.value = false
|
|
|
|
|
- // 在主动模式下显示权限引导;被动模式(如 onShow)只更新本地并同步服务器,但不主动弹窗
|
|
|
|
|
- if (!passive) {
|
|
|
|
|
- showPermissionGuide.value = (mainSwitch === false)
|
|
|
|
|
- }
|
|
|
|
|
- try {
|
|
|
|
|
- // 先更新本地存储
|
|
|
|
|
- saveLocalPatientReminders()
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error('[checkSubscriptionStatus] 更新本地存储失败:', e)
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
- // 异步上传到服务器:不阻塞 UI,记录成功/失败日志
|
|
|
|
|
- try {
|
|
|
|
|
- saveReminders()
|
|
|
|
|
- .then(() => {
|
|
|
|
|
- console.log('[checkSubscriptionStatus] 已将订阅状态同步到服务器')
|
|
|
|
|
- })
|
|
|
|
|
- .catch((err: any) => {
|
|
|
|
|
- console.error('[checkSubscriptionStatus] 同步订阅状态到服务器失败:', err)
|
|
|
|
|
- })
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error('[checkSubscriptionStatus] 调用 saveReminders 异常:', e)
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- // 主开关开启且模板被接受:仅在主动模式下将本地开关置为 true 并关闭引导
|
|
|
|
|
- else if (!passive && mainSwitch === true && templateStatus === 'accept') {
|
|
|
|
|
- console.log('[checkSubscriptionStatus] 用户开启了订阅设置,正在更新本地状态并同步到服务器')
|
|
|
|
|
- notificationsEnabled.value = true
|
|
|
|
|
- showPermissionGuide.value = false
|
|
|
|
|
- try {
|
|
|
|
|
- saveLocalPatientReminders()
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error('[checkSubscriptionStatus] 更新本地存储失败:', e)
|
|
|
|
|
- }
|
|
|
|
|
- try {
|
|
|
|
|
- saveReminders()
|
|
|
|
|
- .then(() => console.log('[checkSubscriptionStatus] 同步订阅开启状态到服务器成功'))
|
|
|
|
|
- .catch((err: any) => console.error('[checkSubscriptionStatus] 同步订阅开启状态到服务器失败:', err))
|
|
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error('[checkSubscriptionStatus] 调用 saveReminders 异常:', e)
|
|
|
|
|
- }
|
|
|
|
|
- } else {
|
|
|
|
|
- console.log('[checkSubscriptionStatus] 订阅设置未发现需要变更,本次检查为被动=' + passive)
|
|
|
|
|
- }
|
|
|
|
|
|
|
+/**
|
|
|
|
|
+ * 积极请求订阅消息
|
|
|
|
|
+ * 逻辑:调用微信订阅接口,成功后根据 getSetting 结果更新为 ONCE 或 MULTI
|
|
|
|
|
+ * @param manual 是否为用户手动触发(手动触发时若拒绝则强制显示权限引导)
|
|
|
|
|
+ * @param wasEnabled 调用前服务器/本地记录的通知开关状态(用于在自动同步失败时决定是否显示引导)
|
|
|
|
|
+ */
|
|
|
|
|
+const requestSubscription = async (manual = false, wasEnabled = false) => {
|
|
|
|
|
+ return new Promise<void>((resolve) => {
|
|
|
|
|
+ console.log(`[requestSubscription] 正在发起订阅请求... (manual=${manual}, wasEnabled=${wasEnabled})`)
|
|
|
|
|
+ if (typeof (uni as any).requestSubscribeMessage !== 'function') {
|
|
|
|
|
+ console.warn('[requestSubscription] 当前环境不支持 requestSubscribeMessage')
|
|
|
|
|
+ resolve()
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ (uni as any).requestSubscribeMessage({
|
|
|
|
|
+ tmplIds: [TEMPLATE_ID],
|
|
|
|
|
+ success: async (res: any) => {
|
|
|
|
|
+ console.log('[requestSubscription] 订阅请求成功结果:', res)
|
|
|
|
|
+ const result = res && res[TEMPLATE_ID]
|
|
|
|
|
+ if (result === 'accept') {
|
|
|
|
|
+ // 订阅成功,进一步检查是长期还是单次
|
|
|
|
|
+ const info = await fetchSubscriptionSettings()
|
|
|
|
|
+ if (info.mainSwitch === true && info.templateStatus === 'accept') {
|
|
|
|
|
+ subscriptionAvailable.value = 'MULTI'
|
|
|
} else {
|
|
} else {
|
|
|
- console.log('[checkSubscriptionStatus] 响应中未找到订阅设置')
|
|
|
|
|
|
|
+ subscriptionAvailable.value = 'ONCE'
|
|
|
|
|
+ }
|
|
|
|
|
+ uni.showToast({ title: '订阅成功', icon: 'success' })
|
|
|
|
|
+ showPermissionGuide.value = false
|
|
|
|
|
+ } else {
|
|
|
|
|
+ // 用户拒绝或关闭
|
|
|
|
|
+ notificationsEnabled.value = false
|
|
|
|
|
+ subscriptionAvailable.value = 'NONE'
|
|
|
|
|
+ uni.showToast({ title: '订阅被拒绝', icon: 'none' })
|
|
|
|
|
+ // 如果是手动触发且被拒绝,或者主开关关闭,或者原本是开启状态但现在失败了,则显示引导
|
|
|
|
|
+ const info = await fetchSubscriptionSettings()
|
|
|
|
|
+ if (info.mainSwitch === false || manual || wasEnabled) {
|
|
|
|
|
+ showPermissionGuide.value = true
|
|
|
}
|
|
}
|
|
|
- } catch (e) {
|
|
|
|
|
- console.error('[checkSubscriptionStatus] 处理返回值时出错:', e)
|
|
|
|
|
}
|
|
}
|
|
|
|
|
+ saveLocalPatientReminders()
|
|
|
|
|
+ await saveReminders()
|
|
|
|
|
+ resolve()
|
|
|
},
|
|
},
|
|
|
- fail: (err: any) => {
|
|
|
|
|
- console.error('[checkSubscriptionStatus] 获取用户设置失败:', err)
|
|
|
|
|
|
|
+ fail: async (err: any) => {
|
|
|
|
|
+ console.log('[requestSubscription] 订阅请求失败:', err)
|
|
|
|
|
+ // 订阅请求失败,确保 UI 开关状态回滚为关闭
|
|
|
|
|
+ notificationsEnabled.value = false
|
|
|
|
|
+ // 根据错误类型显示不同的提示信息
|
|
|
|
|
+ if (err.errCode === 20004) {
|
|
|
|
|
+ uni.showToast({ title: '推送权限已关闭', icon: 'none' })
|
|
|
|
|
+ showPermissionGuide.value = true
|
|
|
|
|
+ } else {
|
|
|
|
|
+ uni.showToast({ title: '订阅请求失败', icon: 'none' })
|
|
|
|
|
+ // 手动触发失败或原本开启但现在失败,也尝试显示引导
|
|
|
|
|
+ if (manual || wasEnabled) showPermissionGuide.value = true
|
|
|
|
|
+ }
|
|
|
|
|
+ saveLocalPatientReminders()
|
|
|
|
|
+ await saveReminders()
|
|
|
|
|
+ resolve()
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
- } else {
|
|
|
|
|
- console.log('当前环境不支持 uni.getSetting')
|
|
|
|
|
|
|
+ })
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/**
|
|
|
|
|
+ * 检查订阅/消息权限状态并同步到服务器
|
|
|
|
|
+ * 逻辑要求:
|
|
|
|
|
+ * 1. 本地微信 mainSwitch: false
|
|
|
|
|
+ * - 若服务器 notificationsEnabled 为 true,则设为 false 并积极请求订阅
|
|
|
|
|
+ * - 若服务器 subscriptionAvailable 不为 NONE,则设为 NONE
|
|
|
|
|
+ * 2. 本地微信 mainSwitch: true 但无长期订阅 (templateStatus !== 'accept')
|
|
|
|
|
+ * - 若服务器 subscriptionAvailable 为 NONE,请求订阅,成功后设为 ONCE
|
|
|
|
|
+ * - 若服务器 subscriptionAvailable 为 MULTI,设为 NONE 并重新请求订阅
|
|
|
|
|
+ * 3. 本地微信 mainSwitch: true 且有长期订阅 (templateStatus === 'accept')
|
|
|
|
|
+ * - 确保服务器 subscriptionAvailable 为 MULTI
|
|
|
|
|
+ */
|
|
|
|
|
+const checkSubscriptionStatus = async (passive = false) => {
|
|
|
|
|
+ try {
|
|
|
|
|
+ const info = await fetchSubscriptionSettings()
|
|
|
|
|
+ const mainSwitch = info.mainSwitch
|
|
|
|
|
+ const templateStatus = info.templateStatus
|
|
|
|
|
+
|
|
|
|
|
+ console.log(`[checkSubscriptionStatus] 微信状态: mainSwitch=${mainSwitch}, templateStatus=${templateStatus}`)
|
|
|
|
|
+ console.log(`[checkSubscriptionStatus] 服务器状态: notificationsEnabled=${notificationsEnabled.value}, subscriptionAvailable=${subscriptionAvailable.value}`)
|
|
|
|
|
+
|
|
|
|
|
+ let needsSave = false
|
|
|
|
|
+ let shouldRequest = false
|
|
|
|
|
+
|
|
|
|
|
+ // 记录检查前的开启状态,用于在自动同步失败时决定是否显示引导
|
|
|
|
|
+ const wasEnabledBeforeCheck = notificationsEnabled.value
|
|
|
|
|
+
|
|
|
|
|
+ // 情况一:用户不允许推送消息 (mainSwitch: false)
|
|
|
|
|
+ if (mainSwitch === false) {
|
|
|
|
|
+ // 检查服务器的 notificationsEnabled,如果是开启的,先设定为关闭
|
|
|
|
|
+ if (notificationsEnabled.value === true) {
|
|
|
|
|
+ console.log('[checkSubscriptionStatus] Case 1: mainSwitch 为 false 但服务器开启,正在关闭并请求订阅')
|
|
|
|
|
+ notificationsEnabled.value = false
|
|
|
|
|
+ needsSave = true
|
|
|
|
|
+ // 积极尝试请求订阅
|
|
|
|
|
+ shouldRequest = true
|
|
|
|
|
+ }
|
|
|
|
|
+ // 检查服务器的 subscriptionAvailable,如果不为 "NONE",需要设定为 NONE
|
|
|
|
|
+ if (subscriptionAvailable.value !== 'NONE') {
|
|
|
|
|
+ console.log('[checkSubscriptionStatus] Case 1: subscriptionAvailable 不为 NONE,修正为 NONE')
|
|
|
|
|
+ subscriptionAvailable.value = 'NONE'
|
|
|
|
|
+ needsSave = true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 情况二:用户同意发通知,但没有长期订阅 (mainSwitch: true, templateStatus !== 'accept')
|
|
|
|
|
+ else if (mainSwitch === true && templateStatus !== 'accept') {
|
|
|
|
|
+ // 如果为 "NONE",说明被服务器标记为消耗了,需要请求订阅
|
|
|
|
|
+ // 修改点:只有在 notificationsEnabled 为 true 时才发起请求
|
|
|
|
|
+ if (subscriptionAvailable.value === 'NONE' && notificationsEnabled.value === true) {
|
|
|
|
|
+ console.log('[checkSubscriptionStatus] Case 2: subscriptionAvailable 为 NONE 且开关开启,发起订阅请求')
|
|
|
|
|
+ shouldRequest = true
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果服务器的 subscriptionAvailable 原本是 MULTI,那么就不对,先把服务器的设定为 NONE 再去请求
|
|
|
|
|
+ else if (subscriptionAvailable.value === 'MULTI') {
|
|
|
|
|
+ console.log('[checkSubscriptionStatus] Case 2: subscriptionAvailable 为 MULTI 但微信无长期订阅,修正为 NONE')
|
|
|
|
|
+ subscriptionAvailable.value = 'NONE'
|
|
|
|
|
+ needsSave = true
|
|
|
|
|
+ // 只有在开关开启时才请求
|
|
|
|
|
+ if (notificationsEnabled.value === true) {
|
|
|
|
|
+ shouldRequest = true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 如果是 ONCE,则不做处理
|
|
|
|
|
+ }
|
|
|
|
|
+ // 情况三:用户同意长期发送消息 (mainSwitch: true, templateStatus === 'accept')
|
|
|
|
|
+ else if (mainSwitch === true && templateStatus === 'accept') {
|
|
|
|
|
+ // 保证远程服务器的 subscriptionAvailable 为 MULTI
|
|
|
|
|
+ if (subscriptionAvailable.value !== 'MULTI') {
|
|
|
|
|
+ console.log('[checkSubscriptionStatus] Case 3: 微信有长期订阅但服务器不是 MULTI,修正为 MULTI')
|
|
|
|
|
+ subscriptionAvailable.value = 'MULTI'
|
|
|
|
|
+ needsSave = true
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (needsSave) {
|
|
|
|
|
+ saveLocalPatientReminders()
|
|
|
|
|
+ await saveReminders()
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 如果需要请求订阅
|
|
|
|
|
+ if (shouldRequest) {
|
|
|
|
|
+ await requestSubscription(false, wasEnabledBeforeCheck)
|
|
|
|
|
+ }
|
|
|
|
|
+ } catch (e) {
|
|
|
|
|
+ console.error('[checkSubscriptionStatus] 检查订阅状态失败:', e)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -759,54 +824,13 @@ const onNotificationChange = (e: any) => {
|
|
|
console.log('通知开关更改为:', newVal)
|
|
console.log('通知开关更改为:', newVal)
|
|
|
|
|
|
|
|
if (newVal) {
|
|
if (newVal) {
|
|
|
- // 先将开关设置为开启状态
|
|
|
|
|
- notificationsEnabled.value = true
|
|
|
|
|
- try { saveLocalPatientReminders() } catch (e) { /* ignore */ }
|
|
|
|
|
-
|
|
|
|
|
- // 请求订阅(仅在微信/小程序有效)
|
|
|
|
|
- ; (uni as any).requestSubscribeMessage({
|
|
|
|
|
- tmplIds: [TEMPLATE_ID],
|
|
|
|
|
- success(res: any) {
|
|
|
|
|
- console.log('订阅消息请求成功结果:', res)
|
|
|
|
|
- // res 可能形如 { "ACS7...": 'accept' }
|
|
|
|
|
- const result = res && res[TEMPLATE_ID]
|
|
|
|
|
- if (result === 'accept') {
|
|
|
|
|
- console.log('用户接受了订阅')
|
|
|
|
|
- // 设置一次性订阅开关为可用
|
|
|
|
|
- subscriptionAvailable.value = true
|
|
|
|
|
- // 用户手动同意订阅并保存
|
|
|
|
|
- saveReminders()
|
|
|
|
|
- uni.showToast({ title: '订阅成功', icon: 'success' })
|
|
|
|
|
- // 隐藏权限引导
|
|
|
|
|
- showPermissionGuide.value = false
|
|
|
|
|
- } else {
|
|
|
|
|
- console.log('用户未接受订阅,结果:', result)
|
|
|
|
|
- // 用户拒绝或关闭了弹窗
|
|
|
|
|
- notificationsEnabled.value = false
|
|
|
|
|
- // 用户主动拒绝订阅:更新并保存状态
|
|
|
|
|
- saveReminders()
|
|
|
|
|
- uni.showToast({ title: '订阅被拒绝', icon: 'none' })
|
|
|
|
|
- // 显示权限引导
|
|
|
|
|
- showPermissionGuide.value = true
|
|
|
|
|
- }
|
|
|
|
|
- },
|
|
|
|
|
- fail(err: any) {
|
|
|
|
|
- console.log('订阅消息请求失败:', err)
|
|
|
|
|
- notificationsEnabled.value = false
|
|
|
|
|
- // 请求失败视为未开启订阅(非被动检查),认为是用户操作失败,保存当前状态
|
|
|
|
|
- saveReminders()
|
|
|
|
|
- // 根据错误类型显示不同的提示信息
|
|
|
|
|
- if (err.errCode === 20004) {
|
|
|
|
|
- uni.showToast({ title: '推送权限已关闭', icon: 'none' })
|
|
|
|
|
- // 显示权限引导
|
|
|
|
|
- showPermissionGuide.value = true
|
|
|
|
|
- } else {
|
|
|
|
|
- uni.showToast({ title: '订阅请求失败', icon: 'none' })
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
- })
|
|
|
|
|
|
|
+ // 先将开关设置为开启状态
|
|
|
|
|
+ notificationsEnabled.value = true
|
|
|
|
|
+ saveLocalPatientReminders()
|
|
|
|
|
+ // 调用统一的请求订阅函数(手动触发)
|
|
|
|
|
+ requestSubscription(true)
|
|
|
} else {
|
|
} else {
|
|
|
- // 关闭订阅:不需要额外调用接口,只改变本地记录
|
|
|
|
|
|
|
+ // 关闭订阅
|
|
|
console.log('通知开关已关闭')
|
|
console.log('通知开关已关闭')
|
|
|
notificationsEnabled.value = false
|
|
notificationsEnabled.value = false
|
|
|
// 用户手动关闭开关 -> 保存当前状态
|
|
// 用户手动关闭开关 -> 保存当前状态
|