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
+26
View File
@@ -1,3 +1,5 @@
const { tryLoginRenewal } = require('../../utils/subscribe');
const announcementSession = require('../../utils/announcement-session');
const { itemsOf, totalOf } = require('../../utils/list-pagination');
let lastLocationReport = 0;
let locationReportUser = null;
@@ -9,8 +11,10 @@ const { diaryEntry } = require('../../utils/journal');
const { saveScrollPosition, resetScrollOnTabShow } = require('../../utils/scroll-pos');
Page(withDataCache({
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
onResize: function() { this.setData(getLayout()); },
data: {
showAnnouncement:false, announcement:null,
userId: null,
coupleId: null,
@@ -53,6 +57,8 @@ Page(withDataCache({
},
onShow: function() {
this._announcementActive=true;
this.loadAnnouncement();
resetScrollOnTabShow(this, 'index');
const tabBar = this.getTabBar && this.getTabBar();
if (tabBar) tabBar.syncActive();
@@ -72,6 +78,26 @@ Page(withDataCache({
this.fetchIpLocation();
},
onHide: function() { this._announcementActive=false; },
onUnload: function() { this._announcementActive=false; },
loadAnnouncement: function() {
if(this._announcementLoading)return this._announcementLoading;
this._announcementLoading=(async()=>{
try {
const notice=await api.announcement();
if(this._announcementActive===false)return;
const userId=wx.getStorageSync('userId');
const show=announcementSession.shouldShow(notice,userId);
this.setData({announcement:notice, showAnnouncement:show});
if(show)announcementSession.markShown(notice,userId);
} catch(e) {} // 公告读取失败不阻塞首页。
})().finally(()=>{this._announcementLoading=null;});
return this._announcementLoading;
},
closeAnnouncement: function() {
this.setData({showAnnouncement:false});
},
preventNoticeMove: function() {},
// 保存滚动位置
onScroll: function(e) {
this._scrollTop = e.detail.scrollTop;
+3 -1
View File
@@ -1,6 +1,6 @@
<import src="../../templates/journal.wxml" />
<launch-transition />
<view class="app-shell {{bgImage ? 'home-has-background' : ''}}" style="{{layoutStyle}}">
<view capture-bind:tap="onLoginSubscribeTap" class="app-shell {{bgImage ? 'home-has-background' : ''}}" style="{{layoutStyle}}">
<view wx:if="{{bgImage}}" class="j-background"><image src="{{bgImage}}" mode="aspectFill" /><view class="j-background-wash" /></view>
<view class="home-fixed-header"><view class="home-fixed-heading" style="height:{{barHeight}}px;padding-right:{{navSide}}px;"><text class="j-eyebrow">OUR LITTLE WORLD</text><view class="home-handwritten-title"><text class="j-page-title">让所有的爱有迹可循</text></view></view></view>
<scroll-view class="page-bg home-scroll" scroll-y show-scrollbar="{{false}}" refresher-enabled="{{true}}" refresher-triggered="{{refreshing}}" bindrefresherrefresh="onRefresh" bindscroll="onScroll" scroll-top="{{scrollTop}}">
@@ -39,3 +39,5 @@
<view class="j-section" wx:if="{{recentAlbums.length && !statsError}}"><view class="j-section-head"><text>相册里的片段</text><view class="j-link" bindtap="goToAlbum">全部相册 →</view></view><view class="j-photo-strip"><view class="j-photo-print" wx:for="{{recentAlbums}}" wx:key="id" data-id="{{item.id}}" bindtap="openAlbumPreview"><image src="{{item.cover}}" mode="aspectFill" /><text>{{item.title}}</text></view></view></view>
</view></scroll-view>
</view>
<view wx:if="{{showAnnouncement}}" class="notice-overlay" catchtouchmove="preventNoticeMove"><view class="notice-dialog"><text class="notice-label">我们 past · 公告</text><text class="notice-title">{{announcement.title}}</text><scroll-view scroll-y class="notice-content"><text selectable>{{announcement.content}}</text></scroll-view><button class="notice-dismiss" bindtap="closeAnnouncement">知道了</button></view></view>
+2
View File
@@ -55,3 +55,5 @@
.home-has-background .j-section-head { text-shadow:0 1rpx 5rpx rgba(255,253,248,.85); }
.home-has-background .home-couple-panel { padding:24rpx; border:1rpx solid rgba(233,221,208,.65); border-radius:24rpx; background:rgba(255,253,248,.82); }
.notice-overlay {position:fixed;inset:0;z-index:12000;display:flex;align-items:center;justify-content:center;background:rgba(49,36,42,.46);padding:48rpx;box-sizing:border-box;}.notice-dialog{width:100%;max-width:640rpx;background:#FFFCF8;border-radius:36rpx;padding:44rpx;box-sizing:border-box;}.notice-label{display:block;color:#9B7B83;font-size:22rpx;}.notice-title{display:block;font-size:36rpx;color:#64424D;margin:16rpx 0 28rpx;}.notice-content{max-height:50vh;white-space:pre-wrap;font-size:28rpx;line-height:1.8;color:#5F5557;}.notice-dismiss{margin-top:32rpx;background:#667E75;color:#fff;border-radius:20rpx;font-size:28rpx;}