343 lines
9.3 KiB
Vue
343 lines
9.3 KiB
Vue
<!-- 页面编号: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>
|