init: initial commit

This commit is contained in:
2026-10-07 09:28:43 +08:00
commit a68a4ef411
251 changed files with 38279 additions and 0 deletions
+176
View File
@@ -0,0 +1,176 @@
const { getLayout } = require('../../utils/layout');
// pages/albums/albums.js
const { api, getImageUrl } = require('../../utils/request');
Page({
onResize: function() { this.setData(getLayout()); },
data: {
loading: true, loadError: false,
albums: [], uploadMode:false,
showMoreModal: false,
showEditModal: false,
currentAlbum: null,
editForm: { title: '', desc: '' }
},
onLoad: function(options) {
this.setData(getLayout());
this.setData({uploadMode: !!(options && options.upload === '1')});
},
onShow: function() {
this.loadAlbums();
},
onPullDownRefresh: async function() {
await this.loadAlbums();
wx.stopPullDownRefresh();
},
// 分享到好友
onShareAppMessage: function() {
return {
title: '让所有的爱有迹可循',
path: '/pages/albums/albums',
imageUrl: '/images/share.png'
};
},
// 分享到朋友圈
onShareTimeline: function() {
return {
title: '让所有的爱有迹可循',
imageUrl: '/images/share.png'
};
},
noop: function() {},
loadAlbums: async function() {
if (this._loading) return;
this._loading = true;
this.setData({ loading: true, loadError: false });
try {
var list = await api.albumList(null, 'GET', true);
list = (list || []).map(function(a) {
a.cover = getImageUrl(a.cover);
a.photo_count = a.photo_count || 0;
// 地理位置:优先显示地址名称,其次显示经纬度
a.location_text = a.location || ((a.lat && a.lng) ? (a.lat + ', ' + a.lng) : '');
return a;
});
this.setData({ albums: list });
} catch(e) { console.error(e); this.setData({ loadError: true }); } finally { this._loading = false; this.setData({ loading: false }); }
},
openAlbum: function(e) {
var id = e.currentTarget.dataset.id;
wx.navigateTo({ url: '/pages/album/album?album_id=' + id + (this.data.uploadMode ? '&upload=1' : '') });
},
// 显示更多菜单
showMoreMenu: function(e) {
var id = e.currentTarget.dataset.id;
var title = e.currentTarget.dataset.title || '默认相册';
var desc = e.currentTarget.dataset.desc || '';
var cover = e.currentTarget.dataset.cover || '';
this.setData({
showMoreModal: true,
currentAlbum: { id: id, title: title, description: desc, cover: cover }
});
},
hideMoreMenu: function() {
this.setData({ showMoreModal: false });
},
// 编辑相册
editAlbum: function() {
var album = this.data.currentAlbum;
if (!album) return;
this.setData({
showMoreModal: false,
showEditModal: true,
editForm: { title: album.title, desc: album.description || '' }
});
},
hideEditModal: function() {
this.setData({ showEditModal: false });
},
onEditTitleInput: function(e) { this.setData({ 'editForm.title': e.detail.value }); },
onEditDescInput: function(e) { this.setData({ 'editForm.desc': e.detail.value }); },
saveAlbumEdit: async function() {
var self = this;
var album = this.data.currentAlbum;
if (!album) return;
var title = this.data.editForm.title;
if (!title) { wx.showToast({ title: '请输入相册标题', icon: 'none' }); return; }
try {
wx.showLoading({ title: '保存中...' });
await api.albumUpdate({
id: album.id,
title: title,
description: this.data.editForm.desc || '',
// 保留原有地理位置
lat: album.lat || 0,
lng: album.lng || 0,
location: album.location || ''
});
wx.hideLoading();
wx.showToast({ title: '已保存 ✨', icon: 'success' });
this.hideEditModal();
this.loadAlbums();
} catch(e) {
wx.hideLoading();
wx.showToast({ title: e.error || '保存失败', icon: 'none' });
}
},
// 删除相册
deleteAlbum: function() {
var self = this;
var album = this.data.currentAlbum;
if (!album) return;
// 从相册列表中查找照片数量
var albums = this.data.albums;
var targetAlbum = albums.find(function(a) { return String(a.id) === String(album.id); });
var count = targetAlbum ? (targetAlbum.photo_count || 0) : 0;
var title = album.title || '该相册';
this.setData({ showMoreModal: false });
if (count > 0) {
wx.showModal({
title: '无法删除',
content: '「' + title + '」中还有 ' + count + ' 张照片,请先删除里面的全部照片后再删除相册',
showCancel: false,
confirmText: '知道了'
});
return;
}
wx.showModal({
title: '确认删除',
content: '确定要删除「' + title + '」吗?',
success: function(res) {
if (res.confirm) {
wx.showLoading({ title: '删除中...' });
api.albumDelete({ id: album.id }).then(function() {
wx.hideLoading();
wx.showToast({ title: '已删除', icon: 'success' });
self.loadAlbums();
}).catch(function(err) {
wx.hideLoading();
wx.showToast({ title: err.error || '删除失败', icon: 'none' });
});
}
}
});
}, goToPublish: function() { wx.navigateTo({ url: '/pages/publish/publish?type=album' }); },
goHome: function() { wx.redirectTo({ url: '/pages/index/index' }); },
goBack: function() { wx.navigateBack(); },
goToProfile: function() { wx.redirectTo({ url: '/pages/profile/profile' }); }
});
+7
View File
@@ -0,0 +1,7 @@
{
"usingComponents": {
"app-nav": "/components/app-nav/app-nav",
"page-state": "/components/page-state/page-state"
},
"enablePullDownRefresh": true
}
+48
View File
@@ -0,0 +1,48 @@
<view class="app-shell app-shell--secondary" style="{{layoutStyle}}">
<launch-transition />
<!-- pages/albums/albums.wxml - 相册列表 -->
<app-nav title="{{uploadMode ? '选择相册' : '相册'}}" back="{{true}}" />
<scroll-view class="page-bg" scroll-y show-scrollbar="{{false}}" bounces="{{true}}">
<view class="j-body"><view class="j-row"><view><text class="j-eyebrow">MOMENTS WE KEEP</text><text class="j-page-title">{{uploadMode ? '选择上传照片的相册' : '照片里的日常'}}</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="loadAlbums" />
<view class="j-album-list" wx:else><view class="j-album-print" wx:for="{{albums}}" wx:key="id" bindtap="openAlbum" data-id="{{item.id}}"><image wx:if="{{item.cover}}" src="{{item.cover}}" mode="aspectFill" /><view wx:else class="j-album-placeholder"><image src="/images/album.svg" /><text>还没有照片</text></view><view class="j-row"><view><text class="j-story-title">{{item.title || '我们的相册'}}</text><text class="j-caption">{{item.photo_count || 0}} 张照片</text></view><view class="j-link j-album-menu" catchtap="showMoreMenu" data-id="{{item.id}}" data-title="{{item.title}}" data-desc="{{item.description}}" data-cover="{{item.cover}}">•••</view></view><text wx:if="{{item.description}}" class="j-caption">{{item.description}}</text></view></view>
<page-state wx:if="{{!loading && !loadError && !albums.length}}" title="相册还空着" description="为旅行、周末或日常,留一本相册" action="创建相册" bind:action="goToPublish" />
</view>
<!-- 操作菜单弹窗 -->
<view class="modal-overlay" wx:if="{{showMoreModal}}" bindtap="hideMoreMenu">
<view class="action-sheet" catchtap="noop">
<view class="action-item" bindtap="editAlbum">
<image src="/images/edit.svg" mode="aspectFit" class="action-icon" />
<text>编辑相册信息</text>
</view>
<view class="action-item danger" bindtap="deleteAlbum">
<image src="/images/delete.svg" mode="aspectFit" class="action-icon" />
<text>删除相册</text>
</view>
<view class="action-cancel" bindtap="hideMoreMenu">取消</view>
</view>
</view>
<!-- 编辑相册弹窗 -->
<view class="modal-overlay" wx:if="{{showEditModal}}" bindtap="hideEditModal">
<view class="modal" catchtap="noop" style="width:90%;max-width:560rpx;">
<button class="modal-close" bindtap="hideEditModal"><image src="/images/close.svg" mode="aspectFit" /></button>
<text class="title">编辑相册</text>
<view class="input-group">
<label>相册标题</label>
<input class="input" placeholder="例如:旅行记录" value="{{editForm.title}}" bindinput="onEditTitleInput" />
</view>
<view class="input-group">
<label>描述(选填)</label>
<input class="input" placeholder="简单描述这个相册" value="{{editForm.desc}}" bindinput="onEditDescInput" />
</view>
<button class="btn btn-primary" bindtap="saveAlbumEdit" hover-class="none">保存</button>
</view>
</view>
</scroll-view>
</view>
+128
View File
@@ -0,0 +1,128 @@
/* pages/albums/albums.wxss */
@import '../../styles/common.wxss';
page { background: linear-gradient(180deg, #F4E2E3 0%, #FAF5EE 55%, #FAF5EE 100%); height: 100vh; overflow: hidden; }
scroll-view.page-bg { height: 100vh; overflow-y: scroll; -webkit-overflow-scrolling: touch; }
.album-grid {
display: flex;
flex-wrap: wrap;
padding: 16rpx 4rpx 300rpx;
}
.album-cell {
width: calc(50% - 8rpx);
margin: 0 4rpx 16rpx 4rpx;
background: white;
border-radius: 20rpx;
overflow: hidden;
box-shadow: 0 2rpx 8rpx rgba(0,0,0,0.04);
position: relative;
box-sizing: border-box;
}
.album-cover {
width: 100%;
height: 260rpx;
background: #f0f0f0;
}
.album-info {
padding: 20rpx 16rpx;
padding-right: 60rpx;
}
.album-name {
font-size: 28rpx;
font-weight: 600;
color: var(--text);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.album-desc {
font-size: 22rpx;
color: var(--text-muted);
margin-top: 4rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.album-count {
font-size: 22rpx;
color: var(--pink);
font-weight: 500;
margin-top: 6rpx;
}
/* 三个点菜单按钮 */
.album-more-btn {
position: absolute;
right: 12rpx;
bottom: 12rpx;
width: 56rpx;
height: 48rpx;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255,255,255,0.85);
border-radius: 24rpx;
z-index: 10;
transition: background 0.2s;
}
.album-more-btn:active {
background: rgba(255,255,255,0.6);
}
.more-dots {
font-size: 28rpx;
font-weight: 700;
color: #999;
letter-spacing: 2rpx;
line-height: 1;
}
/* 操作菜单弹窗 */
.action-sheet {
position: fixed;
bottom: 0;
left: 0;
right: 0;
background: white;
border-radius: 32rpx 32rpx 0 0;
padding: 16rpx 0;
padding-bottom: calc(48rpx + constant(safe-area-inset-bottom));
padding-bottom: calc(48rpx + env(safe-area-inset-bottom));
z-index: 1000;
animation: slideUp 0.25s ease;
}
@keyframes slideUp {
from { transform: translateY(100%); }
to { transform: translateY(0); }
}
.action-item {
display: flex;
align-items: center;
padding: 28rpx 40rpx;
font-size: 30rpx;
color: #333;
}
.action-item .action-icon {
width: 40rpx;
height: 40rpx;
margin-right: 20rpx;
opacity: 0.7;
}
.action-item.danger {
color: #ff4d4f;
}
.action-item.danger .action-icon {
opacity: 1;
}
.action-cancel {
margin: 12rpx 30rpx 0;
padding: 24rpx;
text-align: center;
font-size: 30rpx;
color: #999;
background: #f5f5f5;
border-radius: 20rpx;
}
@import '../../styles/design.wxss';
@import '../../styles/journal.wxss';