完成70%
This commit is contained in:
@@ -14,7 +14,7 @@
|
||||
<view v-if="hasValidContext" class="directory-context">
|
||||
<text class="directory-context__name">汤氏家谱</text>
|
||||
<text class="directory-context__meta"
|
||||
>主支 · {{ members.length }} 位成员</text
|
||||
>已加载 {{ members.length }} / {{ total }} 位成员</text
|
||||
>
|
||||
</view>
|
||||
<view
|
||||
@@ -46,10 +46,10 @@
|
||||
<template v-else-if="directoryState === 'list'">
|
||||
<view class="directory-summary"
|
||||
><text>家谱成员</text
|
||||
><text>{{ filteredMembers.length }} 人 · 按世代排列</text></view
|
||||
><text>{{ members.length }} / {{ total }} 人 · 按世代排列</text></view
|
||||
>
|
||||
<view
|
||||
v-for="item in filteredMembers"
|
||||
v-for="item in members"
|
||||
:key="item.id"
|
||||
class="directory-card"
|
||||
@click="openMember(item)"
|
||||
@@ -60,6 +60,13 @@
|
||||
<text class="directory-card__status">{{ memberStatus(item) }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<AppButton
|
||||
v-if="hasMore"
|
||||
block
|
||||
type="secondary"
|
||||
:label="loadingMore ? '正在加载…' : '加载更多成员'"
|
||||
@click="loadMore"
|
||||
/>
|
||||
</template>
|
||||
<view v-else class="directory-state-card">
|
||||
<view
|
||||
@@ -85,61 +92,82 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { computed, ref } from "vue";
|
||||
import { onLoad } from "@dcloudio/uni-app";
|
||||
import { onLoad, 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 { listTreeMemberPresentationFixtures } from "@/data/mock.js";
|
||||
import { appApi, createRequestController, isRequestCancelled } from "@/utils/api.js";
|
||||
import { goBack, openPage } from "@/utils/navigation.js";
|
||||
const genealogyId = ref("");
|
||||
const keyword = ref("");
|
||||
const directoryState = ref("loading");
|
||||
const members = ref([]);
|
||||
const total = ref(0);
|
||||
const pageNum = ref(1);
|
||||
const loadingMore = ref(false);
|
||||
const directoryRequestController = createRequestController();
|
||||
let loadSequence = 0;
|
||||
const hasValidContext = computed(() => Boolean(genealogyId.value));
|
||||
const members = computed(() => listTreeMemberPresentationFixtures(genealogyId.value));
|
||||
const isRestrictedMember = (member) =>
|
||||
["privacy", "forbidden"].includes(member.status);
|
||||
const memberMeta = (member) =>
|
||||
isRestrictedMember(member)
|
||||
? `第 ${member.generation} 世 · ${member.relation}`
|
||||
: `第 ${member.generation} 世 · ${member.generationName} · ${member.branch}`;
|
||||
`第 ${member.generation} 世 · ${member.generationName || "字辈待补"} · ${member.branch}`;
|
||||
const memberStatus = (member) =>
|
||||
isRestrictedMember(member)
|
||||
? member.status === "forbidden"
|
||||
? "访问受限"
|
||||
: "隐私资料"
|
||||
: member.note;
|
||||
const filteredMembers = computed(() => {
|
||||
const value = keyword.value.trim();
|
||||
if (!value) return members.value;
|
||||
return members.value.filter((item) =>
|
||||
`${item.name}${item.relation}${item.generation}${item.generationName || ""}${item.branch || ""}`.includes(value),
|
||||
);
|
||||
});
|
||||
member.personStatus ? `人物状态:${member.personStatus}` : "人物状态待补";
|
||||
const hasMore = computed(() => members.value.length < total.value);
|
||||
|
||||
const loadMembers = async ({ append = false } = {}) => {
|
||||
if (!hasValidContext.value) return;
|
||||
const activeLoad = ++loadSequence;
|
||||
if (append) loadingMore.value = true;
|
||||
else directoryState.value = "loading";
|
||||
try {
|
||||
const result = await appApi.getPersonPage(
|
||||
genealogyId.value,
|
||||
{ pageNum: pageNum.value, pageSize: 10, keyword: keyword.value },
|
||||
{ requestController: directoryRequestController },
|
||||
);
|
||||
if (activeLoad !== loadSequence) return;
|
||||
members.value = append ? [...members.value, ...result.rows] : result.rows;
|
||||
total.value = result.total;
|
||||
directoryState.value = members.value.length ? "list" : "empty";
|
||||
} catch (error) {
|
||||
if (activeLoad !== loadSequence || isRequestCancelled(error)) return;
|
||||
if (!append) members.value = [];
|
||||
directoryState.value = "error";
|
||||
} finally {
|
||||
if (activeLoad === loadSequence) loadingMore.value = false;
|
||||
}
|
||||
};
|
||||
onLoad((query) => {
|
||||
genealogyId.value = String(query.genealogyId || "");
|
||||
directoryState.value =
|
||||
!hasValidContext.value ? "error" : query.state === "loading"
|
||||
? "loading"
|
||||
: query.state === "empty"
|
||||
? "empty"
|
||||
: query.state === "error"
|
||||
? "error"
|
||||
: members.value.length
|
||||
? "list"
|
||||
: "empty";
|
||||
if (!hasValidContext.value || query.state === "error") {
|
||||
directoryState.value = "error";
|
||||
return;
|
||||
}
|
||||
void loadMembers();
|
||||
});
|
||||
const searchMembers = () => {
|
||||
directoryState.value = filteredMembers.value.length ? "list" : "empty";
|
||||
pageNum.value = 1;
|
||||
void loadMembers();
|
||||
};
|
||||
const loadMore = () => {
|
||||
if (loadingMore.value || !hasMore.value) return;
|
||||
pageNum.value += 1;
|
||||
void loadMembers({ append: true });
|
||||
};
|
||||
const retryDirectory = () => {
|
||||
if (!hasValidContext.value) return goBack();
|
||||
directoryState.value = "list";
|
||||
pageNum.value = 1;
|
||||
return loadMembers();
|
||||
};
|
||||
const openMember = (item) =>
|
||||
hasValidContext.value
|
||||
? openPage("T03", { genealogyId: genealogyId.value, personId: String(item.id) }, "T07")
|
||||
: Promise.resolve(false);
|
||||
onUnload(() => {
|
||||
loadSequence += 1;
|
||||
directoryRequestController.abort();
|
||||
});
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
|
||||
|
||||
Reference in New Issue
Block a user