Files
danyang-match/h5-demo/src/pages/local/LocalEligibilityPage.vue
T
WorkBuddy 69ebf33e18
CI/CD Pipeline / Backend Build & Test (push) Canceled after 0s
CI/CD Pipeline / Admin Web Build (push) Canceled after 0s
CI/CD Pipeline / Mini Program Compile Check (push) Canceled after 0s
CI/CD Pipeline / Migration Validation (push) Canceled after 0s
CI/CD Pipeline / Test Shell Guard (Phase 23 Gate) (push) Canceled after 0s
CI/CD Pipeline / UI Contracts (source-structure gates) (push) Canceled after 0s
CI/CD Pipeline / E2E (live stack) (push) Canceled after 0s
release: freeze demo v1.1.0 2026-10-19
2026-10-19 20:36:22 +08:00

218 lines
6.0 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.
<template>
<PageLayout title="本地资格">
<div class="le">
<!-- 状态卡 -->
<UiLoading v-if="loading" text="正在读取资格状态…" />
<UiErrorState v-else-if="loadError" message="状态加载失败,请重试" @retry="checkStatus" />
<template v-else>
<div class="le__status" :class="`le__status--${statusTone}`">
<span class="le__status-label">当前状态</span>
<UiTag :type="statusTag">{{ statusText }}</UiTag>
</div>
<div class="le__header">
<div class="le__title">为什么需要确认本地资格?</div>
<div class="le__desc">
善缘丹阳主要服务在丹阳工作、居住或拥有丹阳户籍的适龄单身人士。
本地资格确认帮助我们更好地匹配适合你身边的伴侣。
</div>
</div>
<div class="le__section">
<div class="le__section-title">请选择你的本地资格</div>
<div class="le__types">
<div
v-for="t in eligibilityTypes"
:key="t.value"
class="le__type"
:class="{ 'le__type--active': eligibilityType === t.value }"
@click="onTypeSelect(t.value)"
>
<div class="le__type-icon">{{ t.icon }}</div>
<div class="le__type-label">{{ t.label }}</div>
</div>
</div>
</div>
<div class="le__notice">
只需声明一种资格即可。如需补充佐证材料,系统会在审核后告知你。
</div>
<div class="le__actions">
<van-button plain block @click="goToMyEligibility">查看我已有的资格</van-button>
</div>
</template>
</div>
</PageLayout>
</template>
<script setup lang="ts">
import { computed, onMounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { localEligibilityService } from '@/api/services'
import { useAppStore } from '@/stores/app'
import PageLayout from '@/layouts/PageLayout.vue'
import UiLoading from '@/components/UiLoading.vue'
import UiErrorState from '@/components/UiErrorState.vue'
import UiTag from '@/components/UiTag.vue'
const router = useRouter()
const appStore = useAppStore()
const loading = ref(true)
const loadError = ref(false)
const status = ref('not_declared')
const eligibilityType = ref('')
const eligibilityTypes = [
{ value: 'household_registration', label: '丹阳户籍', icon: '户' },
{ value: 'employment', label: '在丹阳工作', icon: '工' },
{ value: 'residence', label: '在丹阳长期居住', icon: '居' },
{ value: 'other', label: '其他符合服务条件', icon: '其' },
]
const STATUS_TEXT: Record<string, string> = {
not_declared: '尚未声明',
declared: '声明已保存',
needs_evidence: '需要补充佐证',
pending_review: '审核中',
verified: '已核验',
rejected: '未通过',
}
const statusText = computed(() => STATUS_TEXT[status.value] || '尚未声明')
const statusTag = computed<'primary' | 'success' | 'warning' | 'danger' | 'info'>(() => {
if (status.value === 'verified') return 'success'
if (status.value === 'rejected') return 'danger'
if (status.value === 'pending_review' || status.value === 'needs_evidence') return 'warning'
if (status.value === 'declared') return 'primary'
return 'info'
})
const statusTone = computed(() => (status.value === 'verified' ? 'ok' : status.value === 'rejected' ? 'bad' : 'warn'))
async function checkStatus() {
loading.value = true
loadError.value = false
try {
const result: any = await localEligibilityService.getStatus()
status.value = result?.verificationStatus || 'not_declared'
eligibilityType.value = result?.eligibilityType || ''
} catch {
loadError.value = true
} finally {
loading.value = false
}
}
function onTypeSelect(type: string) {
router.push({ path: '/local-eligibility/supplement', query: { type } })
}
function goToMyEligibility() {
if (status.value === 'needs_evidence' || status.value === 'rejected' || status.value === 'declared') {
router.push({ path: '/local-eligibility/supplement', query: { type: eligibilityType.value || '' } })
return
}
appStore.toast(statusText.value)
}
onMounted(checkStatus)
</script>
<style scoped>
.le {
padding: 16px;
}
.le__status {
display: flex;
align-items: center;
justify-content: space-between;
border-radius: var(--mini-radius);
padding: 12px 14px;
margin-bottom: 14px;
background: var(--mini-surface);
box-shadow: var(--mini-shadow);
}
.le__status--ok {
background: rgba(47, 179, 109, 0.1);
}
.le__status--warn {
background: rgba(245, 166, 35, 0.12);
}
.le__status--bad {
background: rgba(240, 72, 62, 0.1);
}
.le__status-label {
font-size: 13px;
color: var(--mini-text-secondary);
}
.le__header {
padding: 4px 4px 12px;
}
.le__title {
font-size: 17px;
font-weight: 600;
color: var(--mini-text-strong);
}
.le__desc {
font-size: 13px;
color: var(--mini-text-secondary);
line-height: 1.8;
margin-top: 8px;
}
.le__section-title {
font-size: 14px;
font-weight: 600;
color: var(--mini-text-strong);
margin-bottom: 10px;
}
.le__types {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 10px;
}
.le__type {
display: flex;
align-items: center;
gap: 10px;
background: var(--mini-surface);
border-radius: var(--mini-radius);
padding: 14px;
box-shadow: var(--mini-shadow);
border: 1px solid transparent;
}
.le__type--active {
border-color: var(--mini-tabbar-active);
}
.le__type-icon {
width: 36px;
height: 36px;
border-radius: 10px;
background: var(--mini-brand-gradient);
color: #fff;
display: flex;
align-items: center;
justify-content: center;
font-size: 16px;
font-weight: 600;
flex: none;
}
.le__type-label {
font-size: 13px;
color: var(--mini-text-strong);
}
.le__notice {
font-size: 12px;
color: var(--mini-text-secondary);
background: rgba(79, 140, 255, 0.06);
border-radius: var(--mini-radius);
padding: 12px 14px;
margin-top: 14px;
line-height: 1.7;
}
.le__actions {
margin-top: 18px;
}
</style>