Files
jiapuapp/pages/family/f08-album-detail.vue
T

181 lines
5.0 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">
<ModulePageBackground module="family" />
<view class="album-detail-header"
><PageHeader
title="相册详情"
:action="valid ? '添加' : ''"
custom-back
@back="returnToAlbums"
@action="addPhoto"
/></view>
<view class="album-detail-content">
<view v-if="!valid" class="album-state-card"
><text>相册入口无效</text
><AppButton block label="返回相册列表" @click="returnToAlbums"
/></view>
<view v-else-if="state === 'loading'" class="album-state-card"
><AppLoading text="正在读取相册照片"
/></view>
<view v-else-if="state === 'error'" class="album-state-card"
><text>暂时无法读取相册照片</text
><AppButton block type="secondary" label="重新加载" @click="loadPhotos"
/></view>
<view v-else-if="state === 'empty'" class="album-state-card"
><text>还没有照片</text><text>添加照片后会直接读取服务端相册记录</text
><AppButton block label="添加照片" @click="addPhoto"
/></view>
<view v-else class="photo-list">
<view v-for="item in photos" :key="item.id" class="photo-card"
><text>{{ item.title }}</text
><text v-if="item.description">{{ item.description }}</text
><text v-if="item.meta">{{ item.meta }}</text></view
>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref } from "vue";
import { onLoad, onShow, onUnload } from "@dcloudio/uni-app";
import AppButton from "@/components/AppButton.vue";
import AppLoading from "@/components/AppLoading.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
import {
appApi,
createRequestController,
isRequestCancelled,
} from "@/utils/api.js";
import { goBack, openPage, returnTo } from "@/utils/navigation.js";
const genealogyId = ref("");
const albumId = ref("");
const photos = ref([]);
const state = ref("loading");
const controller = createRequestController();
let active = true;
const valid = computed(
() =>
/^[1-9]\d*$/.test(genealogyId.value) && /^[1-9]\d*$/.test(albumId.value),
);
const loadPhotos = async () => {
if (!valid.value) return;
controller.abort();
state.value = "loading";
try {
const rows = await appApi.getAlbumPhotos(genealogyId.value, albumId.value, {
requestController: controller,
});
if (!active) return;
photos.value = rows
.map((item) => ({
id: String(item.photoId || ""),
title: String(item.photoTitle || "未命名照片"),
description: String(item.photoDesc || ""),
meta: [item.photographer, item.shootTime].filter(Boolean).join(" · "),
}))
.filter((item) => /^[1-9]\d*$/.test(item.id));
state.value = photos.value.length ? "ready" : "empty";
} catch (error) {
if (!active || isRequestCancelled(error)) return;
state.value = "error";
}
};
const returnToAlbums = () =>
/^[1-9]\d*$/.test(genealogyId.value)
? returnTo("F07", { genealogyId: genealogyId.value })
: goBack();
const addPhoto = () =>
valid.value
? openPage(
"F09",
{ genealogyId: genealogyId.value, albumId: albumId.value },
"F08",
)
: Promise.resolve(false);
onLoad((query) => {
genealogyId.value = String(query?.genealogyId || "");
albumId.value = String(query?.albumId || "");
if (valid.value) loadPhotos();
});
onShow(() => {
if (valid.value && state.value !== "loading") loadPhotos();
});
onUnload(() => {
active = false;
controller.abort();
});
</script>
<style scoped lang="scss">
@import "../../styles/adaptive-frame-profiles.scss";
.album-detail-page {
display: flex;
min-height: 100vh;
flex-direction: column;
background: $paper;
}
.album-detail-header,
.album-detail-content {
z-index: 1;
}
.album-detail-content {
padding: 22rpx 24rpx calc(48rpx + env(safe-area-inset-bottom));
}
.album-state-card,
.photo-card {
@include adaptive-family-content;
}
.album-state-card {
width: 100%;
min-height: 340rpx;
padding: 84rpx 44rpx 56rpx;
box-sizing: border-box;
text-align: center;
}
.album-state-card text {
display: block;
}
.album-state-card text:first-child {
color: $ink;
font-family: STKaiti, KaiTi, serif;
font-size: clamp(19px, 36rpx, 24px);
font-weight: 700;
}
.album-state-card text:nth-child(2) {
margin-top: 10rpx;
color: $ink-muted;
font-size: clamp(14px, 23rpx, 17px);
line-height: 1.6;
}
.album-state-card .app-button {
margin-top: 34rpx;
}
.photo-list {
display: flex;
flex-direction: column;
gap: 16rpx;
}
.photo-card {
padding: 28rpx 32rpx;
}
.photo-card text {
display: block;
}
.photo-card text:first-child {
color: $ink;
font-family: STKaiti, KaiTi, serif;
font-size: clamp(17px, 30rpx, 22px);
font-weight: 700;
}
.photo-card text:not(:first-child) {
margin-top: 8rpx;
color: $ink-muted;
font-size: clamp(14px, 22rpx, 17px);
line-height: 1.5;
}
</style>