Review changes batch 6 of 6

This commit is contained in:
2026-07-20 06:52:33 +08:00
parent db97d3da27
commit 5a31a75da0
160 changed files with 9206 additions and 572 deletions
+328 -88
View File
@@ -2,47 +2,94 @@
<template>
<view class="application-page">
<GenealogyPageBackground />
<view class="application-page__header"><PageHeader title="我的申请" /></view>
<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'
}">
<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/opaque/application-status-card.png" mode="scaleToFill" />
<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>
<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/opaque/application-status-card.png" mode="scaleToFill" />
<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'" 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
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}”的申请?撤回后如需加入,可重新提交。` : ''"
:message="
withdrawTarget
? `确认撤回对“${withdrawTarget.genealogyName}”的申请?撤回后如需加入,可重新提交。`
: ''
"
confirm-text="确认撤回"
cancel-text="暂不撤回"
show-cancel
@@ -54,89 +101,282 @@
</template>
<script setup>
import { computed, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import AppDialog from '@/components/AppDialog.vue'
import GenealogyPageBackground from '@/components/GenealogyPageBackground.vue'
import PageHeader from '@/components/PageHeader.vue'
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 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' }
]
{
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 statusLabel = (status) =>
({
PENDING: "审核中",
APPROVED: "已通过",
REJECTED: "未通过",
WITHDRAWN: "已撤回",
})[status] || "状态未知";
const statusHint = (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 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'
}
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)
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 }
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' })
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: 21rpx; }
.application-card { position: relative; width: 100%; height: calc((100vw - 24px) * .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: 20rpx; }
.application-card__relation { display: block; max-width: 70%; margin-top: 14rpx; color: $ink-muted; font-size: 22rpx; }
.application-card__status { position: absolute; right: 3%; bottom: 38%; color: $brand-red; font-size: 23rpx; 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: #8d7c67; font-size: 20rpx; }
.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: 21rpx; font-weight: 700; }
.application-state-card { position: relative; width: 100%; height: calc((100vw - 24px) * .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: 22rpx; 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; }
.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>