Files
jiapuapp/pages/genealogy/g09-my-applications.vue
T
2026-07-23 08:24:07 +08:00

395 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.
<!-- 页面编号G-09用途我的家谱申请列表与空/失败状态 -->
<template>
<view class="application-page">
<GenealogyPageBackground />
<view class="application-page__header">
<PageHeader title="我的申请" custom-back @back="requestBack" />
</view>
<view
class="application-content"
:class="{
'application-state--list': applicationState === 'list',
'application-state--empty': applicationState === 'empty',
'application-state--error': applicationState === 'error',
}"
>
<template v-if="applicationState === 'list'">
<view class="application-intro">
<text>入谱申请进度</text><text>审核结果会同步到消息中心</text>
</view>
<view
v-for="item in applications"
:key="item.id"
class="application-card"
>
<view class="application-card__body">
<text class="application-card__name">{{ item.genealogyName }}</text>
<text class="application-card__time">{{ item.appliedAt }}</text>
<text class="application-card__relation">{{ item.relation }}</text>
<text
class="application-card__status"
:class="`application-card__status--${item.status.toLowerCase()}`"
>{{ statusLabel(item.status) }}</text
>
<text class="application-card__hint">{{
statusHint(item.status)
}}</text>
<view
v-if="actionFor(item)"
class="application-card__action"
@click="handleApplicationAction(item)"
>{{ actionFor(item) }}</view
>
</view>
</view>
</template>
<AppLoading
v-else-if="applicationState === 'loading'"
text="正在整理申请记录"
description="请稍候,正在同步审核状态。"
/>
<view v-else class="application-state-card">
<view class="application-state-card__copy">
<text>{{ stateTitle }}</text>
<text>{{ stateCopy }}</text>
</view>
</view>
<view
v-if="applicationState !== 'list' && applicationState !== 'loading'"
class="application-page__action"
@click="
applicationState === 'error' ? loadApplications({}) : toSearch()
"
>
<text>{{
applicationState === "error" ? "重新查看" : "查找公开家谱"
}}</text>
</view>
</view>
<AppDialog
:visible="!!withdrawTarget"
title="预览撤回效果"
:message="
withdrawTarget
? `当前只更新本页对“${withdrawTarget.genealogyName}”的撤回预览,不会向服务器提交;真实申请仍可能处于审核中。`
: ''
"
confirm-text="查看本地效果"
cancel-text="暂不撤回"
show-cancel
:close-on-mask="false"
@confirm="confirmWithdraw"
@cancel="cancelWithdraw"
/>
</view>
</template>
<script setup>
import { computed, ref } from "vue";
import { onBackPress, onLoad } from "@dcloudio/uni-app";
import AppDialog from "@/components/AppDialog.vue";
import AppLoading from "@/components/AppLoading.vue";
import GenealogyPageBackground from "@/components/GenealogyPageBackground.vue";
import PageHeader from "@/components/PageHeader.vue";
import { findGenealogyFixture } from "@/data/mock.js";
import { handleBackPress, openPage, runBackGuard } from "@/utils/navigation.js";
const applications = ref([]);
const applicationState = ref("loading");
const errorMessage = ref("");
const withdrawTarget = ref(null);
const genealogyNameFor = (genealogyId) =>
findGenealogyFixture(genealogyId)?.name || "未知家谱";
const applicationSamples = [
{
id: "pending-2003",
genealogyId: "2003",
genealogyName: genealogyNameFor("2003"),
relation: "自述为汤正华堂侄",
appliedAt: "今天 10:24",
status: "PENDING",
},
{
id: "approved-1002",
genealogyId: "1002",
genealogyName: genealogyNameFor("1002"),
relation: "祖居河南汝南",
appliedAt: "昨天 18:02",
status: "APPROVED",
},
{
id: "rejected-2004",
genealogyId: "2004",
genealogyName: genealogyNameFor("2004"),
relation: "补充材料不足",
appliedAt: "7月12日 09:18",
status: "REJECTED",
},
];
const statusLabel = (status) =>
({
PENDING: "审核中",
APPROVED: "已通过",
REJECTED: "未通过",
LOCAL_WITHDRAWN: "本地撤回预览",
})[status] || "状态未知";
const statusHint = (status) =>
({
PENDING: "管理员尚未处理,可在审核前撤回",
APPROVED: "申请已通过,可进入这部家谱",
REJECTED: "请修改关系说明后重新提交",
LOCAL_WITHDRAWN: "尚未提交服务器,真实申请仍可能处于审核中",
})[status] || "";
const actionFor = (item) =>
({ PENDING: "预览撤回效果", APPROVED: "进入家谱", REJECTED: "修改后重新提交" })[
item.status
] || "";
const stateTitle = computed(() =>
applicationState.value === "empty"
? "还没有入谱申请"
: applicationState.value === "loading"
? "正在整理申请记录"
: "申请记录暂时无法读取",
);
const stateCopy = computed(() =>
applicationState.value === "empty"
? "从家谱搜索提交的申请会显示在这里;邀请码本地校验不会生成申请记录。"
: applicationState.value === "loading"
? "请稍候,正在同步审核状态。"
: errorMessage.value || "请检查网络后重新查看。",
);
const loadApplications = (query = {}) => {
applicationState.value = "loading";
errorMessage.value = "";
if (query.state === "empty") {
applicationState.value = "empty";
return;
}
if (query.state === "error") {
applicationState.value = "error";
return;
}
if (query.state === "loading") {
applicationState.value = "loading";
return;
}
applications.value = applicationSamples.map((item) => ({ ...item }));
if (query.status) {
const requestedStatus = String(query.status).toUpperCase();
applications.value = applications.value.filter(
(item) => item.status === requestedStatus,
);
if (!applications.value.length) applicationState.value = "empty";
}
if (applicationState.value !== "empty") applicationState.value = "list";
};
onLoad(loadApplications);
const requestBack = () =>
runBackGuard({
transientOpen: Boolean(withdrawTarget.value),
"close-transient": cancelWithdraw,
});
onBackPress((event) => handleBackPress(event, requestBack));
const handleApplicationAction = (item) => {
if (item.status === "APPROVED")
return openPage(
"G05",
{ genealogyId: String(item.genealogyId) },
"G09",
);
if (item.status === "REJECTED")
return openPage(
"G08",
{ genealogyId: String(item.genealogyId), source: "search" },
"G09",
);
if (item.status === "PENDING") withdrawTarget.value = item;
};
const cancelWithdraw = () => {
withdrawTarget.value = null;
};
const confirmWithdraw = () => {
const target = applications.value.find(
(item) => item.id === withdrawTarget.value?.id,
);
if (target) target.status = "LOCAL_WITHDRAWN";
cancelWithdraw();
};
const toSearch = () => openPage("G06", {}, "G09");
</script>
<style scoped lang="scss">
@use "../../styles/adaptive-frame-profiles.scss" as adaptive;
.application-page {
display: flex;
min-height: 100vh;
flex-direction: column;
background: $paper;
}
.application-page__header {
z-index: 3;
}
.application-content {
z-index: 2;
padding: 28rpx 24rpx 60rpx;
}
.application-intro {
display: flex;
align-items: baseline;
justify-content: space-between;
margin: 0 8rpx 20rpx;
}
.application-intro text:first-child {
color: $ink;
font-family: "STKaiti", "KaiTi", serif;
font-size: 31rpx;
font-weight: 700;
}
.application-intro text:last-child {
color: $ink-muted;
font-size: 24rpx;
}
.application-card {
@include adaptive.adaptive-genealogy-list-card;
display: grid;
width: 100%;
min-height: 210rpx;
margin-bottom: 12rpx;
}
.application-card__body {
display: grid;
min-width: 0;
min-height: 174rpx;
grid-template-columns: minmax(0, 1fr) auto;
gap: 8rpx 14rpx;
padding: 26rpx 28rpx 22rpx 40rpx;
box-sizing: border-box;
}
.application-card__name {
grid-row: 1;
grid-column: 1;
align-self: start;
justify-self: start;
color: $ink;
font-family: "STKaiti", "KaiTi", serif;
font-size: 30rpx;
font-weight: 700;
}
.application-card__time {
grid-row: 1;
grid-column: 2;
align-self: start;
justify-self: end;
margin-top: 3rpx;
color: #998873;
font-size: 23rpx;
}
.application-card__relation {
display: block;
grid-row: 2;
grid-column: 1 / -1;
align-self: start;
justify-self: start;
margin-top: 0;
color: $ink-muted;
font-size: 24rpx;
}
.application-card__status {
grid-row: 2;
grid-column: 2;
align-self: center;
justify-self: end;
margin-right: 3%;
color: $brand-red;
font-size: 25rpx;
font-weight: 700;
}
.application-card__status--approved {
color: #537368;
}
.application-card__status--rejected {
color: #7e6f62;
}
.application-card__hint {
grid-row: 3;
grid-column: 1;
align-self: center;
justify-self: start;
margin-bottom: 4rpx;
color: #766653;
font-size: 23rpx;
}
.application-card__action {
z-index: 2;
display: flex;
grid-row: 3;
grid-column: 2;
align-self: center;
justify-self: end;
min-height: 54rpx;
align-items: center;
margin-right: 2%;
margin-bottom: 0;
color: $brand-red;
font-size: 23rpx;
font-weight: 700;
white-space: nowrap;
}
.application-state-card {
@include adaptive.adaptive-genealogy-list-card;
display: flex;
width: 100%;
min-height: 228rpx;
align-items: center;
justify-content: center;
margin-top: 80rpx;
padding: 48rpx 12%;
box-sizing: border-box;
}
.application-state-card__copy {
display: flex;
flex-direction: column;
justify-content: center;
text-align: center;
}
.application-state-card__copy text:first-child {
color: $ink;
font-family: "STKaiti", "KaiTi", serif;
font-size: 31rpx;
font-weight: 700;
}
.application-state-card__copy text:last-child {
margin-top: 16rpx;
color: $ink-muted;
font-size: 24rpx;
line-height: 1.6;
}
.application-page__action {
display: flex;
width: 420rpx;
min-height: 82rpx;
align-items: center;
justify-content: center;
margin: 34rpx auto 0;
background: url("/static/assets/foundation/transparent/a01-scroll-primary-v3.png")
center / contain no-repeat;
}
.application-page__action text {
z-index: 1;
color: #fff9ed;
font-size: 26rpx;
font-weight: 700;
}
</style>