|
|
@@ -87,7 +87,7 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
<!-- 权限引导弹窗 -->
|
|
|
<view class="permission-modal" v-if="showPermissionGuide">
|
|
|
<view class="modal-mask" @click="closePermissionGuide"></view>
|
|
|
@@ -97,7 +97,8 @@
|
|
|
</view>
|
|
|
<view class="modal-body">
|
|
|
<view class="modal-text">检测到您可能误关闭了消息通知权限,或之前曾拒绝过授权。{{ '\n' }}消息通知权限能帮助您及时接收血压、血糖等重要健康提醒!{{ '\n' }}
|
|
|
- 若您希望开启通知,请按以下步骤操作{{ '\n' }}(若您无需通知,可点击下方取消按钮):{{ '\n' }}{{ '\n' }}1. 点击下方【去开启】按钮{{ '\n' }}2. 进入【通知管理】选项{{ '\n' }}3. 开启【接收通知】开关{{ '\n' }}4. 确保各项健康提醒均为【接收】状态</view>
|
|
|
+ 若您希望开启通知,请按以下步骤操作{{ '\n' }}(若您无需通知,可点击下方取消按钮):{{ '\n' }}{{ '\n' }}1. 点击下方【去开启】按钮{{ '\n' }}2. 进入【通知管理】选项{{ '\n'
|
|
|
+ }}3. 开启【接收通知】开关{{ '\n' }}4. 确保各项健康提醒均为【接收】状态</view>
|
|
|
</view>
|
|
|
<view class="modal-footer">
|
|
|
<button class="modal-button cancel" @click="closePermissionGuide">取消</button>
|
|
|
@@ -127,7 +128,7 @@
|
|
|
</view>
|
|
|
</view>
|
|
|
</view>
|
|
|
-
|
|
|
+
|
|
|
</template>
|
|
|
|
|
|
<script setup lang="ts">
|
|
|
@@ -199,6 +200,68 @@ const loadUser = () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+// 读取本地 patientReminders(已简化,不包含旧的手动关闭标记)
|
|
|
+
|
|
|
+// 将页面来源识别逻辑抽成函数,便于复用与测试
|
|
|
+const determineEntrySource = () => {
|
|
|
+ try {
|
|
|
+ const pages = (getCurrentPages as any)()
|
|
|
+ console.log('当前页面栈:', pages)
|
|
|
+
|
|
|
+ if (pages && pages.length >= 1) {
|
|
|
+ const currentPage = pages[pages.length - 1]
|
|
|
+ const currentRoute = currentPage?.route || currentPage?.__route || currentPage?.$page?.route
|
|
|
+ const currentOptions = currentPage?.options || {}
|
|
|
+
|
|
|
+ console.log('当前页面路由:', currentRoute)
|
|
|
+ console.log('当前页面参数:', currentOptions)
|
|
|
+
|
|
|
+ // 检查当前页面是否包含 from=subscribe 参数
|
|
|
+ if (currentOptions.from === 'subscribe') {
|
|
|
+ entrySource.value = 'subscribe'
|
|
|
+ console.log('通过当前页面参数识别为订阅消息来源')
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查当前页面是否包含 templateId 相关参数
|
|
|
+ if (currentOptions.templateId === TEMPLATE_ID || currentOptions.template_id === TEMPLATE_ID) {
|
|
|
+ entrySource.value = 'subscribe'
|
|
|
+ console.log('通过当前页面的模板ID参数识别为订阅消息来源')
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pages && pages.length >= 2) {
|
|
|
+ const prev = pages[pages.length - 2]
|
|
|
+ const prevRoute = prev?.route || prev?.__route || prev?.$page?.route
|
|
|
+ console.log('上一页路由:', prevRoute)
|
|
|
+ if (prevRoute && String(prevRoute).includes('pages/public/health/index')) {
|
|
|
+ entrySource.value = 'healthIndex'
|
|
|
+ console.log('识别来源为健康首页')
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ // 如果没有上一页信息,检查小程序启动参数(例如用户通过订阅消息打开)
|
|
|
+ if ((uni as any).getLaunchOptionsSync) {
|
|
|
+ const launch = (uni as any).getLaunchOptionsSync()
|
|
|
+ console.log('启动参数:', launch)
|
|
|
+ if (launch && launch.query) {
|
|
|
+ console.log('查询参数:', launch.query)
|
|
|
+ // 如果你在推送消息里把 from=subscribe 作为参数传入,这里会命中
|
|
|
+ if (launch.query.from === 'subscribe') {
|
|
|
+ entrySource.value = 'subscribe'
|
|
|
+ console.log('通过 from 参数识别为订阅消息来源')
|
|
|
+ }
|
|
|
+ // 有些平台会把 templateId 或其它字段放在 query 中,可据此判断
|
|
|
+ if (launch.query.templateId === TEMPLATE_ID || launch.query.template_id === TEMPLATE_ID) {
|
|
|
+ entrySource.value = 'subscribe'
|
|
|
+ console.log('通过模板ID参数识别为订阅消息来源')
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ } catch (e) {
|
|
|
+ console.error('识别入口来源时出错:', e)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
// 获取当前用户ID (保持为字符串以避免JavaScript Number精度问题)
|
|
|
const currentUserId = computed(() => user.value.id || undefined)
|
|
|
|
|
|
@@ -215,6 +278,9 @@ const entrySourceText = computed(() => {
|
|
|
}
|
|
|
})
|
|
|
|
|
|
+// 标志位:onMounted 是否已执行(某些平台上 onShow 可能早于 onMounted)
|
|
|
+const mountedDone = ref(false)
|
|
|
+
|
|
|
// 各个提醒项的开关控制函数
|
|
|
const toggleBloodPressureReminder = () => {
|
|
|
bloodPressureReminder.value.enabled = !bloodPressureReminder.value.enabled
|
|
|
@@ -275,7 +341,7 @@ const confirmTime = () => {
|
|
|
if (editingReminderType.value) {
|
|
|
const time = timeOptions.value[selectedTimeIndex.value]
|
|
|
let times: string[] = []
|
|
|
-
|
|
|
+
|
|
|
switch (editingReminderType.value) {
|
|
|
case 'bloodPressure':
|
|
|
times = bloodPressureReminder.value.times
|
|
|
@@ -287,7 +353,7 @@ const confirmTime = () => {
|
|
|
times = heartRateReminder.value.times
|
|
|
break
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
if (!times.includes(time)) {
|
|
|
times.push(time)
|
|
|
saveReminders()
|
|
|
@@ -296,132 +362,57 @@ const confirmTime = () => {
|
|
|
closeTimePicker()
|
|
|
}
|
|
|
|
|
|
-onMounted(() => {
|
|
|
+onMounted(async () => {
|
|
|
+ console.log('onMounted')
|
|
|
loadUser()
|
|
|
-
|
|
|
- // 加载提醒设置
|
|
|
+
|
|
|
+ // 加载远端提醒设置
|
|
|
+
|
|
|
+ // 加载提醒设置(等待完成后触发 onShow 的工作逻辑)
|
|
|
loadReminders()
|
|
|
-
|
|
|
+
|
|
|
// 加载用药时间点
|
|
|
loadMedicationTimes()
|
|
|
-
|
|
|
- // 检查用户订阅状态
|
|
|
- // checkSubscriptionStatus()
|
|
|
-
|
|
|
- // 尝试判断来源:优先检查页面栈的上一个页面;若无(直接打开),则检查 launch options 的 query
|
|
|
- try {
|
|
|
- const pages = (getCurrentPages as any)()
|
|
|
- console.log('当前页面栈:', pages)
|
|
|
-
|
|
|
- if (pages && pages.length >= 1) {
|
|
|
- const currentPage = pages[pages.length - 1]
|
|
|
- const currentRoute = currentPage?.route || currentPage?.__route || currentPage?.$page?.route
|
|
|
- const currentOptions = currentPage?.options || {}
|
|
|
-
|
|
|
- console.log('当前页面路由:', currentRoute)
|
|
|
- console.log('当前页面参数:', currentOptions)
|
|
|
-
|
|
|
- // 检查当前页面是否包含 from=subscribe 参数
|
|
|
- if (currentOptions.from === 'subscribe') {
|
|
|
- entrySource.value = 'subscribe'
|
|
|
- console.log('通过当前页面参数识别为订阅消息来源')
|
|
|
- }
|
|
|
-
|
|
|
- // 检查当前页面是否包含 templateId 相关参数
|
|
|
- if (currentOptions.templateId === TEMPLATE_ID || currentOptions.template_id === TEMPLATE_ID) {
|
|
|
- entrySource.value = 'subscribe'
|
|
|
- console.log('通过当前页面的模板ID参数识别为订阅消息来源')
|
|
|
- }
|
|
|
- }
|
|
|
|
|
|
- if (pages && pages.length >= 2) {
|
|
|
- const prev = pages[pages.length - 2]
|
|
|
- const prevRoute = prev?.route || prev?.__route || prev?.$page?.route
|
|
|
- console.log('上一页路由:', prevRoute)
|
|
|
- if (prevRoute && String(prevRoute).includes('pages/public/health/index')) {
|
|
|
- entrySource.value = 'healthIndex'
|
|
|
- console.log('识别来源为健康首页')
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 如果没有上一页信息,检查小程序启动参数(例如用户通过订阅消息打开)
|
|
|
- if ((uni as any).getLaunchOptionsSync) {
|
|
|
- const launch = (uni as any).getLaunchOptionsSync()
|
|
|
- console.log('启动参数:', launch)
|
|
|
- if (launch && launch.query) {
|
|
|
- console.log('查询参数:', launch.query)
|
|
|
- // 如果你在推送消息里把 from=subscribe 作为参数传入,这里会命中
|
|
|
- if (launch.query.from === 'subscribe') {
|
|
|
- entrySource.value = 'subscribe'
|
|
|
- console.log('通过 from 参数识别为订阅消息来源')
|
|
|
- }
|
|
|
- // 有些平台会把 templateId 或其它字段放在 query 中,可据此判断
|
|
|
- if (launch.query.templateId === TEMPLATE_ID || launch.query.template_id === TEMPLATE_ID) {
|
|
|
- entrySource.value = 'subscribe'
|
|
|
- console.log('通过模板ID参数识别为订阅消息来源')
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- console.error('识别入口来源时出错:', e)
|
|
|
- }
|
|
|
-
|
|
|
// 显示来源提示(用于测试),延迟一点以保证 UI 已就绪
|
|
|
try {
|
|
|
setTimeout(() => {
|
|
|
+ // 尝试判断来源:优先检查页面栈的上一个页面;若无(直接打开),则检查 launch options 的 query
|
|
|
+ determineEntrySource()
|
|
|
console.log('入口来源:', entrySource.value, entrySourceText.value)
|
|
|
+ if (entrySource.value === 'unknown') {
|
|
|
+ console.log('入口来源默认为未知')
|
|
|
+ }
|
|
|
}, 250)
|
|
|
} catch (e) {
|
|
|
- // 忽略错误
|
|
|
- }
|
|
|
-
|
|
|
- if (entrySource.value === 'unknown') {
|
|
|
- console.log('入口来源默认为未知')
|
|
|
+ console.error('[reminder] 尝试判断入口来源时出错:', e)
|
|
|
}
|
|
|
+ // 标记 onMounted 已执行
|
|
|
+ mountedDone.value = true
|
|
|
})
|
|
|
|
|
|
// 监听页面显示/隐藏(用于检测用户将小程序/APP切到后台或再次回到前台)
|
|
|
-onShow(() => {
|
|
|
+// 抽取 onShow 的可重用逻辑,支持强制触发(force=true)
|
|
|
+const doOnShowWork = (force = false) => {
|
|
|
+ console.log('onShow')
|
|
|
console.log('[reminder] 页面/应用返回前台(onShow)', { entrySource: entrySource.value })
|
|
|
- loadMedicationTimes() // 加载用药时间点
|
|
|
- // 在页面返回前台时,检查订阅设置;如果用户关闭了通知订阅主开关或对本模板拒绝,则主动关闭本地消息开关
|
|
|
+ // 如果 onMounted 尚未执行完(某些平台上 onShow 可能先于 onMounted),则跳过 onShow 的后续逻辑
|
|
|
+ if (!mountedDone.value && !force) {
|
|
|
+ console.log('[reminder][onShow] onMounted 未完成,跳过 onShow 逻辑')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ loadMedicationTimes() // 加载用药时间点
|
|
|
+ // 在页面返回前台时进行被动检查(仅在发现被关闭/拒绝时强制关闭本地开关,不在接受时修改本地开关或显示引导)
|
|
|
try {
|
|
|
- if (typeof (uni as any).getSetting === 'function') {
|
|
|
- ;(uni as any).getSetting({
|
|
|
- withSubscriptions: true,
|
|
|
- success(res: any) {
|
|
|
- try {
|
|
|
- const subs = res.subscriptionsSetting || {}
|
|
|
- const mainSwitch = subs.mainSwitch
|
|
|
- const itemSettings = subs.itemSettings || {}
|
|
|
- const templateStatus = itemSettings[TEMPLATE_ID]
|
|
|
- console.log('[reminder][onShow] 订阅设置检查结果:', { mainSwitch, templateStatus })
|
|
|
- // 若主开关关闭或模板被拒绝/屏蔽,则主动关闭本地通知开关
|
|
|
- if (mainSwitch === false || templateStatus === 'reject' || templateStatus === 'ban') {
|
|
|
- console.log('[reminder][onShow] 发现订阅被关闭或本模板被拒绝,主动关闭通知开关')
|
|
|
- notificationsEnabled.value = false
|
|
|
- //showPermissionGuide.value = (mainSwitch === false)
|
|
|
- try {
|
|
|
- ;(uni as any).setStorageSync('notificationsEnabled', false)
|
|
|
- } catch (e) {}
|
|
|
- } else {
|
|
|
- // 订阅为开启或未明确拒绝,不修改本地开关(按要求)
|
|
|
- console.log('[reminder][onShow] 订阅设置未发现关闭,不更改本地开关状态')
|
|
|
- }
|
|
|
- } catch (e) {
|
|
|
- console.error('[reminder][onShow] 处理 getSetting 返回值时出错:', e)
|
|
|
- }
|
|
|
- },
|
|
|
- fail(err: any) {
|
|
|
- console.error('[reminder][onShow] 获取订阅设置失败:', err)
|
|
|
- }
|
|
|
- })
|
|
|
- } else {
|
|
|
- console.log('[reminder][onShow] 当前环境不支持 getSetting,跳过订阅检查')
|
|
|
- }
|
|
|
+ checkSubscriptionStatus(true)
|
|
|
} catch (e) {
|
|
|
- console.error('[reminder][onShow] 检查订阅设置时异常:', e)
|
|
|
+ console.error('[reminder][onShow] 被动检查订阅设置时异常:', e)
|
|
|
}
|
|
|
+}
|
|
|
+
|
|
|
+onShow(() => {
|
|
|
+ doOnShowWork()
|
|
|
})
|
|
|
|
|
|
onHide(() => {
|
|
|
@@ -455,12 +446,12 @@ onMounted(() => {
|
|
|
// 额外注册 uni 全局的 App 前后台事件(部分平台需要)
|
|
|
try {
|
|
|
if ((uni as any) && typeof (uni as any).onAppShow === 'function') {
|
|
|
- ;(uni as any).onAppShow((res: any) => {
|
|
|
+ ; (uni as any).onAppShow((res: any) => {
|
|
|
console.log('[reminder][uni.onAppShow] App 回到前台', res)
|
|
|
})
|
|
|
}
|
|
|
if ((uni as any) && typeof (uni as any).onAppHide === 'function') {
|
|
|
- ;(uni as any).onAppHide(() => {
|
|
|
+ ; (uni as any).onAppHide(() => {
|
|
|
console.log('[reminder][uni.onAppHide] App 进入后台')
|
|
|
})
|
|
|
}
|
|
|
@@ -484,42 +475,57 @@ onUnmounted(() => {
|
|
|
*/
|
|
|
const loadReminders = async () => {
|
|
|
if (!currentUserId.value) return
|
|
|
-
|
|
|
+
|
|
|
try {
|
|
|
const res = await getPatientReminderOverview()
|
|
|
if (res && res.data && res.data.code === 200) {
|
|
|
const reminderData = res.data.data?.reminder
|
|
|
-
|
|
|
+
|
|
|
if (reminderData) {
|
|
|
// 更新各个提醒项的状态
|
|
|
bloodPressureReminder.value = {
|
|
|
enabled: reminderData.bloodPressureEnabled,
|
|
|
times: reminderData.bloodPressureTimes || []
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
bloodSugarReminder.value = {
|
|
|
enabled: reminderData.bloodSugarEnabled,
|
|
|
times: reminderData.bloodSugarTimes || []
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
heartRateReminder.value = {
|
|
|
enabled: reminderData.heartRateEnabled,
|
|
|
times: reminderData.heartRateTimes || []
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
medicationReminder.value = {
|
|
|
enabled: reminderData.medicationEnabled,
|
|
|
times: medicationReminder.value.times // 保留已加载的用药时间点
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
// 更新全局消息开关和一次性订阅开关
|
|
|
notificationsEnabled.value = reminderData.notificationEnabled
|
|
|
subscriptionAvailable.value = reminderData.subscriptionAvailable
|
|
|
-
|
|
|
+
|
|
|
try {
|
|
|
- (uni as any).setStorageSync('notificationsEnabled', reminderData.notificationEnabled)
|
|
|
+ const remindersToSave = {
|
|
|
+ bloodPressureReminder: bloodPressureReminder.value,
|
|
|
+ bloodSugarReminder: bloodSugarReminder.value,
|
|
|
+ heartRateReminder: heartRateReminder.value,
|
|
|
+ medicationReminder: medicationReminder.value,
|
|
|
+ notificationsEnabled: notificationsEnabled.value,
|
|
|
+ subscriptionAvailable: subscriptionAvailable.value
|
|
|
+ };
|
|
|
+ (uni as any).setStorageSync('patientReminders', remindersToSave)
|
|
|
+ // 本地保存后触发 onShow 的可重用逻辑,确保订阅/权限等状态被及时检查
|
|
|
+ try {
|
|
|
+ console.log('[loadReminders] 触发 onShow 逻辑')
|
|
|
+ doOnShowWork(true)
|
|
|
+ } catch (err) {
|
|
|
+ console.error('[loadReminders] 触发 onShow 逻辑失败:', err)
|
|
|
+ }
|
|
|
} catch (e) {
|
|
|
- console.error('保存通知开关状态到本地存储失败:', e)
|
|
|
+ console.error('保存提醒设置到本地存储失败:', e)
|
|
|
}
|
|
|
}
|
|
|
} else {
|
|
|
@@ -538,7 +544,7 @@ const saveReminders = async () => {
|
|
|
console.warn('用户未登录,无法保存提醒设置')
|
|
|
return
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
try {
|
|
|
// 构造要保存的提醒设置对象
|
|
|
const payload = {
|
|
|
@@ -552,10 +558,10 @@ const saveReminders = async () => {
|
|
|
heartRateTimes: heartRateReminder.value.times,
|
|
|
medicationEnabled: medicationReminder.value.enabled
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
await savePatientReminder(payload)
|
|
|
console.log('提醒设置保存成功')
|
|
|
-
|
|
|
+
|
|
|
// 同时也保存到本地存储以防万一
|
|
|
try {
|
|
|
const remindersToSave = {
|
|
|
@@ -566,9 +572,8 @@ const saveReminders = async () => {
|
|
|
notificationsEnabled: notificationsEnabled.value,
|
|
|
subscriptionAvailable: subscriptionAvailable.value
|
|
|
}
|
|
|
- ;(uni as any).setStorageSync('patientReminders', remindersToSave)
|
|
|
- ;(uni as any).setStorageSync('notificationsEnabled', notificationsEnabled.value)
|
|
|
-
|
|
|
+ ; (uni as any).setStorageSync('patientReminders', remindersToSave)
|
|
|
+
|
|
|
// 通知首页更新打卡任务
|
|
|
uni.$emit('reminderSettingsUpdated')
|
|
|
} catch (e) {
|
|
|
@@ -580,6 +585,25 @@ const saveReminders = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * 将当前 in-memory 提醒状态保存到本地 storage(只使用 patientReminders 键)
|
|
|
+ */
|
|
|
+const saveLocalPatientReminders = () => {
|
|
|
+ try {
|
|
|
+ const remindersToSave = {
|
|
|
+ bloodPressureReminder: bloodPressureReminder.value,
|
|
|
+ bloodSugarReminder: bloodSugarReminder.value,
|
|
|
+ heartRateReminder: heartRateReminder.value,
|
|
|
+ medicationReminder: medicationReminder.value,
|
|
|
+ notificationsEnabled: notificationsEnabled.value,
|
|
|
+ subscriptionAvailable: subscriptionAvailable.value
|
|
|
+ }
|
|
|
+ ; (uni as any).setStorageSync('patientReminders', remindersToSave)
|
|
|
+ } catch (e) {
|
|
|
+ console.error('保存提醒设置到本地存储失败:', e)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* 加载用药时间点
|
|
|
*/
|
|
|
@@ -598,52 +622,90 @@ const loadMedicationTimes = async () => {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-const checkSubscriptionStatus = () => {
|
|
|
+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)
|
|
|
-
|
|
|
- // 检查订阅消息设置
|
|
|
- if (res.subscriptionsSetting) {
|
|
|
- console.log('[checkSubscriptionStatus] 订阅设置详情:', JSON.stringify(res.subscriptionsSetting, null, 2))
|
|
|
-
|
|
|
- // 检查主开关
|
|
|
- const mainSwitch = res.subscriptionsSetting.mainSwitch
|
|
|
- console.log(`[checkSubscriptionStatus] 订阅主开关状态: ${mainSwitch ? '已开启(用户允许接收通知)' : '已关闭(用户禁止接收所有通知)'}`)
|
|
|
-
|
|
|
- // 检查针对特定模板的设置
|
|
|
- const itemSettings = res.subscriptionsSetting.itemSettings || {}
|
|
|
- const templateStatus = itemSettings[TEMPLATE_ID]
|
|
|
- console.log(`[checkSubscriptionStatus] 模板 ${TEMPLATE_ID} 状态:`, templateStatus)
|
|
|
-
|
|
|
- // 如果主开关关闭或特定模板被拒绝,则更新本地状态
|
|
|
- if (mainSwitch === false || templateStatus === 'reject' || templateStatus === 'ban') {
|
|
|
- console.log('[checkSubscriptionStatus] 用户关闭了订阅设置,正在更新本地状态')
|
|
|
- notificationsEnabled.value = false
|
|
|
- // 显示权限引导
|
|
|
- showPermissionGuide.value = (mainSwitch === false)
|
|
|
- try {
|
|
|
- (uni as any).setStorageSync('notificationsEnabled', false)
|
|
|
- } catch (e) {
|
|
|
- console.error('[checkSubscriptionStatus] 更新存储失败:', e)
|
|
|
+ try {
|
|
|
+ // 额外输出可序列化的 JSON 版本,方便在日志中完整查看返回结构
|
|
|
+ console.log('[checkSubscriptionStatus] 用户设置(JSON):', JSON.stringify(res, null, 2))
|
|
|
+ } catch (err) {
|
|
|
+ console.error('[checkSubscriptionStatus] 无法序列化 getSetting 返回值:', err)
|
|
|
+ }
|
|
|
+
|
|
|
+ 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 (mainSwitch === true && templateStatus === 'accept') {
|
|
|
- console.log('[checkSubscriptionStatus] 用户开启了订阅设置,正在更新本地状态')
|
|
|
- notificationsEnabled.value = true
|
|
|
- showPermissionGuide.value = false
|
|
|
- try {
|
|
|
- (uni as any).setStorageSync('notificationsEnabled', true)
|
|
|
- } catch (e) {
|
|
|
- console.error('[checkSubscriptionStatus] 更新存储失败:', 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)
|
|
|
}
|
|
|
+ } else {
|
|
|
+ console.log('[checkSubscriptionStatus] 响应中未找到订阅设置')
|
|
|
}
|
|
|
- } else {
|
|
|
- console.log('[checkSubscriptionStatus] 响应中未找到订阅设置')
|
|
|
+ } catch (e) {
|
|
|
+ console.error('[checkSubscriptionStatus] 处理返回值时出错:', e)
|
|
|
}
|
|
|
},
|
|
|
fail: (err: any) => {
|
|
|
@@ -695,54 +757,59 @@ const closePermissionGuide = () => {
|
|
|
const onNotificationChange = (e: any) => {
|
|
|
const newVal = e?.detail?.value
|
|
|
console.log('通知开关更改为:', newVal)
|
|
|
-
|
|
|
+
|
|
|
if (newVal) {
|
|
|
- // 先将开关设置为开启状态
|
|
|
- notificationsEnabled.value = true
|
|
|
-
|
|
|
- // 请求订阅(仅在微信/小程序有效)
|
|
|
- ;(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 = 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()
|
|
|
- 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' })
|
|
|
+ // 根据错误类型显示不同的提示信息
|
|
|
+ if (err.errCode === 20004) {
|
|
|
+ uni.showToast({ title: '推送权限已关闭', icon: 'none' })
|
|
|
+ // 显示权限引导
|
|
|
+ showPermissionGuide.value = true
|
|
|
+ } else {
|
|
|
+ uni.showToast({ title: '订阅请求失败', icon: 'none' })
|
|
|
+ }
|
|
|
}
|
|
|
- }
|
|
|
- })
|
|
|
+ })
|
|
|
} else {
|
|
|
// 关闭订阅:不需要额外调用接口,只改变本地记录
|
|
|
console.log('通知开关已关闭')
|
|
|
notificationsEnabled.value = false
|
|
|
+ // 用户手动关闭开关 -> 保存当前状态
|
|
|
saveReminders()
|
|
|
uni.showToast({ title: '已关闭通知', icon: 'none' })
|
|
|
// 隐藏权限引导
|
|
|
@@ -845,21 +912,25 @@ const onNotificationChange = (e: any) => {
|
|
|
border-radius: 12rpx;
|
|
|
margin-top: 20rpx;
|
|
|
}
|
|
|
+
|
|
|
.notification-label {
|
|
|
font-size: 32rpx;
|
|
|
color: #000;
|
|
|
}
|
|
|
+
|
|
|
.template-info {
|
|
|
margin-top: 12rpx;
|
|
|
padding: 0 10rpx;
|
|
|
color: #666;
|
|
|
font-size: 24rpx;
|
|
|
}
|
|
|
+
|
|
|
.tmpl-title {
|
|
|
display: block;
|
|
|
font-size: 26rpx;
|
|
|
color: #333;
|
|
|
}
|
|
|
+
|
|
|
.tmpl-meta {
|
|
|
display: block;
|
|
|
font-size: 22rpx;
|
|
|
@@ -918,7 +989,8 @@ const onNotificationChange = (e: any) => {
|
|
|
font-size: 28rpx;
|
|
|
color: #666;
|
|
|
line-height: 1.5;
|
|
|
- white-space: pre-line; /* 添加这行来支持换行 */
|
|
|
+ white-space: pre-line;
|
|
|
+ /* 添加这行来支持换行 */
|
|
|
}
|
|
|
|
|
|
.modal-footer {
|