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:
@@ -1,3 +1,4 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { uploadReference } = require('../../utils/file-media');
|
||||
const { itemsOf, startList, current, mergeUnique, applyList, failList, finishList, withListPagination } = require('../../utils/list-pagination');
|
||||
const { currentUserLocation } = require('../../utils/user-location');
|
||||
@@ -6,9 +7,9 @@ const { withDataCache } = require('../../utils/page-cache');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/album/album.js - 日记式分组相册
|
||||
const { api, getImageUrl, API_BASE, uploadFileCompat } = require('../../utils/request');
|
||||
const { requestSubscribeAfterAction } = require('../../utils/subscribe');
|
||||
const { guardStorageSpace } = require('../../utils/storage-guard');
|
||||
Page(withDataCache(withListPagination({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loading: true, loadError: false,
|
||||
batches: [],
|
||||
@@ -317,9 +318,8 @@ Page(withDataCache(withListPagination({
|
||||
var successCount = 0;
|
||||
var failCount = 0;
|
||||
var failReasons = [];
|
||||
var quotaReached = false;
|
||||
|
||||
// ★ 在用户点击手势上下文中提前请求订阅消息(符合微信规范)
|
||||
await requestSubscribeAfterAction('photo');
|
||||
|
||||
try {
|
||||
var albumId = /^-\d+$/.test(String(this.data.albumId)) ? null : this.data.albumId;
|
||||
@@ -372,6 +372,12 @@ Page(withDataCache(withListPagination({
|
||||
failReasons.push('第' + (i+1) + '张: 上传返回无路径 - ' + JSON.stringify(uploadRes));
|
||||
}
|
||||
} catch (e) {
|
||||
if (e && Number(e.code) === 10001) {
|
||||
quotaReached = true;
|
||||
failCount += paths.length - i;
|
||||
wx.hideLoading();
|
||||
break;
|
||||
}
|
||||
failCount++;
|
||||
failReasons.push('第' + (i+1) + '张: ' + (e.error || e.errMsg || e.message || JSON.stringify(e)));
|
||||
// 内容安全违规:明确提示用户
|
||||
@@ -390,7 +396,7 @@ Page(withDataCache(withListPagination({
|
||||
|
||||
var msg = '上传完成 ' + successCount + '/' + paths.length;
|
||||
if (failCount > 0) msg += '(' + failCount + '张失败)';
|
||||
wx.showToast({ title: msg, icon: successCount > 0 ? 'success' : 'none', duration: 2000 });
|
||||
if (!quotaReached) wx.showToast({ title: msg, icon: successCount > 0 ? 'success' : 'none', duration: 2000 });
|
||||
|
||||
// 如果有失败,输出详细原因到控制台
|
||||
if (failCount > 0 && failReasons.length > 0) {
|
||||
|
||||
@@ -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/album/album.wxml -->
|
||||
<app-nav title="相册详情" back="{{true}}" />
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
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/albums/albums.js
|
||||
const { api, getImageUrl } = require('../../utils/request');
|
||||
Page(withDataCache(withListPagination({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: {
|
||||
loading: true, loadError: false,
|
||||
|
||||
@@ -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/albums/albums.wxml - 相册列表 -->
|
||||
<app-nav title="{{uploadMode ? '选择相册' : '相册'}}" back="{{true}}" />
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { uploadReference } = require('../../utils/file-media');
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/checkin-detail/checkin-detail.js
|
||||
const { api, getImageUrl, API_BASE, uploadFileCompat } = require('../../utils/request');
|
||||
const { createSwipeBack } = require('../../utils/util');
|
||||
const { requestSubscribeAfterAction } = require('../../utils/subscribe');
|
||||
const { guardStorageSpace } = require('../../utils/storage-guard');
|
||||
const COOLDOWN = 5000;
|
||||
Page(withDataCache({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loading: true, loadError: false, item: null, logs: [], logsPage: 1, logsTotal: 0, logsHasMore: false, logsLoading: false, logsError: false, freqLabel: '', typeLabel: '', myStreak: 0, partnerStreak: 0, showCheckModal: false, checkPhoto: '', checkNote: '', lastActionTime: 0, detailId: 0, myAvatar: '', partnerAvatar: '', myName: '我', partnerName: 'TA' },
|
||||
|
||||
@@ -180,8 +181,6 @@ Page(withDataCache({
|
||||
this._submittingCheck = true;
|
||||
|
||||
try {
|
||||
// 为本人接收TA的提醒补充授权。
|
||||
await requestSubscribeAfterAction('checkin');
|
||||
var photoPath = '';
|
||||
if (this.data.checkPhoto) {
|
||||
wx.showLoading({ title: '上传中...' });
|
||||
|
||||
@@ -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/checkin-detail/checkin-detail.wxml - 打卡详情 -->
|
||||
<app-nav title="打卡详情" back="{{true}}" />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
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');
|
||||
@@ -6,6 +7,7 @@ const { api, getImageUrl } = require('../../utils/request');
|
||||
const { diaryEntry } = require('../../utils/journal');
|
||||
const { saveScrollPosition, getScrollPosition } = require('../../utils/scroll-pos');
|
||||
Page(withDataCache(withListPagination({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: {
|
||||
loading: true, loadError: false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<import src="../../templates/journal.wxml" />
|
||||
<launch-transition />
|
||||
<view class="app-shell app-shell--secondary" style="{{layoutStyle}}"><app-nav title="日记" back="{{true}}" />
|
||||
<view capture-bind:tap="onLoginSubscribeTap" class="app-shell app-shell--secondary" style="{{layoutStyle}}"><app-nav title="日记" back="{{true}}" />
|
||||
<scroll-view class="page-bg" scroll-y show-scrollbar="{{false}}" bindscrolltolower="onScrollToLower" lower-threshold="100" bindscroll="onScroll" scroll-top="{{scrollTop}}">
|
||||
<view class="j-body"><view class="j-row"><view><text class="j-eyebrow">LIFE IN WORDS</text><text class="j-page-title">生活里的每一页</text></view><button class="j-button j-button-small" bindtap="goToPublish">+ 写日记</button></view>
|
||||
<page-state wx:if="{{loading}}" kind="loading" title="正在翻开日记" /><page-state wx:elif="{{loadError}}" kind="error" title="加载失败" action="重试" bind:action="loadData" />
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { itemsOf, totalOf, mergeUnique } = require('../../utils/list-pagination');
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
const { api, getImageUrl } = require('../../utils/request');
|
||||
Page(withDataCache({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
noop: function() {},
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loadError: false,
|
||||
|
||||
@@ -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 />
|
||||
<app-nav title="日记详情" back="{{true}}" /><view class="page-bg">
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { uploadReference } = require('../../utils/file-media');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
const { api, API_BASE, getImageUrl, uploadFileCompat } = require('../../utils/request');
|
||||
@@ -7,6 +8,7 @@ var MOOD_OPTIONS = ['😊', '🥰', '😢', '😤', '😴', '🤩', '🥺', '
|
||||
var WEATHER_OPTIONS = ['☀️', '⛅', '☁️', '🌧️', '⛈️', '❄️', '🌤️', '🌥️', '🌈', '🌪️', '🌫️', '🌙'];
|
||||
|
||||
Page({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: {
|
||||
editorContent: '', loading: true, loadError: false,
|
||||
|
||||
@@ -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 />
|
||||
<app-nav title="编辑日记" back="{{true}}" />
|
||||
<scroll-view class="page-bg" scroll-y show-scrollbar="{{false}}" style="height:100vh;">
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { itemsOf, totalOf } = require('../../utils/list-pagination');
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
@@ -7,6 +8,7 @@ const { diaryEntry, albumEntry, memoryEntry } = require('../../utils/journal');
|
||||
const { saveScrollPosition, resetScrollOnTabShow } = require('../../utils/scroll-pos');
|
||||
|
||||
Page(withDataCache({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: {
|
||||
stats: null, loading: true, loadError: false, refreshing: false, publishOpen: false,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<import src="../../templates/journal.wxml" />
|
||||
<launch-transition />
|
||||
<view class="app-shell j-handwritten-page" style="{{layoutStyle}}"><view class="j-fixed-header"><view class="j-fixed-heading" style="height:{{barHeight}}px;padding-right:{{navSide}}px;"><text class="j-eyebrow">PAGES OF US</text><text class="j-page-title">我们的生活手账</text></view></view>
|
||||
<view capture-bind:tap="onLoginSubscribeTap" class="app-shell j-handwritten-page" style="{{layoutStyle}}"><view class="j-fixed-header"><view class="j-fixed-heading" style="height:{{barHeight}}px;padding-right:{{navSide}}px;"><text class="j-eyebrow">PAGES OF US</text><text class="j-page-title">我们的生活手账</text></view></view>
|
||||
<scroll-view class="page-bg j-main-scroll" scroll-y show-scrollbar="{{false}}" bindscroll="onScroll" scroll-top="{{scrollTop}}" refresher-enabled="{{true}}" refresher-triggered="{{refreshing}}" bindrefresherrefresh="onRefresh">
|
||||
<view class="j-body"><view class="records-action-row"><text class="j-small-title">一起的日常</text><button class="j-button j-button-small" bindtap="showPublish">+ 记录</button></view>
|
||||
<view class="j-tools records-tools"><view class="j-tool-grid"><view bindtap="goToSongs"><image src="/images/stat-music.svg" /><text>歌曲</text></view><view bindtap="goToCheckin"><image src="/images/stat-check.svg" /><text>打卡</text></view><view bindtap="goToPet"><image src="/images/stat-pet.svg" /><text>宠物</text></view><view bindtap="goToPeriod"><image src="/images/stat-j-flower.svg" /><text>姨姨</text></view></view></view>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/history/history.js
|
||||
const { api } = require('../../utils/request');
|
||||
@@ -23,6 +24,7 @@ var ACTION_CONFIG = {
|
||||
};
|
||||
|
||||
Page({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loadError: false, list: [], page: 1, totalPages: 0, pages: [], loading: true },
|
||||
|
||||
|
||||
@@ -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/history/history.wxml - 情侣操作记录(优化版) -->
|
||||
<app-nav title="操作记录" back="{{true}}" />
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
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/lovewords/lovewords.js - 一起听过的歌
|
||||
const { api } = require('../../utils/request');
|
||||
Page(withDataCache(withListPagination({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loading: true, loadError: false,
|
||||
list: [],
|
||||
|
||||
@@ -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/lovewords/lovewords.wxml - 一起听过的歌 -->
|
||||
<app-nav title="一起听的歌" back="{{true}}" />
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/period/period.js - 姨姨(美柚风格日历模式)
|
||||
const { api } = require('../../utils/request');
|
||||
|
||||
|
||||
Page({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: {
|
||||
// 日历
|
||||
|
||||
@@ -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/period/period.wxml - 姨姨(美柚风格日历模式) -->
|
||||
<app-nav title="姨姨" back="{{true}}" /><view class="period-loading" wx:if="{{accessLoading}}"><page-state kind="loading" title="正在加载姨姨记录" /></view>
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/pet/achievements.js
|
||||
const { api } = require('../../utils/request');
|
||||
|
||||
Page(withDataCache({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loading: true, loadError: false,
|
||||
achievements: [],
|
||||
|
||||
@@ -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/pet/achievements.wxml -->
|
||||
<app-nav title="宠物成就" back="{{true}}" />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/pet/pet.js
|
||||
@@ -20,6 +21,7 @@ const BREED_EMOJIS = {
|
||||
const STAGE_NAMES = ['', '幼犬期', '少年期', '青年期', '成年期', '终极期'];
|
||||
|
||||
Page(withDataCache({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loading: true, loadError: false, needsBinding: false,
|
||||
hasPet: false,
|
||||
|
||||
@@ -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/pet/pet.wxml -->
|
||||
<app-nav title="宠物养成" back="{{true}}" />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { uploadReference } = require('../../utils/file-media');
|
||||
const { itemsOf, totalOf } = require('../../utils/list-pagination');
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
@@ -5,7 +6,6 @@ const { getLayout } = require('../../utils/layout');
|
||||
// pages/profile/profile.js - 与原网站一致的个人中心
|
||||
const { api, getImageUrl } = require('../../utils/request');
|
||||
const { saveScrollPosition, resetScrollOnTabShow } = require('../../utils/scroll-pos');
|
||||
const { requestSubscribe } = require('../../utils/subscribe');
|
||||
const { guardStorageSpace } = require('../../utils/storage-guard');
|
||||
|
||||
function formatStorageBytes(bytes) {
|
||||
@@ -16,6 +16,7 @@ function formatStorageBytes(bytes) {
|
||||
}
|
||||
|
||||
Page(withDataCache({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: {
|
||||
scrollTop: 0,
|
||||
@@ -904,8 +905,6 @@ Page(withDataCache({
|
||||
const { inviteMessage } = this.data;
|
||||
if (!inviteTargetId) { wx.showToast({ title: '请输入对方ID', icon: 'none' }); return; }
|
||||
if (!/^[0-9]{6}$/.test(inviteTargetId)) { wx.showToast({ title: 'ID为6位数字', icon: 'none' }); return; }
|
||||
// 邀请成功且对方接受时,需要通知邀请人,提前申请一次性订阅授权
|
||||
requestSubscribe('notify').catch(function() {});
|
||||
try {
|
||||
wx.showLoading({ title: '发送中...' });
|
||||
const res = await api.invitePartner({ target_user_id: inviteTargetId, message: inviteMessage });
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<view class="app-shell j-handwritten-page" style="{{layoutStyle}}">
|
||||
<view capture-bind:tap="onLoginSubscribeTap" class="app-shell j-handwritten-page" style="{{layoutStyle}}">
|
||||
<launch-transition />
|
||||
<!-- pages/profile/profile.wxml -->
|
||||
<view wx:if="{{!showEditProfileModal && !showEditPartnerModal}}" class="j-fixed-header"><view class="j-fixed-heading" style="height:{{barHeight}}px;padding-right:{{navSide}}px;"><text class="j-eyebrow">MY CORNER</text><text class="j-page-title">我的小角落</text></view></view>
|
||||
|
||||
@@ -325,7 +325,7 @@ scroll-view.page-bg { height: 100vh; overflow-y: scroll; -webkit-overflow-scroll
|
||||
.profile-stats-retry { text-align:center; color:#B74768; font-size:22rpx; padding:24rpx 0 0; }
|
||||
|
||||
/* 存储空间入口卡片。 */
|
||||
.j-storage-card { margin-top:32rpx; padding:26rpx 30rpx; background:#FFFDF8; border:1rpx solid #F1DCE4; border-radius:32rpx; }
|
||||
.j-storage-card { margin-top:32rpx; padding:26rpx 30rpx; background:linear-gradient(135deg,#FFF7F9,#FBE8EF); border:1rpx solid #F1DCE4; border-radius:32rpx; }
|
||||
.j-storage-top { display:flex; justify-content:space-between; align-items:baseline; }
|
||||
.j-storage-label { font-family:'Kaiti SC','STKaiti','KaiTi',cursive; font-size:28rpx; color:#64424D; }
|
||||
.j-storage-val { font-size:26rpx; font-weight:600; color:#B74768; }
|
||||
@@ -335,12 +335,12 @@ scroll-view.page-bg { height: 100vh; overflow-y: scroll; -webkit-overflow-scroll
|
||||
.j-storage-hint { font-size:22rpx; color:#A39386; }
|
||||
.j-storage-cta { font-size:24rpx; color:#B74768; font-weight:500; }
|
||||
|
||||
/* 会员(无限空间)卡片:玫红渐变,突出「无限空间」与到期时间。 */
|
||||
.j-storage-vip { background:linear-gradient(135deg,#FF9EB5,#B74768); border:1rpx solid rgba(255,255,255,.4); border-radius:32rpx; }
|
||||
.j-storage-vip .j-storage-label { color:#FFF; }
|
||||
.j-storage-vip .j-storage-val.j-vip { color:#FFF; font-size:28rpx; }
|
||||
.j-storage-vip .j-storage-hint { color:rgba(255,255,255,.9); }
|
||||
.j-storage-vip .j-storage-cta { color:#FFF; }
|
||||
/* 延续玫粉色系,降低饱和度,深色文字保持清晰。 */
|
||||
.j-storage-vip { background:linear-gradient(135deg,#F8D6E1,#E9A9BF); border:1rpx solid #E8B5C7; border-radius:32rpx; }
|
||||
.j-storage-vip .j-storage-label { color:#6E3549; }
|
||||
.j-storage-vip .j-storage-val.j-vip { color:#6E3549; font-size:28rpx; }
|
||||
.j-storage-vip .j-storage-hint { color:#704052; }
|
||||
.j-storage-vip .j-storage-cta { color:#6E3549; }
|
||||
|
||||
/* 本人与对方资料卡共用完整样式,整卡点击编辑。 */
|
||||
.j-body > .j-profile-summary,
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { uploadReference } = require('../../utils/file-media');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/publish/publish.js - 统一发布页(增强版编辑器)
|
||||
const { api, API_BASE, uploadFileCompat } = require('../../utils/request');
|
||||
const { createSwipeBack } = require('../../utils/util');
|
||||
const { requestSubscribeAfterAction } = require('../../utils/subscribe');
|
||||
const { guardStorageSpace } = require('../../utils/storage-guard');
|
||||
|
||||
var MOOD_OPTIONS = ['😊', '🥰', '😢', '😤', '😴', '🤩', '🥺', '😎', '🤔', '😭', '😋', '😌'];
|
||||
@@ -18,6 +18,7 @@ var TYPE_CONFIG = {
|
||||
};
|
||||
|
||||
Page({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: {
|
||||
type: '',
|
||||
@@ -360,17 +361,6 @@ Page({
|
||||
if (!form.title) { throw new Error('请填写打卡标题'); }
|
||||
}
|
||||
|
||||
// ★ 在用户点击手势上下文中提前请求订阅消息(符合微信规范)
|
||||
// 为本人接收TA的提醒补充授权,拒绝或保存失败也不影响发布
|
||||
var sceneMap = {
|
||||
diary: 'diary', album: 'photo', checkin: 'checkin',
|
||||
timeline: 'timeline', song: 'song'
|
||||
};
|
||||
var scene = sceneMap[type];
|
||||
if (scene) {
|
||||
await requestSubscribeAfterAction(scene);
|
||||
}
|
||||
|
||||
// 再执行异步操作(上传/API调用)
|
||||
if (type === 'timeline') {
|
||||
var editId = this.data.editId;
|
||||
|
||||
@@ -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/publish/publish.wxml - 统一发布页(增强版编辑器) -->
|
||||
<app-nav title="{{titleText}}" back="{{true}}" />
|
||||
|
||||
@@ -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"]}));
|
||||
|
||||
@@ -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}}">
|
||||
|
||||
@@ -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; }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/settings/settings.js
|
||||
const { api, getImageUrl, API_BASE, uploadFileCompat } = require('../../utils/request');
|
||||
const { requestSubscribe, getSubscribeStatus } = require('../../utils/subscribe');
|
||||
const { requestSubscribe, getSubscribeStatus, isTemplateConfigured, subscribeErrorMessage } = require('../../utils/subscribe');
|
||||
const { guardStorageSpace } = require('../../utils/storage-guard');
|
||||
Page({
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
@@ -23,6 +23,7 @@ Page({
|
||||
// 消息通知设置
|
||||
showSubscribeModal: false,
|
||||
subscribeStatus: {},
|
||||
notifyAvailable: typeof isTemplateConfigured === 'function' && isTemplateConfigured('notify'),
|
||||
subscribeItems: [],
|
||||
subscribeLoading: false,
|
||||
|
||||
@@ -63,6 +64,25 @@ Page({
|
||||
wx.switchTab({ url: '/pages/profile/profile' });
|
||||
},
|
||||
|
||||
deleteAccount: async function() {
|
||||
if(this._deletingAccount)return;
|
||||
this._deletingAccount=true;
|
||||
try {
|
||||
const preview=await api.accountDeletionPreview();
|
||||
const counts=preview.summary.counts;
|
||||
const text='已上传文件 '+counts.files+' 个,相册 '+counts.albums+' 个,照片 '+counts.photos+' 张,日记 '+counts.diaries+' 篇,记忆日 '+counts.timeline+' 条,打卡 '+counts.checkins+' 条,抽烟记录 '+counts.smoking+' 条,生理期日记录 '+counts.period+' 条。';
|
||||
const labels={past_song:'歌曲',past_diary_comment:'评论',past_period_record:'生理期周期',past_period_sex_record:'亲密记录',past_storage_order:'订单',past_subscribe_template:'消息订阅'};
|
||||
const more=Object.keys(labels).map(key=>labels[key]+' '+((preview.summary.record_counts||{})[key]||0)+' 条').join(',');
|
||||
const confirm=options=>new Promise(resolve=>wx.showModal({...options,success:r=>resolve(r.confirm),fail:()=>resolve(false)}));
|
||||
if(!await confirm({title:'注销账号前,请确认',content:text+' 其他数据:'+more+'。注销后,账号、所有内容及文件关联会被删除,无法恢复;剩余空间权益将失效。',confirmText:'继续注销',confirmColor:'#B74768'}))return;
|
||||
if(!await confirm({title:'最后一次确认',content:'确定永久注销并删除全部数据?独占文件将从存储中清理;与其他用户重复的物理文件只移除你的关联,不会删除他人的内容。',confirmText:'确认注销',confirmColor:'#B74768'}))return;
|
||||
wx.showLoading({title:'正在注销',mask:true});
|
||||
await api.accountDelete({confirmed:true,confirmation_text:'注销并删除全部数据',confirmation_token:preview.confirmation_token});
|
||||
getApp().finishAccountDeletion();
|
||||
wx.reLaunch({url:'/pages/index/index'});
|
||||
} catch(error) {wx.showToast({title:error.error||'注销失败,请稍后重试',icon:'none',duration:3000});}
|
||||
finally {wx.hideLoading();this._deletingAccount=false;}
|
||||
},
|
||||
// 加载解绑状态
|
||||
loadUnbindStatus: function() {
|
||||
var self = this;
|
||||
@@ -82,7 +102,7 @@ Page({
|
||||
|
||||
noop: function() {},
|
||||
|
||||
// ===== 消息通知管理(统一使用一个模板) =====
|
||||
// ===== 消息通知管理(按场景独立授权) =====
|
||||
showSubscribeModal: async function() {
|
||||
this.setData({ showSubscribeModal: true, subscribeLoading: true });
|
||||
try {
|
||||
@@ -110,6 +130,18 @@ Page({
|
||||
this.setData({ showAboutModal: false });
|
||||
},
|
||||
|
||||
openPrivacyContract: function() {
|
||||
if (typeof wx.openPrivacyContract !== 'function') {
|
||||
wx.showToast({ title: '请升级微信后查看隐私协议', icon: 'none' });
|
||||
return;
|
||||
}
|
||||
wx.openPrivacyContract({
|
||||
fail: function() {
|
||||
wx.showToast({ title: '隐私协议暂时无法打开,请稍后重试', icon: 'none' });
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// ===== 联系我们 =====
|
||||
showContactModal: function() {
|
||||
this.setData({ showContactModal: true });
|
||||
@@ -120,7 +152,12 @@ Page({
|
||||
|
||||
toggleSubscribe: async function(e) {
|
||||
const type = 'notify';
|
||||
const current = this.data.subscribeChecked;
|
||||
if (typeof isTemplateConfigured === 'function' && !isTemplateConfigured(type)) {
|
||||
wx.showToast({title:'该提醒暂未配置模板',icon:'none'});
|
||||
return;
|
||||
}
|
||||
const field = 'subscribeChecked';
|
||||
const current = this.data[field];
|
||||
|
||||
// 防止重复点击
|
||||
if (this._subscribing) return;
|
||||
@@ -130,8 +167,8 @@ Page({
|
||||
// 取消订阅
|
||||
try {
|
||||
await api.unsubscribeTemplate({ template_type: type });
|
||||
this.setData({ subscribeChecked: false });
|
||||
wx.setStorageSync('subscribed_notify', false);
|
||||
this.setData({ [field]: false });
|
||||
wx.setStorageSync('subscribed_' + type, false);
|
||||
wx.showToast({ title: '已关闭通知', icon: 'success' });
|
||||
} catch (e) {
|
||||
wx.showToast({ title: '操作失败', icon: 'none' });
|
||||
@@ -141,33 +178,35 @@ Page({
|
||||
try {
|
||||
const results = await requestSubscribe(type);
|
||||
if (results[type]) {
|
||||
this.setData({ subscribeChecked: true });
|
||||
wx.setStorageSync('subscribed_notify', true);
|
||||
this.setData({ [field]: true });
|
||||
wx.setStorageSync('subscribed_' + type, true);
|
||||
wx.showToast({ title: '已开启通知', icon: 'success' });
|
||||
} else {
|
||||
wx.showToast({ title: '订阅被拒绝,可在设置中重新开启', icon: 'none' });
|
||||
}
|
||||
} catch (e) {
|
||||
wx.showToast({ title: '订阅失败', icon: 'none' });
|
||||
wx.showModal({title:'无法订阅提醒',content:subscribeErrorMessage(e),showCancel:false});
|
||||
}
|
||||
}
|
||||
|
||||
this._subscribing = false;
|
||||
},
|
||||
|
||||
renewSubscribe: async function() {
|
||||
renewSubscribe: async function(e) {
|
||||
const type = 'notify';
|
||||
const field = 'subscribeChecked';
|
||||
if (this._subscribing) return;
|
||||
this._subscribing = true;
|
||||
try {
|
||||
const results = await requestSubscribe('notify');
|
||||
if (results.notify) {
|
||||
this.setData({ subscribeChecked: true });
|
||||
const results = await requestSubscribe(type);
|
||||
if (results[type]) {
|
||||
this.setData({ [field]: true });
|
||||
wx.showToast({ title: '已订阅一次提醒', icon: 'success' });
|
||||
} else {
|
||||
wx.showToast({ title: '本次未授权提醒', icon: 'none' });
|
||||
}
|
||||
} catch (e) {
|
||||
wx.showToast({ title: '订阅失败,请重试', icon: 'none' });
|
||||
wx.showModal({title:'无法订阅提醒',content:subscribeErrorMessage(e),showCancel:false});
|
||||
} finally {
|
||||
this._subscribing = false;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
</view>
|
||||
|
||||
<view class="section-heading">关系与账号</view>
|
||||
<view class="j-profile-setting" wx:if="{{bindingKnown && !hasPartner}}" bindtap="deleteAccount"><view class="setting-info"><view class="j-small-title" style="color:#B74768">注销账号</view><view class="j-caption">未绑定时可注销,确认后删除全部个人数据</view></view><text class="j-link">›</text></view>
|
||||
<!-- 操作记录 -->
|
||||
<view class="j-profile-setting" bindtap="goToHistory">
|
||||
<view class="setting-info">
|
||||
@@ -73,6 +74,14 @@
|
||||
<text class="j-link">›</text>
|
||||
</view>
|
||||
|
||||
<view class="j-profile-setting" bindtap="openPrivacyContract">
|
||||
<view class="setting-info">
|
||||
<view class="j-small-title">隐私协议</view>
|
||||
<view class="j-caption">查看本小程序的隐私保护指引</view>
|
||||
</view>
|
||||
<text class="j-link">›</text>
|
||||
</view>
|
||||
|
||||
<!-- 联系我们 -->
|
||||
<view class="j-profile-setting" bindtap="showContactModal">
|
||||
<view class="setting-info">
|
||||
@@ -133,11 +142,11 @@
|
||||
<text class="subscribe-icon">💕</text>
|
||||
</view>
|
||||
<view class="subscribe-info">
|
||||
<text class="subscribe-name">操作通知</text>
|
||||
<text class="subscribe-desc">TA有新的操作时通知你</text>
|
||||
<text class="subscribe-name">操作与打卡通知</text>
|
||||
<text class="subscribe-desc">{{notifyAvailable ? 'TA有新动态或完成打卡时通知你' : '暂未配置当前小程序的通知模板'}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<switch checked="{{subscribeChecked}}" bindchange="toggleSubscribe" color="#B74768" style="transform:scale(0.75);" />
|
||||
<switch disabled="{{!notifyAvailable}}" checked="{{subscribeChecked}}" bindchange="toggleSubscribe" color="#B74768" style="transform:scale(0.75);" />
|
||||
</view>
|
||||
|
||||
<!-- 状态提示 -->
|
||||
@@ -148,11 +157,11 @@
|
||||
</block>
|
||||
<block wx:else>
|
||||
<text class="tip-icon">💡</text>
|
||||
<text class="tip-text">开启并授权后,可接收一次TA的操作提醒</text>
|
||||
<text class="tip-text">开启并授权后,可接收一次TA的提醒</text>
|
||||
</block>
|
||||
</view>
|
||||
|
||||
<button wx:if="{{subscribeChecked}}" class="subscribe-renew" bindtap="renewSubscribe">订阅一次 TA 的提醒</button>
|
||||
<button wx:if="{{notifyAvailable && subscribeChecked}}" class="subscribe-renew" bindtap="renewSubscribe">订阅一次 TA 的提醒</button>
|
||||
|
||||
<!-- 说明 -->
|
||||
<view class="subscribe-note">
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
Page({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
data:{},
|
||||
onLoad(){this.setData(getLayout());},
|
||||
onResize(){this.setData(getLayout());},
|
||||
|
||||
@@ -1 +1 @@
|
||||
<view class="app-shell app-shell--secondary" style="{{layoutStyle}}"><launch-transition /><app-nav title="抽烟记录" back="{{true}}" /><scroll-view class="page-bg" scroll-y bindscrolltolower="loadMore" lower-threshold="120" show-scrollbar="{{false}}"><view class="c-body"><smoking-card id="smoking" detailed="{{true}}" /></view></scroll-view></view>
|
||||
<view capture-bind:tap="onLoginSubscribeTap" class="app-shell app-shell--secondary" style="{{layoutStyle}}"><launch-transition /><app-nav title="抽烟记录" back="{{true}}" /><scroll-view class="page-bg" scroll-y bindscrolltolower="loadMore" lower-threshold="120" show-scrollbar="{{false}}"><view class="c-body"><smoking-card id="smoking" detailed="{{true}}" /></view></scroll-view></view>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
const { api } = require('../../utils/request');
|
||||
|
||||
@@ -8,7 +10,8 @@ function formatBytes(bytes) {
|
||||
return (bytes / 1024 / 1024 / 1024).toFixed(2) + ' GB';
|
||||
}
|
||||
|
||||
Page({
|
||||
Page(withDataCache({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function () { this.setData(getLayout()); },
|
||||
|
||||
data: {
|
||||
@@ -157,4 +160,4 @@ Page({
|
||||
}
|
||||
},
|
||||
|
||||
});
|
||||
}, {loadInfo:['storageInfo']}));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<view class="app-shell app-shell--secondary j-handwritten-page" style="{{layoutStyle}}">
|
||||
<view capture-bind:tap="onLoginSubscribeTap" class="app-shell app-shell--secondary j-handwritten-page" style="{{layoutStyle}}">
|
||||
<launch-transition />
|
||||
<!-- pages/storage/storage.wxml -->
|
||||
<app-nav title="存储空间" back="{{true}}" />
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { withDataCache } = require('../../utils/page-cache');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/timeline-detail/timeline-detail.js
|
||||
@@ -59,6 +60,7 @@ function calcNearestRepeatDate(eventDate, today, interval, unit) {
|
||||
}
|
||||
|
||||
Page(withDataCache({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loading: true, loadError: false,
|
||||
item: null,
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<view class="app-shell app-shell--secondary {{bgImageUrl ? 'detail-immersive' : ''}}" style="{{layoutStyle}}">
|
||||
<view capture-bind:tap="onLoginSubscribeTap" class="app-shell app-shell--secondary {{bgImageUrl ? 'detail-immersive' : ''}}" style="{{layoutStyle}}">
|
||||
<launch-transition />
|
||||
<!-- pages/timeline-detail/timeline-detail.wxml -->
|
||||
<page-meta page-style="{{bgImageUrl ? 'background: transparent;' : ''}}"></page-meta>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
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');
|
||||
@@ -58,6 +59,7 @@ function calcNearestRepeatDate(eventDate, today, interval, unit) {
|
||||
}
|
||||
|
||||
Page(withDataCache(withListPagination({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: { loading: true, loadError: false,
|
||||
list: []
|
||||
|
||||
@@ -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/timeline/timeline.wxml - 左右交替记忆日 -->
|
||||
<app-nav title="记忆日" back="{{true}}" />
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
const { tryLoginRenewal } = require('../../utils/subscribe');
|
||||
const { getLayout } = require('../../utils/layout');
|
||||
// pages/unbind/unbind.js - 情侣解绑确认页
|
||||
const { api } = require('../../utils/request');
|
||||
|
||||
Page({
|
||||
onLoginSubscribeTap: function() { return tryLoginRenewal(); },
|
||||
onResize: function() { this.setData(getLayout()); },
|
||||
data: {
|
||||
loading: true, loadError: false,
|
||||
|
||||
@@ -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/unbind/unbind.wxml - 情侣解绑确认页 -->
|
||||
<app-nav title="解绑" back="{{true}}" />
|
||||
|
||||
Reference in New Issue
Block a user