Files
jiapuapp/pages/family/f04-article-list.vue
T

194 lines
5.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-04用途读取并展示当前家谱的谱文列表 -->
<template>
<view class="article-list-page" :class="`article-list-state--${listState}`">
<ModulePageBackground module="family" />
<view class="article-list-header"
><PageHeader
title="谱文"
:action="hasValidContext ? '新建' : ''"
@action="createArticle"
/></view>
<view class="article-list-content">
<view v-if="listState === 'list'" class="article-list-items">
<view
v-for="item in articles"
:key="item.id"
class="article-card"
@click="openArticle(item)"
>
<text class="article-card__title">{{ item.title }}</text>
<text class="article-card__summary">{{
item.summary || item.content
}}</text>
<text class="article-card__meta"
>{{ item.author || "家族成员" }} ·
{{ item.time || "未标注时间" }}</text
>
</view>
</view>
<view v-else class="article-list-state-card">
<text>{{ stateCopy.title }}</text>
<text>{{ stateCopy.copy }}</text>
<AppButton
v-if="!hasValidContext || listState !== 'loading'"
block
:label="stateCopy.action"
@click="handleStateAction"
/>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref } from "vue";
import { onLoad, onShow } from "@dcloudio/uni-app";
import AppButton from "@/components/AppButton.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
import { appApi } from "@/utils/api.js";
import { goBack, openPage } from "@/utils/navigation.js";
const genealogyId = ref("");
const hasValidContext = ref(false);
const listState = ref("loading");
const articles = ref([]);
const stateCopy = computed(() =>
hasValidContext.value
? listState.value === "empty"
? {
title: "还没有谱文",
copy: "新建第一篇谱文,记录值得传承的故事。",
action: "新建谱文",
}
: listState.value === "error"
? {
title: "谱文暂时无法读取",
copy: "请检查网络后重新读取。",
action: "重新读取",
}
: {
title: "正在读取谱文",
copy: "请稍候。",
action: "重新读取",
}
: {
title: "谱文入口无效",
copy: "没有取得有效家谱标识,页面不会展示其他家谱内容。",
action: "返回上一页",
},
);
onLoad((query) => {
genealogyId.value = String(query?.genealogyId || "");
hasValidContext.value = /^[1-9]\d*$/.test(genealogyId.value);
if (hasValidContext.value) void loadArticles();
else listState.value = "invalid";
});
onShow(() => {
if (hasValidContext.value) void loadArticles();
});
const loadArticles = async () => {
listState.value = "loading";
try {
const rows = await appApi.getArticles(genealogyId.value);
articles.value = rows;
listState.value = articles.value.length ? "list" : "empty";
} catch {
listState.value = "error";
}
};
const createArticle = () =>
hasValidContext.value
? openPage("F06", { genealogyId: genealogyId.value, mode: "create" }, "F04")
: Promise.resolve(false);
const openArticle = (item) =>
openPage("F05", { genealogyId: genealogyId.value, articleId: item.id }, "F04");
const handleStateAction = () => {
if (!hasValidContext.value) return goBack();
if (listState.value === "error") return loadArticles();
if (listState.value === "empty") return createArticle();
return undefined;
};
</script>
<style scoped lang="scss">
@import "../../styles/adaptive-frame-profiles.scss";
.article-list-page {
display: flex;
min-height: 100vh;
flex-direction: column;
background: $paper;
}
.article-list-header,
.article-list-content {
z-index: 1;
}
.article-list-content {
padding: 18rpx 24rpx 72rpx;
}
.article-list-items {
margin-top: 24rpx;
}
.article-card {
@include adaptive-family-content;
display: flex;
min-height: 150rpx;
flex-direction: column;
justify-content: center;
box-sizing: border-box;
margin-bottom: 16rpx;
padding: 28rpx;
}
.article-card text {
display: block;
}
.article-card__title {
color: $ink;
font-family: STKaiti, KaiTi, serif;
font-size: clamp(17px, 31rpx, 22px);
font-weight: 700;
}
.article-card__summary {
display: -webkit-box;
margin-top: 9rpx;
overflow: hidden;
color: $ink-muted;
font-size: clamp(15px, 24rpx, 18px);
line-height: 1.45;
overflow-wrap: anywhere;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
.article-card__meta {
margin-top: 10rpx;
color: $brand-red;
font-size: clamp(13px, 21rpx, 16px);
}
.article-list-state-card {
@include adaptive-family-content;
width: 100%;
min-height: 340rpx;
margin-top: 30rpx;
padding: 78rpx 52rpx 50rpx;
text-align: center;
}
.article-list-state-card > text {
display: block;
}
.article-list-state-card > text:first-child {
color: $ink;
font-family: STKaiti, KaiTi, serif;
font-size: clamp(19px, 35rpx, 24px);
font-weight: 700;
}
.article-list-state-card > text:nth-child(2) {
margin-top: 18rpx;
color: $ink-muted;
font-size: clamp(15px, 24rpx, 18px);
line-height: 1.65;
}
.article-list-state-card .app-button {
margin-top: 28rpx;
}
</style>