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

132 lines
7.3 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-08用途申请加入家谱与提交成功/失败状态 -->
<template>
<view class="join-page">
<image class="join-page__paper" src="/static/assets/foundation/opaque/page-paper.jpg" mode="aspectFill" />
<image class="join-page__footer" src="/static/assets/foundation/transparent/footer-mountain-bamboo.png" mode="widthFix" />
<view class="join-page__header"><PageHeader title="申请加入家谱" /></view>
<view class="join-panel" :class="{
'join-state--form': joinState === 'form',
'join-state--success': joinState === 'success',
'join-state--error': joinState === 'error'
}">
<image class="join-panel__skin" src="/static/assets/modules/genealogy/opaque/g03-create-flow-panel.png" mode="scaleToFill" />
<view v-if="joinState === 'form'" class="join-form">
<text class="join-form__eyebrow">公开家谱入谱申请</text>
<text class="join-form__title">申请加入 {{ genealogyName }}</text>
<text class="join-form__copy">请填写真实身份和亲属关系管理员审核后会通过消息告知结果</text>
<view class="join-field">
<image src="/static/assets/modules/genealogy/opaque/g06-search-input-wide.png" mode="scaleToFill" />
<text>真实姓名</text><input v-model="form.realName" placeholder="请输入真实姓名" placeholder-class="join-placeholder" />
</view>
<view class="join-field">
<image src="/static/assets/modules/genealogy/opaque/g06-search-input-wide.png" mode="scaleToFill" />
<text>与家谱关系</text><input v-model="form.relation" placeholder="例如:汤正华堂侄" placeholder-class="join-placeholder" />
</view>
<view class="join-field join-field--message">
<image src="/static/assets/modules/genealogy/opaque/g06-search-input-wide.png" mode="scaleToFill" />
<text>申请说明</text><textarea v-model="form.message" maxlength="80" placeholder="补充祖居地、长辈姓名等核验信息" placeholder-class="join-placeholder" />
</view>
<text class="join-form__note">提交后可在我的申请中查看审核进度</text>
<view class="join-action" @click="submitJoin">
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
<text>{{ isSubmitting ? '正在提交…' : '提交申请' }}</text>
</view>
</view>
<view v-else class="join-result">
<text class="join-result__eyebrow">{{ joinState === 'success' ? '申请已送达' : '申请未提交' }}</text>
<text class="join-result__title">{{ joinState === 'success' ? '等待管理员核实亲属关系' : '暂时无法提交申请' }}</text>
<text class="join-result__copy">{{ resultCopy }}</text>
<view class="join-action" @click="joinState === 'success' ? toMyApplications() : retryForm()">
<image src="/static/assets/foundation/opaque/a01-primary-button.png" mode="scaleToFill" />
<text>{{ joinState === 'success' ? '查看我的申请' : '重新填写' }}</text>
</view>
</view>
</view>
</view>
</template>
<script setup>
import { computed, reactive, ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import PageHeader from '@/components/PageHeader.vue'
const genealogyId = ref('')
const genealogyName = ref('这部家谱')
const genealogyPreview = {
'1001': '汤氏家谱',
'1002': '汝南汤氏家谱'
}
const joinState = ref('form')
const isSubmitting = ref(false)
const errorMessage = ref('')
const form = reactive({ realName: '', relation: '', message: '' })
const resultCopy = computed(() => joinState.value === 'success'
? `“${genealogyName.value}”的管理员会在核实后给出结果,请留意消息中心。`
: errorMessage.value || '请检查网络后重新填写;未成功提交的内容不会进入审核列表。')
onLoad((query) => {
genealogyId.value = query.genealogyId || ''
if (query.state === 'success') {
joinState.value = 'success'
return
}
if (!genealogyId.value) {
errorMessage.value = '没有找到要申请加入的家谱,请先返回公开家谱检索。'
joinState.value = 'error'
return
}
genealogyName.value = genealogyPreview[genealogyId.value] || '这部家谱'
})
const submitJoin = () => {
if (isSubmitting.value) return
if (!form.realName.trim() || !form.relation.trim()) {
uni.showToast({ title: '请填写真实姓名和亲属关系', icon: 'none' })
return
}
isSubmitting.value = true
setTimeout(() => {
joinState.value = 'success'
isSubmitting.value = false
}, 280)
}
const retryForm = () => { joinState.value = 'form'; errorMessage.value = '' }
const toMyApplications = () => uni.redirectTo({ url: '/pages/genealogy/g09-my-applications' })
</script>
<style scoped lang="scss">
.join-page { position: relative; min-height: 100vh; overflow: hidden; background: $paper; }
.join-page__paper { position: absolute; inset: 0; z-index: 0; width: 100%; height: 100%; opacity: .98; pointer-events: none; }
.join-page__footer { position: absolute; right: 0; bottom: 0; left: 0; z-index: 1; width: 100%; opacity: .13; pointer-events: none; }
.join-page__header { position: relative; z-index: 3; }
.join-panel { position: relative; z-index: 2; width: calc(100% - 32rpx); height: min(590px, calc((100vw - 16px) * 1.337)); margin: 22rpx auto 0; }
.join-panel__skin { position: absolute; inset: 0; width: 100%; height: 100%; }
.join-form { position: absolute; inset: 8.5% 8%; }
.join-form__eyebrow, .join-result__eyebrow { display: block; color: $brand-red; font-size: 23rpx; letter-spacing: 3rpx; }
.join-form__title, .join-result__title { display: block; margin-top: 12rpx; color: $ink; font-family: 'STKaiti', 'KaiTi', serif; font-size: 36rpx; font-weight: 700; }
.join-form__copy, .join-result__copy { display: block; margin-top: 12rpx; color: $ink-muted; font-size: 22rpx; line-height: 1.6; }
.join-field { position: relative; height: 92rpx; margin-top: 18rpx; }
.join-field > image { position: absolute; inset: 0; width: 100%; height: 100%; }
.join-field > text { position: absolute; top: 31rpx; left: 24rpx; z-index: 1; color: $ink; font-size: 23rpx; font-weight: 700; }
.join-field input, .join-field textarea { position: absolute; top: 0; right: 20rpx; bottom: 0; left: 170rpx; z-index: 1; height: 92rpx; color: $ink; font-size: 23rpx; line-height: 92rpx; }
.join-field textarea { box-sizing: border-box; padding-top: 26rpx; line-height: 1.5; }
.join-placeholder { color: #a79884; }
.join-form__note { display: block; margin-top: 18rpx; color: $ink-muted; font-size: 21rpx; text-align: center; }
.join-action { position: relative; width: 100%; height: 82rpx; margin-top: 20rpx; }
.join-action image { position: absolute; inset: 0; width: 100%; height: 100%; }
.join-action text { position: relative; z-index: 1; display: flex; align-items: center; justify-content: center; height: 100%; color: #fff9ed; font-size: 27rpx; font-weight: 700; letter-spacing: 3rpx; }
.join-result { position: absolute; top: 28%; right: 12%; left: 12%; text-align: center; }
.join-result__eyebrow { text-align: center; }
.join-result__copy { margin-top: 22rpx; }
.join-result .join-action { width: 420rpx; max-width: 100%; margin: 34rpx auto 0; }
@media (min-width: 400px) {
.join-panel { width: calc(100% - 48rpx); }
.join-form { right: 9%; left: 9%; }
}
</style>