Files
jiapuapp/pages/family/f08-album-detail.vue
T
2026-07-20 17:23:13 +08:00

343 lines
9.3 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!-- 页面编号F-08用途相册详情与照片墙 -->
<template>
<view class="album-detail-page" :class="`album-state--${albumState}`">
<ModulePageBackground module="family" />
<view class="album-detail-header"><PageHeader title="相册详情" /></view>
<view class="album-detail-content">
<view v-if="albumState === 'expired'" class="album-expired-state">
<view class="album-state-card__body">
<text class="album-state-card__eyebrow">相册状态</text>
<text class="album-state-card__title">相册已失效</text>
<text class="album-state-card__copy">这个相册已无法查看</text>
<AppButton block label="返回相册列表" @click="returnToAlbums" />
</view>
</view>
<template v-else>
<view class="album-heading">
<text class="album-heading__eyebrow">家族影像 · 2024</text>
<text class="album-heading__title">2024 春节团圆</text>
<text class="album-heading__copy"
>一家人围坐团圆让今朝欢聚与祖居旧影留在同一本相册里</text
>
<text class="album-heading__count"
>{{ albumState === "empty" ? "0 张照片" : "5 张照片" }}</text
>
</view>
<view v-if="albumState === 'empty'" class="album-empty-state">
<view class="album-state-card__body">
<text class="album-state-card__eyebrow">照片墙</text>
<text class="album-state-card__title">相册里还没有照片</text>
<text class="album-state-card__copy"
>添加第一张团圆影像把值得珍藏的时刻留在这里</text
>
</view>
</view>
<view v-else class="album-wall">
<view
class="album-photo-tile album-photo-tile--hero"
@click="openPreview(0)"
>
<image
class="album-hero-photo"
:src="photos[0].src"
:alt="photos[0].alt"
mode="aspectFill"
/>
<text class="album-photo-tile__caption">{{ photos[0].caption }}</text>
</view>
<view class="album-photo-grid">
<view
v-for="(photo, index) in photos.slice(1)"
:key="photo.src"
class="album-photo-tile album-photo-tile--grid"
@click="openPreview(index + 1)"
>
<image
class="album-photo-tile__image"
:src="photo.src"
:alt="photo.alt"
mode="aspectFill"
/>
<text class="album-photo-tile__caption">{{ photo.caption }}</text>
</view>
</view>
</view>
<view class="album-upload-action" @click="showUploadNotice">
<AppButton block label="添加照片" />
</view>
</template>
</view>
<view v-if="previewVisible" class="album-preview">
<view class="album-preview__toolbar">
<text class="album-preview__title">照片预览</text>
<view class="album-preview__close" @click="closePreview"><text>关闭</text></view>
</view>
<image
class="album-preview__image"
:src="photos[previewIndex].src"
:alt="photos[previewIndex].alt"
mode="aspectFit"
/>
<view class="album-preview__footer">
<text class="album-preview__position"
>{{ previewIndex + 1 }} / {{ photos.length }}</text
>
<text class="album-preview__caption">{{ photos[previewIndex].caption }}</text>
</view>
</view>
<AppToast :visible="uploadNoticeVisible" :message="uploadNoticeMessage" />
</view>
</template>
<script setup>
import { ref } from "vue";
import { onBackPress, onLoad, onUnload } from "@dcloudio/uni-app";
import AppButton from "@/components/AppButton.vue";
import AppToast from "@/components/AppToast.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
const albumState = ref("normal");
const previewVisible = ref(false);
const previewIndex = ref(0);
const uploadNoticeVisible = ref(false);
const uploadNoticeMessage = "上传照片将在入口接通后开放";
let uploadNoticeTimer;
const photos = [
{ src: "/static/assets/modules/family/f08/f08-reunion-hero.png", alt: "春节团圆时三代家人的合影", caption: "除夕团圆 · 2024" },
{ src: "/static/assets/modules/family/f08/f08-family-portrait.png", alt: "家人在院落前的春节合影", caption: "院前合影 · 2024" },
{ src: "/static/assets/modules/family/f08/f08-reunion-table.png", alt: "家人围坐吃年夜饭", caption: "围桌守岁 · 2024" },
{ src: "/static/assets/modules/family/f08/f08-ancestral-home.png", alt: "祖居院落的复古旧照", caption: "祖居旧影 · 1968" },
{ src: "/static/assets/modules/family/f08/f08-ancestral-portrait.png", alt: "老一辈家人在祖居门前的合影", caption: "门前合影 · 1972" },
];
const openPreview = (index) => {
previewIndex.value = index;
previewVisible.value = true;
albumState.value = "preview";
};
const closePreview = () => {
previewVisible.value = false;
albumState.value = "normal";
};
const showUploadNotice = () => {
uploadNoticeVisible.value = true;
clearTimeout(uploadNoticeTimer);
uploadNoticeTimer = setTimeout(() => {
uploadNoticeVisible.value = false;
}, 1800);
};
const returnToAlbums = () => {
uni.redirectTo({ url: "/pages/family/f07-album-list" });
};
onLoad((query) => {
albumState.value =
query.state === "empty"
? "empty"
: query.state === "preview"
? "preview"
: query.state === "expired"
? "expired"
: "normal";
previewVisible.value = albumState.value === "preview";
});
onBackPress(() => {
if (!previewVisible.value) return false;
closePreview();
return true;
});
onUnload(() => {
clearTimeout(uploadNoticeTimer);
});
</script>
<style scoped lang="scss">
.album-detail-page {
position: relative;
min-height: 100vh;
overflow-x: hidden;
background: $paper;
}
.album-detail-header,
.album-detail-content {
position: relative;
z-index: 2;
}
.album-detail-content {
padding: 22rpx 24rpx calc(48rpx + env(safe-area-inset-bottom));
}
.album-heading {
padding: 18rpx 12rpx 20rpx;
text-align: center;
}
.album-heading text,
.album-state-card__body text,
.album-preview__footer text {
display: block;
}
.album-heading__eyebrow,
.album-state-card__eyebrow {
color: $brand-red;
font-size: 22rpx;
letter-spacing: 2rpx;
}
.album-heading__title,
.album-state-card__title {
margin-top: 8rpx;
color: $ink;
font-family: STKaiti, KaiTi, serif;
font-size: 36rpx;
font-weight: 700;
}
.album-heading__copy,
.album-state-card__copy {
margin-top: 10rpx;
color: $ink-muted;
font-size: 23rpx;
line-height: 1.6;
}
.album-heading__count {
margin-top: 12rpx;
color: #806a51;
font-size: 22rpx;
}
.album-wall {
margin-top: 8rpx;
}
.album-photo-tile {
position: relative;
min-height: 44px;
overflow: hidden;
box-sizing: border-box;
border: 2rpx solid rgba(179, 133, 63, 0.62);
background: rgba(245, 238, 226, 0.86);
box-shadow: 0 8rpx 18rpx rgba(91, 60, 32, 0.12);
}
.album-photo-tile--hero {
width: 100%;
aspect-ratio: 16 / 9;
}
.album-photo-grid {
display: grid;
grid-template-columns: repeat(2, minmax(0, 1fr));
gap: 14rpx;
margin-top: 14rpx;
}
.album-photo-tile--grid {
aspect-ratio: 4 / 3;
}
.album-hero-photo,
.album-photo-tile__image {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
}
.album-photo-tile__caption {
position: absolute;
z-index: 1;
right: 0;
bottom: 0;
left: 0;
padding: 10rpx 12rpx;
background: rgba(48, 35, 25, 0.72);
color: #fffaf0;
font-size: 21rpx;
line-height: 1.35;
}
.album-upload-action {
margin-top: 24rpx;
}
.album-empty-state,
.album-expired-state {
position: relative;
width: 100%;
min-height: 430rpx;
box-sizing: border-box;
border: 20rpx solid transparent;
border-image-source: url("/static/assets/modules/family/transparent/module-content-frame.png");
border-image-slice: 72 fill;
border-image-width: 64rpx;
border-image-repeat: stretch;
}
.album-state-card__body {
padding: 104rpx 40rpx 62rpx;
text-align: center;
}
.album-state-card__body > .app-button {
margin-top: 34rpx;
}
.album-preview {
position: fixed;
z-index: 80;
inset: 0;
display: flex;
flex-direction: column;
background: rgba(24, 17, 13, 0.96);
}
.album-preview__toolbar {
display: flex;
min-height: 96rpx;
align-items: center;
justify-content: space-between;
padding: calc(env(safe-area-inset-top) + 12rpx) 24rpx 12rpx;
}
.album-preview__title {
color: #fffaf0;
font-size: 29rpx;
font-weight: 700;
}
.album-preview__close {
display: flex;
min-width: 44px;
min-height: 44px;
align-items: center;
justify-content: center;
color: #fffaf0;
font-size: 25rpx;
}
.album-preview__image {
width: 100%;
min-height: 0;
flex: 1;
}
.album-preview__footer {
padding: 20rpx 28rpx calc(30rpx + env(safe-area-inset-bottom));
color: #fffaf0;
text-align: center;
}
.album-preview__position {
font-size: 23rpx;
letter-spacing: 2rpx;
}
.album-preview__caption {
margin-top: 8rpx;
color: rgba(255, 250, 240, 0.78);
font-size: 22rpx;
}
@media (max-width: 340px) {
.album-detail-content {
padding-right: 16rpx;
padding-left: 16rpx;
}
.album-photo-grid {
gap: 10rpx;
}
}
</style>