383 lines
9.8 KiB
Vue
383 lines
9.8 KiB
Vue
<!-- 页面编号:G-09;用途:我的家谱申请列表与空/失败状态。 -->
|
||
<template>
|
||
<view class="application-page">
|
||
<GenealogyPageBackground />
|
||
<view class="application-page__header"
|
||
><PageHeader title="我的申请"
|
||
/></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"
|
||
>
|
||
<image
|
||
class="application-card__skin"
|
||
src="/static/assets/modules/genealogy/transparent/list-slip-frame.png"
|
||
mode="scaleToFill"
|
||
/>
|
||
<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">
|
||
<image
|
||
src="/static/assets/modules/genealogy/transparent/list-slip-frame.png"
|
||
mode="scaleToFill"
|
||
/>
|
||
<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()
|
||
"
|
||
>
|
||
<image
|
||
src="/static/assets/foundation/transparent/a01-scroll-primary-v3.png"
|
||
mode="aspectFit"
|
||
/>
|
||
<text>{{
|
||
applicationState === "error" ? "重新查看" : "查找公开家谱"
|
||
}}</text>
|
||
</view>
|
||
</view>
|
||
|
||
<AppDialog
|
||
:visible="!!withdrawTarget"
|
||
title="撤回加入申请"
|
||
:message="
|
||
withdrawTarget
|
||
? `确认撤回对“${withdrawTarget.genealogyName}”的申请?撤回后如需加入,可重新提交。`
|
||
: ''
|
||
"
|
||
confirm-text="确认撤回"
|
||
cancel-text="暂不撤回"
|
||
show-cancel
|
||
@confirm="confirmWithdraw"
|
||
@cancel="cancelWithdraw"
|
||
@close="cancelWithdraw"
|
||
/>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { computed, ref } from "vue";
|
||
import { 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";
|
||
|
||
const applications = ref([]);
|
||
const applicationState = ref("loading");
|
||
const errorMessage = ref("");
|
||
const withdrawTarget = ref(null);
|
||
const applicationSamples = [
|
||
{
|
||
id: 1,
|
||
genealogyId: 1001,
|
||
genealogyName: "汤氏家谱",
|
||
relation: "自述为汤正华堂侄",
|
||
appliedAt: "今天 10:24",
|
||
status: "PENDING",
|
||
},
|
||
{
|
||
id: 2,
|
||
genealogyId: 1002,
|
||
genealogyName: "汝南汤氏家谱",
|
||
relation: "祖居河南汝南",
|
||
appliedAt: "昨天 18:02",
|
||
status: "APPROVED",
|
||
},
|
||
{
|
||
id: 3,
|
||
genealogyId: 1003,
|
||
genealogyName: "清河汤氏家谱",
|
||
relation: "补充材料不足",
|
||
appliedAt: "7月12日 09:18",
|
||
status: "REJECTED",
|
||
},
|
||
];
|
||
|
||
const statusLabel = (status) =>
|
||
({
|
||
PENDING: "审核中",
|
||
APPROVED: "已通过",
|
||
REJECTED: "未通过",
|
||
WITHDRAWN: "已撤回",
|
||
})[status] || "状态未知";
|
||
|
||
const statusHint = (status) =>
|
||
({
|
||
PENDING: "管理员尚未处理,可在审核前撤回",
|
||
APPROVED: "申请已通过,可进入这部家谱",
|
||
REJECTED: "请修改关系说明后重新提交",
|
||
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 }));
|
||
applicationState.value = "list";
|
||
};
|
||
|
||
onLoad(loadApplications);
|
||
const handleApplicationAction = (item) => {
|
||
if (item.status === "APPROVED")
|
||
return uni.navigateTo({
|
||
url: `/pages/genealogy/g05-genealogy-overview?genealogyId=${item.genealogyId}`,
|
||
});
|
||
if (item.status === "REJECTED")
|
||
return uni.navigateTo({
|
||
url: `/pages/genealogy/g08-join-application?source=search&previous=rejected&genealogyId=${item.genealogyId}`,
|
||
});
|
||
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 = "WITHDRAWN";
|
||
cancelWithdraw();
|
||
};
|
||
const toSearch = () =>
|
||
uni.navigateTo({ url: "/pages/genealogy/g06-search-genealogies" });
|
||
</script>
|
||
|
||
<style scoped lang="scss">
|
||
.application-page {
|
||
position: relative;
|
||
min-height: 100vh;
|
||
overflow-x: hidden;
|
||
background: $paper;
|
||
}
|
||
.application-page__header {
|
||
position: relative;
|
||
z-index: 3;
|
||
}
|
||
.application-content {
|
||
position: relative;
|
||
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 {
|
||
position: relative;
|
||
width: 100%;
|
||
height: calc((100vw - 24px) * 0.34286);
|
||
min-height: 228rpx;
|
||
max-height: 282rpx;
|
||
margin-bottom: 18rpx;
|
||
}
|
||
.application-card__skin {
|
||
position: absolute;
|
||
inset: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.application-card__body {
|
||
position: absolute;
|
||
inset: 18% 7% 14% 8.5%;
|
||
}
|
||
.application-card__name {
|
||
color: $ink;
|
||
font-family: "STKaiti", "KaiTi", serif;
|
||
font-size: 30rpx;
|
||
font-weight: 700;
|
||
}
|
||
.application-card__time {
|
||
position: absolute;
|
||
top: 3rpx;
|
||
right: 0;
|
||
color: #998873;
|
||
font-size: 23rpx;
|
||
}
|
||
.application-card__relation {
|
||
display: block;
|
||
max-width: 70%;
|
||
margin-top: 14rpx;
|
||
color: $ink-muted;
|
||
font-size: 24rpx;
|
||
}
|
||
.application-card__status {
|
||
position: absolute;
|
||
right: 3%;
|
||
bottom: 38%;
|
||
color: $brand-red;
|
||
font-size: 25rpx;
|
||
font-weight: 700;
|
||
}
|
||
.application-card__status--approved {
|
||
color: #537368;
|
||
}
|
||
.application-card__status--rejected {
|
||
color: #7e6f62;
|
||
}
|
||
.application-card__hint {
|
||
position: absolute;
|
||
bottom: 5%;
|
||
left: 0;
|
||
max-width: 62%;
|
||
color: #766653;
|
||
font-size: 23rpx;
|
||
}
|
||
.application-card__action {
|
||
position: absolute;
|
||
right: 2%;
|
||
bottom: 2%;
|
||
z-index: 2;
|
||
display: flex;
|
||
min-height: 54rpx;
|
||
align-items: center;
|
||
color: $brand-red;
|
||
font-size: 23rpx;
|
||
font-weight: 700;
|
||
}
|
||
.application-state-card {
|
||
position: relative;
|
||
width: 100%;
|
||
height: calc((100vw - 24px) * 0.34286);
|
||
min-height: 228rpx;
|
||
margin-top: 80rpx;
|
||
}
|
||
.application-state-card > image {
|
||
position: absolute;
|
||
inset: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.application-state-card__copy {
|
||
position: absolute;
|
||
inset: 22% 12%;
|
||
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 {
|
||
position: relative;
|
||
width: 420rpx;
|
||
height: 82rpx;
|
||
margin: 34rpx auto 0;
|
||
}
|
||
.application-page__action image {
|
||
position: absolute;
|
||
inset: 0;
|
||
width: 100%;
|
||
height: 100%;
|
||
}
|
||
.application-page__action text {
|
||
position: relative;
|
||
z-index: 1;
|
||
display: flex;
|
||
align-items: center;
|
||
justify-content: center;
|
||
height: 100%;
|
||
color: #fff9ed;
|
||
font-size: 26rpx;
|
||
font-weight: 700;
|
||
}
|
||
</style>
|