Files
jiapuapp/pages/tree/t03-member-profile.vue
T
2026-07-21 07:53:08 +08:00

169 lines
10 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.
<!-- 页面编号T-03用途 personId 展示成员档案并进入其真实成员状态 -->
<template>
<view
class="member-page"
:class="{
'member-state--detail': memberState === 'detail',
'member-state--error': memberState === 'error',
}"
>
<ModulePageBackground module="tree" />
<view class="member-page__header">
<PageHeader title="成员档案" :action="memberState === 'detail' && canEdit ? '编辑' : ''" @action="toEdit" />
</view>
<view class="member-context">
<text>{{ genealogyName }}</text>
<text>{{ memberState === "detail" ? "成员身份与亲属关系" : "请重新选择成员" }}</text>
</view>
<view class="member-panel">
<AppLoading v-if="memberState === 'loading'" text="正在读取成员档案" description="请稍候,正在整理成员资料。" />
<view v-else-if="memberState === 'detail' && member" class="member-detail">
<view class="member-heading">
<view class="member-heading__seal"><text>{{ member.name.slice(0, 1) }}</text></view>
<view>
<text>{{ member.name }}</text>
<text> {{ member.generation }} · {{ member.relation }} · {{ member.branch }}</text>
</view>
</view>
<view class="member-status-entry" @click="openMemberState(member.status)">
<text>{{ statusLabel }}</text>
<text>{{ statusDescription }}</text>
<text>查看</text>
</view>
<text class="member-section-title">基本资料</text>
<view v-for="item in details" :key="item.label" class="member-info-row">
<text>{{ item.label }}</text><text>{{ item.value || "未填写" }}</text>
</view>
<text class="member-section-title member-section-title--relation">亲属关系</text>
<view class="member-relatives">
<view v-for="relative in member.relatives" :key="relative.id" @click="openRelative(relative)">
<text>{{ relative.relation }}</text><text>{{ relative.name }}</text>
</view>
<text v-if="!member.relatives.length">尚未记录可查看的亲属</text>
</view>
<view v-if="canEdit" class="member-profile-action" @click="toEdit"><text>完善成员档案</text></view>
</view>
<view v-else class="member-error">
<text>成员档案暂不可用</text>
<text>{{ errorMessage }}</text>
<view class="member-profile-action" @click="toTree"><text>返回世系树</text></view>
</view>
</view>
</view>
</template>
<script setup>
import { computed, ref } from "vue";
import { onLoad } from "@dcloudio/uni-app";
import AppLoading from "@/components/AppLoading.vue";
import ModulePageBackground from "@/components/ModulePageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
import { genealogyContext } from "@/utils/genealogy-context.js";
const genealogyId = ref("");
const personId = ref("");
const memberState = ref("loading");
const member = ref(null);
const errorMessage = ref("");
const genealogyName = ref("汤氏家谱");
const memberFixtures = {
101: {
id: 101, name: "汤文远", generation: 12, relation: "始祖", branch: "主支", generationName: "文字辈",
birthDate: "1940年3月", years: "1940—2012", birthplace: "河南南阳", status: "deceased", canEdit: true,
relatives: [{ id: 102, name: "汤正国", relation: "长子" }, { id: 103, name: "汤正华", relation: "次子" }],
},
102: {
id: 102, name: "汤正国", generation: 13, relation: "长子", branch: "长房", generationName: "正字辈",
birthDate: "1965年5月", years: "1965—", birthplace: "河南洛阳", status: "privacy", canEdit: true,
relatives: [{ id: 101, name: "汤文远", relation: "父亲" }, { id: 104, name: "汤凯", relation: "长子" }],
},
103: {
id: 103, name: "汤正华", generation: 13, relation: "次子", branch: "二房", generationName: "正字辈",
birthDate: "", years: "资料受限", birthplace: "", status: "forbidden", canEdit: false,
relatives: [{ id: 101, name: "汤文远", relation: "父亲" }],
},
};
const details = computed(() => member.value ? [
{ label: "字辈", value: member.value.generationName },
{ label: "出生日期", value: member.value.status === "forbidden" ? "按权限隐藏" : member.value.birthDate },
{ label: "生卒信息", value: member.value.years },
{ label: "祖居地", value: member.value.status === "forbidden" ? "按权限隐藏" : member.value.birthplace },
{ label: "所属支系", value: member.value.branch },
] : []);
const canEdit = computed(() => Boolean(member.value?.canEdit));
const statusLabel = computed(() => ({ privacy: "隐私资料", deceased: "离世纪念", forbidden: "访问受限" })[member.value?.status] || "成员状态");
const statusDescription = computed(() => ({
privacy: "部分资料仅向授权成员展示",
deceased: "查看生平保留与纪念资料说明",
forbidden: "当前账号只能查看有限身份信息",
})[member.value?.status] || "查看成员状态说明");
onLoad((query) => {
genealogyId.value = query.genealogyId || genealogyContext.getCurrentGenealogyId() || "";
personId.value = query.personId || "";
if (genealogyId.value) genealogyContext.setCurrentGenealogyId(genealogyId.value);
if (query.state === "loading") { memberState.value = "loading"; return; }
if (query.state === "error" || !personId.value || !memberFixtures[personId.value]) {
memberState.value = "error";
errorMessage.value = !personId.value ? "没有指定成员,请从世系树重新选择。" : "这位成员不存在或已不属于当前家谱。";
return;
}
member.value = { ...memberFixtures[personId.value] };
memberState.value = "detail";
});
const toEdit = () => {
if (!canEdit.value) { openMemberState("forbidden"); return; }
uni.navigateTo({ url: `/pages/tree/t05-edit-member?genealogyId=${genealogyId.value}&personId=${personId.value}` });
};
const openMemberState = (state) =>
uni.navigateTo({
url: `/pages/tree/t08-member-states?genealogyId=${genealogyId.value}&personId=${personId.value}&state=${state}`,
});
const openRelative = (relative) =>
uni.navigateTo({ url: `/pages/tree/t03-member-profile?genealogyId=${genealogyId.value}&personId=${relative.id}` });
const toTree = () => uni.navigateBack();
</script>
<style scoped lang="scss">
.member-page { display: flex; min-height: 100vh; flex-direction: column; padding-bottom: 28rpx; box-sizing: border-box; background: $paper; }
.member-page__header, .member-context, .member-panel { z-index: 2; }
.member-context { width: calc(100% - 32rpx); margin: 18rpx auto 0; padding: 16rpx 24rpx; box-sizing: border-box; background: url("/static/assets/modules/tree/transparent/t07-search-input-frame.png") center / 100% 100% no-repeat; }
.member-context text { display: block; color: $ink-muted; font-size: 23rpx; line-height: 1.45; }
.member-context text:first-child { color: $ink; font-size: 26rpx; font-weight: 700; }
.member-panel { width: calc(100% - 32rpx); min-height: min(620px, calc((100vw - 16px) * 1.42)); margin: 16rpx auto 0; padding: 9% 8%; box-sizing: border-box; background: url("/static/assets/modules/tree/transparent/t01-state-panel.png") center / 100% 100% no-repeat; }
.member-panel > .app-loading { margin-top: 30%; }
.member-heading { display: flex; align-items: center; gap: 20rpx; }
.member-heading__seal { display: flex; width: 74rpx; height: 74rpx; flex: 0 0 74rpx; align-items: center; justify-content: center; background: url("/static/assets/modules/genealogy/transparent/current-seal-frame.png") center / contain no-repeat; }
.member-heading__seal text { color: #fff7e7; font-size: 28rpx; }
.member-heading > view:last-child text { display: block; color: $ink-muted; font-size: 23rpx; line-height: 1.45; }
.member-heading > view:last-child text:last-child { font-size: 23rpx; }
.member-heading > view:last-child text:first-child { color: $ink; font-family: "STKaiti", "KaiTi", serif; font-size: 36rpx; font-weight: 700; }
.member-status-entry { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 14rpx; margin-top: 18rpx; padding: 18rpx 22rpx; background: url("/static/assets/modules/genealogy/transparent/list-slip-frame.png") center / 100% 100% no-repeat; }
.member-status-entry text { color: $ink-muted; font-size: 22rpx; line-height: 1.4; }
.member-status-entry text:first-child, .member-status-entry text:last-child { color: $brand-red; font-weight: 700; }
.member-section-title { display: block; margin-top: 24rpx; color: $brand-red; font-size: 24rpx; font-weight: 700; }
.member-info-row { display: grid; grid-template-columns: auto minmax(0, 1fr); min-height: 64rpx; align-items: center; gap: 18rpx; margin-top: 8rpx; padding: 8rpx 18rpx; box-sizing: border-box; background: url("/static/assets/modules/tree/transparent/t07-search-input-frame.png") center / 100% 100% no-repeat; }
.member-info-row text { color: $ink-muted; font-size: 23rpx; line-height: 1.45; }
.member-info-row text:last-child { color: $ink; text-align: right; }
.member-relatives { margin-top: 8rpx; font-size: 23rpx; }
.member-relatives > view { display: flex; justify-content: space-between; gap: 20rpx; padding: 12rpx 18rpx; color: $ink; font-size: 23rpx; }
.member-relatives > view text:last-child { color: $brand-red; }
.member-relatives > text { display: block; color: $ink-muted; font-size: 23rpx; line-height: 1.5; }
.member-profile-action { display: flex; min-height: 76rpx; align-items: center; justify-content: center; margin-top: 22rpx; background: url("/static/assets/foundation/transparent/a01-scroll-primary-v3.png") center / 100% 100% no-repeat; }
.member-profile-action text { color: #fff9ed; font-size: 24rpx; font-weight: 700; }
.member-error { margin-top: 30%; text-align: center; }
.member-error > text { display: block; color: $ink-muted; font-size: 24rpx; line-height: 1.55; }
.member-error > text:nth-child(2) { font-size: 24rpx; }
.member-error > text:first-child { color: $ink; font-family: "STKaiti", "KaiTi", serif; font-size: 34rpx; font-weight: 700; }
@media (min-width: 400px) { .member-context, .member-panel { width: calc(100% - 48rpx); } }
</style>