feat: add account deletion, announcements and subscription renewal
Support personal records and persistent smoking visibility. Add upload quota preflight, file cleanup, privacy entry, image caching and revision-based page refresh across the backend, admin and mini program.
This commit is contained in:
+57
-20
@@ -6,9 +6,9 @@
|
||||
*/
|
||||
const { api } = require('./request');
|
||||
|
||||
// 统一使用「每日记录提醒」模板,所有操作都通过这个模板通知
|
||||
// 操作和打卡共用同一模板、同一份一次性授权。
|
||||
const SUBSCRIBE_TEMPLATES = {
|
||||
notify: 'tOaqM_Z6pNSih2pVpaUmP86MgwnDT5ZlwOqd0lgmXP8',
|
||||
notify: 'K_iQMwE_jre0j6QDVL78DZz7wiR1SKVY5h2YJCK6uPU',
|
||||
};
|
||||
|
||||
// 只合并正在进行的授权请求,后续用户点击仍可补充一次性授权。
|
||||
@@ -19,7 +19,7 @@ let _pendingSubscribe = null;
|
||||
* @param {string|string[]} templateTypes - 模板类型或模板类型数组
|
||||
* @returns {Promise<object>} 订阅结果 { templateType: true/false }
|
||||
*/
|
||||
function requestSubscribe(templateTypes) {
|
||||
function requestSubscribe(templateTypes, options = {}) {
|
||||
if (_pendingSubscribe) return _pendingSubscribe;
|
||||
const pending = new Promise((resolve, reject) => {
|
||||
if (!Array.isArray(templateTypes)) {
|
||||
@@ -49,7 +49,7 @@ function requestSubscribe(templateTypes) {
|
||||
});
|
||||
|
||||
// 将授权结果同步到后端
|
||||
syncSubscribeResults(results).then(() => resolve(results), reject);
|
||||
syncSubscribeResults(results, options).then(() => resolve(results), reject);
|
||||
},
|
||||
fail: (err) => {
|
||||
console.error('[subscribe] 请求订阅失败:', err);
|
||||
@@ -57,31 +57,22 @@ function requestSubscribe(templateTypes) {
|
||||
}
|
||||
});
|
||||
});
|
||||
_pendingSubscribe = pending.finally(() => { _pendingSubscribe = null; });
|
||||
_pendingSubscribe = pending.finally(() => { _pendingSubscribe = null; prepareLoginRenewal(); });
|
||||
return _pendingSubscribe;
|
||||
}
|
||||
|
||||
/**
|
||||
* 将订阅结果同步到后端
|
||||
*/
|
||||
function syncSubscribeResults(results) {
|
||||
function syncSubscribeResults(results, options) {
|
||||
return Promise.all(Object.keys(results).filter(type => results[type]).map(type => {
|
||||
return api.subscribeTemplate({template_type:type, template_id:SUBSCRIBE_TEMPLATES[type]}).then(result => {
|
||||
return api.subscribeTemplate({template_type:type, template_id:SUBSCRIBE_TEMPLATES[type]}, options).then(result => {
|
||||
if (!result || !result.success) throw new Error('订阅授权保存失败');
|
||||
wx.setStorageSync('subscribed_notify', true);
|
||||
wx.setStorageSync('subscribed_' + type, true);
|
||||
});
|
||||
}));
|
||||
}
|
||||
|
||||
// 必须由用户点击直接调用;补充的是当前用户接收TA提醒的次数。
|
||||
function requestSubscribeAfterAction(scene) {
|
||||
if (wx.getStorageSync('subscribed_notify') === false || !wx.getStorageSync('coupleId')) return Promise.resolve({});
|
||||
return requestSubscribe('notify').catch(error => {
|
||||
console.warn('[subscribe] 授权或保存失败,下次点击可重试:', error);
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户当前的订阅状态
|
||||
* 从后端获取
|
||||
@@ -93,7 +84,7 @@ async function getSubscribeStatus(forceRefresh = false) {
|
||||
const res = await api.mySubscribeTemplates();
|
||||
const status = {};
|
||||
Object.keys(SUBSCRIBE_TEMPLATES).forEach(type => {
|
||||
status[type] = !!res.templates[type];
|
||||
status[type] = !!SUBSCRIBE_TEMPLATES[type] && res.templates[type] === SUBSCRIBE_TEMPLATES[type];
|
||||
});
|
||||
return status;
|
||||
} catch (e) {
|
||||
@@ -103,6 +94,52 @@ async function getSubscribeStatus(forceRefresh = false) {
|
||||
|
||||
module.exports = {
|
||||
requestSubscribe,
|
||||
requestSubscribeAfterAction,
|
||||
getSubscribeStatus
|
||||
resetLoginRenewal,
|
||||
prepareLoginRenewal,
|
||||
tryLoginRenewal,
|
||||
getSubscribeStatus,
|
||||
isTemplateConfigured: type => !!SUBSCRIBE_TEMPLATES[type],
|
||||
subscribeErrorMessage
|
||||
};
|
||||
|
||||
function subscribeErrorMessage(error) {
|
||||
const code = Number(error && error.errCode);
|
||||
if (code === 20001) return '微信未找到该提醒模板,请核对当前小程序的模板配置';
|
||||
if (code === 20004) return '微信消息通知总开关已关闭,请在小程序设置中开启';
|
||||
if (code === 10002 || code === 10003) return '网络异常,暂时无法订阅,请稍后重试';
|
||||
return error && (error.error || error.message) || '订阅失败,请稍后重试';
|
||||
}
|
||||
|
||||
// Reading settings at login never asks for authorization. Only a later real tap
|
||||
// may renew, and only when WeChat reports a remembered acceptance.
|
||||
let renewal = {generation:0,userId:'',allowed:false,attempted:false};
|
||||
function resetLoginRenewal() {
|
||||
renewal = {generation:renewal.generation+1,userId:'',allowed:false,attempted:false};
|
||||
}
|
||||
function prepareLoginRenewal() {
|
||||
renewal.allowed = false;
|
||||
if (typeof wx.getSetting !== 'function' || typeof wx.getStorageSync !== 'function') return;
|
||||
const userId = String(wx.getStorageSync('userId') || '');
|
||||
if (!userId) return;
|
||||
if (renewal.userId && renewal.userId !== userId) resetLoginRenewal();
|
||||
renewal.userId = userId;
|
||||
const generation = ++renewal.generation;
|
||||
try {
|
||||
wx.getSetting({withSubscriptions:true,success(result){
|
||||
if (renewal.generation !== generation || String(wx.getStorageSync('userId') || '') !== userId) return;
|
||||
const settings = result.subscriptionsSetting || {};
|
||||
renewal.allowed = settings.mainSwitch === true && !!settings.itemSettings && settings.itemSettings[SUBSCRIBE_TEMPLATES.notify] === 'accept';
|
||||
},fail(){ /* Unknown permission means no automatic request. */ }});
|
||||
} catch(error) { /* Unsupported API: keep the manual entry. */ }
|
||||
}
|
||||
function tryLoginRenewal() {
|
||||
const app = typeof getApp === 'function' ? getApp() : null;
|
||||
if (!app || !app.globalData || app.globalData.authState !== 'ready' || !renewal.allowed || renewal.attempted) return;
|
||||
if (!wx.getStorageSync('coupleId') || wx.getStorageSync('subscribed_notify') === false || String(wx.getStorageSync('userId') || '') !== renewal.userId) return;
|
||||
renewal.attempted = true;
|
||||
// Intentionally no await before requesting: preserve this tap's user gesture.
|
||||
return requestSubscribe('notify', {silent:true}).catch(error => {
|
||||
console.warn('[subscribe] 本次静默续订未完成,保留手动订阅入口:',error);
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user