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:
2026-11-03 22:06:47 +08:00
parent 4c9708b562
commit 8be6d9b1ab
98 changed files with 1679 additions and 372 deletions
+17 -3
View File
@@ -1,12 +1,14 @@
const { tryLoginRenewal } = require('../../utils/subscribe');
const { itemsOf, startList, applyList, failList, finishList, withListPagination } = require('../../utils/list-pagination');
const { withDataCache } = require('../../utils/page-cache');
const { getLayout } = require('../../utils/layout');
// pages/punch/punch.js - 情侣打卡
const { api, getImageUrl } = require('../../utils/request');
Page(withDataCache(withListPagination({
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
onResize: function() { this.setData(getLayout()); },
data: { loadError: false,
checkins: [],
checkins: [], smokingVisible: false, smokingKnown: false, smokingSaving: false, smokingError: false,
coupleInfo: null,
myAvatar: '', partnerAvatar: '',
myName: '我', partnerName: 'TA',
@@ -20,8 +22,20 @@ Page(withDataCache(withListPagination({
this.loadCoupleInfo();
this.loadData();
},
onShow: function() { this.loadCoupleInfo(); this.loadData(); },
onShow: function() { this.loadSmokingPreference(); this.loadCoupleInfo(); this.loadData(); },
loadSmokingPreference: async function() {
try { const auth=await api.checkAuth(); this.setData({smokingVisible:Number(auth.user.smoking_card_visible)!==0, smokingKnown:true, smokingError:false}); }
catch(e) { this.setData({smokingError:true}); }
},
toggleSmoking: async function(e) {
if (this.data.smokingSaving || !this.data.smokingKnown) return;
const previous=this.data.smokingVisible;
this.setData({smokingSaving:true});
try { const result=await api.smokingCardVisible({visible:e.detail.value?1:0}); this.setData({smokingVisible:Number(result.card_visible)===1}); }
catch(error) { this.setData({smokingVisible:previous}); wx.showToast({title:error.error||'保存失败,请重试',icon:'none'}); }
finally { this.setData({smokingSaving:false}); }
},
onSmokingUpdated: function() { this.loadData(); },
onPullDownRefresh: async function() {
@@ -120,4 +134,4 @@ Page(withDataCache(withListPagination({
goBack: function() { wx.navigateBack(); },
goHome: function() { wx.switchTab({ url: '/pages/index/index' }); },
goProfile: function() { wx.switchTab({ url: '/pages/profile/profile' }); }
}, 'loadData'), {"loadData": ["checkinList", "checkinStats", "coupleInfo"]}));
}, 'loadData'), {"loadData": ["checkinList", "checkinStats", "coupleInfo"], "loadSmokingPreference":["checkAuth"], "loadCoupleInfo":["coupleInfo"]}));
+3 -2
View File
@@ -1,4 +1,4 @@
<view class="app-shell app-shell--secondary" style="{{layoutStyle}}">
<view capture-bind:tap="onLoginSubscribeTap" class="app-shell app-shell--secondary" style="{{layoutStyle}}">
<launch-transition />
<!-- pages/punch/punch.wxml - 情侣打卡 -->
<app-nav title="打卡" back="{{true}}" />
@@ -25,7 +25,8 @@
</view>
</view>
<smoking-card id="smoking" bind:updated="onSmokingUpdated" />
<view class="smoking-preference"><view><text class="j-small-title">抽烟记录</text><text class="j-caption">显示设置保存到账号,重新安装后仍生效</text></view><switch wx:if="{{smokingKnown}}" checked="{{smokingVisible}}" disabled="{{smokingSaving}}" color="#667E75" bindchange="toggleSmoking" /><text wx:elif="{{smokingError}}" bindtap="loadSmokingPreference">重试</text><text wx:else>加载中</text></view>
<smoking-card wx:if="{{smokingKnown && smokingVisible}}" id="smoking" bind:updated="onSmokingUpdated" />
<!-- 打卡列表 -->
<view class="checkin-cards" wx:if="{{!loading && !loadError && checkins.length > 0}}">
+2
View File
@@ -13,3 +13,5 @@
@import '../../styles/button-theme.wxss';
@import '../../styles/typography.wxss';
.smoking-preference { display:flex; align-items:center; justify-content:space-between; gap:20rpx; margin:26rpx 0; padding:24rpx; background:#F2F7F4; border-radius:24rpx; }