feat(miniapp): add privacy consent and legal pages

Show privacy popup on launch, gate login on legal consent, and link
user agreement and privacy policy pages in the mini program.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
john
2026-07-12 12:18:54 +08:00
parent 8928827291
commit 048f25f580
29 changed files with 817 additions and 8 deletions
+2
View File
@@ -1,5 +1,6 @@
const SESSION_KEY = 'tkmind_session';
const { createUuid, SESSION_COOKIE_NAME } = require('./config');
const { clearLegalConsent } = require('./legal-consent');
let apiBaseUrl = '';
let cookie = '';
@@ -225,6 +226,7 @@ async function logout() {
await portalRequest('/auth/logout', { method: 'POST' });
} finally {
clearSession();
clearLegalConsent();
}
}
+44
View File
@@ -0,0 +1,44 @@
const CONSENT_KEY = 'tkmind_legal_consent';
const CONSENT_VERSION = '1.0';
function getStoredConsent() {
try {
const stored = wx.getStorageSync(CONSENT_KEY);
if (stored && typeof stored === 'object') {
return stored;
}
} catch {
// Ignore storage read errors.
}
return null;
}
function hasAcceptedLegalConsent() {
const stored = getStoredConsent();
return stored?.accepted === true && stored?.version === CONSENT_VERSION;
}
function saveLegalConsent() {
wx.setStorageSync(CONSENT_KEY, {
accepted: true,
version: CONSENT_VERSION,
acceptedAt: new Date().toISOString(),
});
}
function clearLegalConsent() {
wx.removeStorageSync(CONSENT_KEY);
}
function shouldSkipLoginConsent() {
return hasAcceptedLegalConsent();
}
module.exports = {
CONSENT_VERSION,
getStoredConsent,
hasAcceptedLegalConsent,
saveLegalConsent,
clearLegalConsent,
shouldSkipLoginConsent,
};
+51
View File
@@ -0,0 +1,51 @@
function canUsePrivacyApis() {
return typeof wx.getPrivacySetting === 'function';
}
function getPrivacySetting() {
return new Promise((resolve) => {
if (!canUsePrivacyApis()) {
resolve({ needAuthorization: false, privacyContractName: '' });
return;
}
wx.getPrivacySetting({
success(res) {
resolve({
needAuthorization: Boolean(res?.needAuthorization),
privacyContractName: String(res?.privacyContractName || ''),
});
},
fail() {
resolve({ needAuthorization: false, privacyContractName: '' });
},
});
});
}
function openPrivacyContract() {
if (typeof wx.openPrivacyContract !== 'function') {
wx.showToast({ title: '请升级微信版本后查看', icon: 'none' });
return;
}
wx.openPrivacyContract({
fail() {
wx.showToast({ title: '暂时无法打开隐私指引', icon: 'none' });
},
});
}
function registerPrivacyAuthorizationListener(handler) {
if (typeof wx.onNeedPrivacyAuthorization !== 'function') {
return;
}
wx.onNeedPrivacyAuthorization((resolve) => {
handler(resolve);
});
}
module.exports = {
canUsePrivacyApis,
getPrivacySetting,
openPrivacyContract,
registerPrivacyAuthorizationListener,
};