Files
jiapuapp/pages/genealogy/g10-application-review.vue
T
2026-07-15 08:31:33 +08:00

134 lines
8.4 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-10用途管理员入谱申请审核与空/失败状态 -->
<template>
<view class="review-page">
<image class="review-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
<image class="review-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
<view class="review-page__header"><PageHeader title="入谱审核" action="说明" @action="showHelp" /></view>
<view class="review-content" :class="{
'review-state--list': reviewState === 'list',
'review-state--empty': reviewState === 'empty',
'review-state--error': reviewState === 'error'
}">
<view class="review-intro">
<text>核实亲属关系后再决定</text>
<text>审核结果会通过消息告知申请人</text>
<image src="/static/assets/modules/genealogy/transparent/section-divider.png" mode="scaleToFill" />
</view>
<template v-if="reviewState === 'list'">
<view v-for="item in applications" :key="item.id" class="application-card">
<image class="application-card__skin" src="/static/assets/modules/genealogy/opaque/application-record-card.png" mode="scaleToFill" />
<view class="application-card__body">
<text class="application-card__name">{{ item.name }}</text>
<text class="application-card__phone">{{ item.phone }}</text>
<text class="application-card__time">{{ item.appliedAt }}</text>
<text class="application-card__relation">{{ item.relation }}</text>
<view v-if="item.status === 'PENDING'" class="review-actions">
<view class="review-action" @click="confirmAudit(item, false)">
<image src="/static/assets/foundation/opaque/a01-secondary-button.png" mode="scaleToFill" /><text>拒绝</text>
</view>
<view class="review-action" @click="confirmAudit(item, true)">
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>通过</text>
</view>
</view>
<text v-else class="application-card__status">{{ item.status === 'APPROVED' ? '已通过' : '已拒绝' }}</text>
</view>
</view>
</template>
<view v-else class="review-state-card">
<image src="/static/assets/modules/genealogy/opaque/application-status-card.png" mode="scaleToFill" />
<view class="review-state-card__copy">
<text>{{ reviewState === 'empty' ? '暂无待审核申请' : '审核列表暂时无法读取' }}</text>
<text>{{ reviewState === 'empty' ? '新的入谱申请会在这里出现,并同步发送消息提醒。' : errorMessage || '请检查网络或家谱权限后重试。' }}</text>
</view>
</view>
<view v-if="reviewState === 'error'" class="review-page__retry" @click="loadApplications({ genealogyId })">
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" /><text>重新查看</text>
</view>
</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import PageHeader from '@/components/PageHeader.vue'
import { genealogyContext } from '@/utils/genealogy-context.js'
const applications = ref([])
const reviewSamples = [
{ id: 1, name: '汤志成', phone: '139****6421', relation: '自述为汤正华堂侄 · 祖居洛阳', appliedAt: '今天 10:24', status: 'PENDING' },
{ id: 2, name: '汤雨薇', phone: '136****2798', relation: '自述为汤正国之女 · 已补充长辈姓名', appliedAt: '昨天 18:02', status: 'PENDING' }
]
const genealogyId = ref('')
const reviewState = ref('loading')
const errorMessage = ref('')
const loadApplications = (query = {}) => {
reviewState.value = 'loading'
errorMessage.value = ''
genealogyId.value = query.genealogyId?.value || query.genealogyId || genealogyId.value || genealogyContext.getCurrentGenealogyId()
if (query.state === 'empty') { reviewState.value = 'empty'; return }
if (query.state === 'error') { reviewState.value = 'error'; return }
if (!genealogyId.value) {
errorMessage.value = '没有找到当前家谱,请从家谱总览进入。'
reviewState.value = 'error'
return
}
genealogyContext.setCurrentGenealogyId(genealogyId.value)
applications.value = reviewSamples.map((item) => ({ ...item }))
reviewState.value = 'list'
}
onLoad(loadApplications)
const confirmAudit = (item, approved) => {
uni.showModal({
title: approved ? '确认通过申请?' : '确认拒绝申请?',
content: approved ? '通过后,申请人将成为本家谱成员。' : '拒绝后,申请人会收到审核结果。',
confirmText: approved ? '确认通过' : '确认拒绝',
success: ({ confirm }) => {
if (!confirm) return
item.status = approved ? 'APPROVED' : 'REJECTED'
uni.showToast({ title: approved ? '已通过申请' : '已拒绝申请', icon: 'none' })
}
})
}
const showHelp = () => uni.showModal({ title: '审核说明', content: '请核对申请人的姓名、亲属关系和补充说明,仅确认与本家谱存在真实关系的申请。', showCancel: false })
</script>
<style scoped lang="scss">
.review-page { position: relative; min-height: 100vh; overflow: hidden; background: $paper; }
.review-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
.review-page__footer { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .13; pointer-events: none; }
.review-page__header { position: relative; z-index: 3; }
.review-content { position: relative; z-index: 2; padding: 24rpx 24rpx 60rpx; }
.review-intro { position: relative; margin: 0 8rpx 24rpx; padding-bottom: 22rpx; }
.review-intro text { display: block; }
.review-intro text:first-child { color: $ink; font-family: 'STKaiti', 'KaiTi', serif; font-size: 29rpx; font-weight: 700; }
.review-intro text:nth-child(2) { margin-top: 8rpx; color: $ink-muted; font-size: 21rpx; }
.review-intro image { position: absolute; right: 0; bottom: 0; left: 0; width: 100%; height: 14rpx; }
.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% 12% 8.5%; }
.application-card__name { color: $ink; font-family: 'STKaiti', 'KaiTi', serif; font-size: 30rpx; font-weight: 700; }
.application-card__phone { margin-left: 14rpx; color: $ink-muted; font-size: 20rpx; }
.application-card__time { position: absolute; top: 3rpx; right: 0; color: #998873; font-size: 20rpx; }
.application-card__relation { display: block; max-width: 58%; margin-top: 15rpx; color: $ink-muted; font-size: 22rpx; }
.review-actions { position: absolute; right: 0; bottom: 0; display: flex; gap: 12rpx; }
.review-action { position: relative; width: 128rpx; height: 60rpx; }
.review-action image { position: absolute; inset: 0; width: 100%; height: 100%; }
.review-action text { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; height: 100%; color: $ink; font-size: 22rpx; font-weight: 700; }
.review-action:last-child text { color: #fff9ed; }
.application-card__status { position: absolute; right: 3%; bottom: 10%; color: $brand-red; font-size: 24rpx; font-weight: 700; }
.review-state-card { position: relative; width: 100%; height: calc((100vw - 24px) * .34286); min-height: 228rpx; margin-top: 70rpx; }
.review-state-card > image { position: absolute; inset: 0; width: 100%; height: 100%; }
.review-state-card__copy { position: absolute; inset: 22% 12%; display: flex; flex-direction: column; justify-content: center; text-align: center; }
.review-state-card__copy text:first-child { color: $ink; font-family: 'STKaiti', 'KaiTi', serif; font-size: 31rpx; font-weight: 700; }
.review-state-card__copy text:last-child { margin-top: 15rpx; color: $ink-muted; font-size: 22rpx; line-height: 1.6; }
.review-page__retry { position: relative; width: 420rpx; height: 82rpx; margin: 32rpx auto 0; }
.review-page__retry image { position: absolute; inset: 0; width: 100%; height: 100%; }
.review-page__retry 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>