release: freeze demo v1.1.0 2026-10-19
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
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
This commit is contained in:
@@ -0,0 +1,217 @@
|
||||
<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>
|
||||
@@ -0,0 +1,326 @@
|
||||
<template>
|
||||
<PageLayout title="本地资格核验">
|
||||
<div class="les">
|
||||
<div class="les__header">
|
||||
<div class="les__title">补充本地资格佐证</div>
|
||||
<div class="les__desc">
|
||||
请补充一项能够说明你在丹阳工作或居住的材料。材料仅用于资格审核,不对其他用户展示。
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="eligibilityType" class="les__type-tag">
|
||||
<UiTag type="primary">{{ typeLabel(eligibilityType) }}</UiTag>
|
||||
</div>
|
||||
|
||||
<div class="les__section">
|
||||
<div class="les__section-title">选择佐证类型</div>
|
||||
<div class="les__evidence-list">
|
||||
<div
|
||||
v-for="e in evidenceTypes"
|
||||
:key="e.value"
|
||||
class="les__evidence"
|
||||
:class="{ 'les__evidence--active': selectedType === e.value }"
|
||||
@click="selectedType = e.value"
|
||||
>
|
||||
<div class="les__evidence-label">{{ e.label }}</div>
|
||||
<div class="les__evidence-desc">{{ e.desc }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="les__section">
|
||||
<div class="les__section-title">上传佐证材料</div>
|
||||
<div class="les__upload">
|
||||
<div class="les__upload-hint">支持 JPG/PNG,最多 {{ maxFiles }} 张</div>
|
||||
<div class="les__grid">
|
||||
<div v-for="(f, index) in files" :key="f.fileId" class="les__item">
|
||||
<img :src="f.previewUrl" class="les__preview" alt="" />
|
||||
<div class="les__remove" @click="onRemove(index)">×</div>
|
||||
</div>
|
||||
<div v-if="files.length < maxFiles" class="les__add" @click="onChooseFile">
|
||||
<span class="les__add-icon">+</span>
|
||||
<span class="les__add-text">上传</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<input
|
||||
ref="fileInput"
|
||||
type="file"
|
||||
accept="image/*"
|
||||
class="les__hidden-input"
|
||||
@change="onFileChange"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div class="les__privacy">材料仅用于资格审核,不对其他用户展示</div>
|
||||
|
||||
<div class="les__actions">
|
||||
<van-button
|
||||
type="primary"
|
||||
block
|
||||
round
|
||||
:loading="submitting"
|
||||
:disabled="submitting || uploading"
|
||||
@click="onSubmit"
|
||||
>
|
||||
{{ submitting ? '提交中…' : '提交审核' }}
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</PageLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { localEligibilityService, profileService } from '@/api/services'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import PageLayout from '@/layouts/PageLayout.vue'
|
||||
import UiTag from '@/components/UiTag.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const fileInput = ref<HTMLInputElement | null>(null)
|
||||
const eligibilityType = ref(typeof route.query.type === 'string' ? route.query.type : '')
|
||||
const selectedType = ref('')
|
||||
const files = ref<Array<{ fileId: string; previewUrl: string }>>([])
|
||||
const uploading = ref(false)
|
||||
const submitting = ref(false)
|
||||
const maxFiles = 5
|
||||
|
||||
const TYPE_LABELS: Record<string, string> = {
|
||||
household_registration: '丹阳户籍',
|
||||
employment: '在丹阳工作',
|
||||
residence: '在丹阳长期居住',
|
||||
other: '其他符合服务条件',
|
||||
}
|
||||
const evidenceTypes = [
|
||||
{ value: 'employment_proof', label: '工作证明', desc: '劳动合同、工牌或在职证明等' },
|
||||
{ value: 'residence_proof', label: '居住证明', desc: '房产证、租赁合同或水电账单等' },
|
||||
{ value: 'household_proof', label: '户籍证明', desc: '户口本或户籍页等' },
|
||||
{ value: 'other', label: '其他材料', desc: '能够说明你在丹阳生活或工作的材料' },
|
||||
]
|
||||
|
||||
function typeLabel(code: string): string {
|
||||
return TYPE_LABELS[code] || code
|
||||
}
|
||||
|
||||
async function loadStatus() {
|
||||
try {
|
||||
const result: any = await localEligibilityService.getStatus()
|
||||
if (!eligibilityType.value && result?.eligibilityType) eligibilityType.value = result.eligibilityType
|
||||
const evidences = result?.evidences || []
|
||||
files.value = evidences
|
||||
.filter((e: any) => e.fileId)
|
||||
.map((e: any) => ({ fileId: e.fileId, previewUrl: e.url || e.fileUrl || '' }))
|
||||
} catch {
|
||||
/* 允许重新提交 */
|
||||
}
|
||||
}
|
||||
|
||||
function onChooseFile() {
|
||||
if (!selectedType.value) {
|
||||
appStore.toast('请先选择佐证类型')
|
||||
return
|
||||
}
|
||||
if (files.value.length >= maxFiles) {
|
||||
appStore.toast(`最多上传 ${maxFiles} 份材料`)
|
||||
return
|
||||
}
|
||||
fileInput.value?.click()
|
||||
}
|
||||
|
||||
async function onFileChange(evt: Event) {
|
||||
const input = evt.target as HTMLInputElement
|
||||
const file = input.files?.[0]
|
||||
input.value = ''
|
||||
if (!file) return
|
||||
if (files.value.length >= maxFiles) {
|
||||
appStore.toast(`最多上传 ${maxFiles} 份材料`)
|
||||
return
|
||||
}
|
||||
uploading.value = true
|
||||
try {
|
||||
const token: any = await profileService.requestUploadToken({
|
||||
fileName: `eligibility_${Date.now()}_${file.name}`,
|
||||
contentType: file.type || 'image/jpeg',
|
||||
})
|
||||
await fetch(token.uploadUrl, {
|
||||
method: 'PUT',
|
||||
body: file,
|
||||
headers: { 'Content-Type': file.type || 'image/jpeg' },
|
||||
})
|
||||
await localEligibilityService.uploadEvidence({
|
||||
evidenceType: selectedType.value,
|
||||
fileId: token.fileKey,
|
||||
})
|
||||
files.value = [...files.value, { fileId: token.fileKey, previewUrl: URL.createObjectURL(file) }]
|
||||
appStore.toastSuccess('材料已上传')
|
||||
} catch (err: any) {
|
||||
appStore.toastError(err?.message || '上传失败,请稍后重试')
|
||||
} finally {
|
||||
uploading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function onRemove(index: number) {
|
||||
files.value = files.value.filter((_, i) => i !== index)
|
||||
}
|
||||
|
||||
async function onSubmit() {
|
||||
if (!eligibilityType.value) {
|
||||
appStore.toast('请先选择本地资格类型')
|
||||
return
|
||||
}
|
||||
submitting.value = true
|
||||
try {
|
||||
await localEligibilityService.declare({ eligibilityType: eligibilityType.value, regionCode: '321181' })
|
||||
await localEligibilityService.submit()
|
||||
appStore.toastSuccess('已提交审核')
|
||||
router.replace('/local-eligibility')
|
||||
} catch (err: any) {
|
||||
appStore.toastError(err?.message || '提交失败,请重试')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
onMounted(loadStatus)
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.les {
|
||||
padding: 16px;
|
||||
}
|
||||
.les__header {
|
||||
padding: 4px 4px 12px;
|
||||
}
|
||||
.les__title {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: var(--mini-text-strong);
|
||||
}
|
||||
.les__desc {
|
||||
font-size: 13px;
|
||||
color: var(--mini-text-secondary);
|
||||
line-height: 1.8;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.les__type-tag {
|
||||
margin: 4px 0 12px;
|
||||
}
|
||||
.les__section {
|
||||
margin-top: 12px;
|
||||
}
|
||||
.les__section-title {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--mini-text-strong);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.les__evidence-list {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
.les__evidence {
|
||||
background: var(--mini-surface);
|
||||
border-radius: var(--mini-radius);
|
||||
padding: 12px;
|
||||
box-shadow: var(--mini-shadow);
|
||||
border: 1px solid transparent;
|
||||
}
|
||||
.les__evidence--active {
|
||||
border-color: var(--mini-tabbar-active);
|
||||
}
|
||||
.les__evidence-label {
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
color: var(--mini-text-strong);
|
||||
}
|
||||
.les__evidence-desc {
|
||||
font-size: 11px;
|
||||
color: var(--mini-text-secondary);
|
||||
margin-top: 4px;
|
||||
line-height: 1.6;
|
||||
}
|
||||
.les__upload {
|
||||
background: var(--mini-surface);
|
||||
border-radius: var(--mini-radius);
|
||||
padding: 12px;
|
||||
box-shadow: var(--mini-shadow);
|
||||
}
|
||||
.les__upload-hint {
|
||||
font-size: 12px;
|
||||
color: var(--mini-text-muted);
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.les__grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(3, 1fr);
|
||||
gap: 10px;
|
||||
}
|
||||
.les__item {
|
||||
position: relative;
|
||||
padding-top: 100%;
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
background: var(--mini-bg);
|
||||
}
|
||||
.les__preview {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
}
|
||||
.les__remove {
|
||||
position: absolute;
|
||||
top: 2px;
|
||||
right: 2px;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
border-radius: 50%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
color: #fff;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
.les__add {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 4px;
|
||||
padding-top: 100%;
|
||||
position: relative;
|
||||
border: 1px dashed var(--mini-border, #dcdfe6);
|
||||
border-radius: 10px;
|
||||
color: var(--mini-text-secondary);
|
||||
}
|
||||
.les__add-icon {
|
||||
position: absolute;
|
||||
top: 30%;
|
||||
font-size: 24px;
|
||||
}
|
||||
.les__add-text {
|
||||
position: absolute;
|
||||
top: 58%;
|
||||
font-size: 12px;
|
||||
}
|
||||
.les__hidden-input {
|
||||
display: none;
|
||||
}
|
||||
.les__privacy {
|
||||
font-size: 12px;
|
||||
color: var(--mini-text-muted);
|
||||
margin-top: 14px;
|
||||
text-align: center;
|
||||
}
|
||||
.les__actions {
|
||||
margin-top: 18px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,126 @@
|
||||
<template>
|
||||
<PageLayout title="公益红娘协助授权">
|
||||
<div class="ma">
|
||||
<div class="card">
|
||||
<div class="ma__title">公益红娘协助授权说明</div>
|
||||
<div class="ma__tag">当前为演示测试稿,正式版本以法务审核文件为准</div>
|
||||
<div class="ma__content">
|
||||
<p>
|
||||
为帮助你更顺利地了解身边的公益服务与线下活动,你同意公益红娘在你授权范围内提供协助:
|
||||
了解你的婚恋诉求、协助你参与公益活动、并在必要时为你推荐合适的服务。
|
||||
</p>
|
||||
<p>
|
||||
红娘只能在授权范围内提供协助,不能替你进行喜欢/略过等操作,不能查看你的私人聊天,
|
||||
也不会将你的联系方式提供给任何未获授权的一方。
|
||||
</p>
|
||||
<p>
|
||||
你可随时在「红娘联系授权」中撤回授权,撤回后红娘将停止相应协助。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div v-if="!targetUserId" class="ma__warn">
|
||||
未获取到目标用户,无法提交协助申请。
|
||||
</div>
|
||||
|
||||
<div class="ma__actions">
|
||||
<van-button plain block :disabled="submitting" @click="onCancel">暂不申请</van-button>
|
||||
<van-button
|
||||
type="primary"
|
||||
block
|
||||
:loading="submitting"
|
||||
:disabled="submitting || !targetUserId"
|
||||
@click="onAgree"
|
||||
>
|
||||
同意并申请
|
||||
</van-button>
|
||||
</div>
|
||||
</div>
|
||||
</PageLayout>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, ref } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import { matchmakerService } from '@/api/services'
|
||||
import { useAppStore } from '@/stores/app'
|
||||
import PageLayout from '@/layouts/PageLayout.vue'
|
||||
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const appStore = useAppStore()
|
||||
|
||||
const targetUserId = computed(() => (typeof route.query.targetUserId === 'string' ? route.query.targetUserId : ''))
|
||||
const submitting = ref(false)
|
||||
|
||||
async function onAgree() {
|
||||
if (!targetUserId.value || submitting.value) return
|
||||
submitting.value = true
|
||||
try {
|
||||
await matchmakerService.applyService({
|
||||
serviceType: 'recommendation_assistance',
|
||||
targetUserId: targetUserId.value,
|
||||
description: '希望公益红娘协助了解公益活动和线下服务',
|
||||
authorizationAccepted: true,
|
||||
})
|
||||
appStore.toastSuccess('申请已提交')
|
||||
router.replace('/matchmaker/progress')
|
||||
} catch (err: any) {
|
||||
appStore.toastError(err?.message || '申请失败,请稍后重试')
|
||||
} finally {
|
||||
submitting.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function onCancel() {
|
||||
if (window.history.length > 1) router.back()
|
||||
else router.replace('/matchmaker')
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.ma {
|
||||
padding: 16px;
|
||||
}
|
||||
.card {
|
||||
background: var(--mini-surface);
|
||||
border-radius: var(--mini-radius);
|
||||
box-shadow: var(--mini-shadow);
|
||||
padding: 16px;
|
||||
}
|
||||
.ma__title {
|
||||
font-size: 17px;
|
||||
font-weight: 600;
|
||||
color: var(--mini-text-strong);
|
||||
}
|
||||
.ma__tag {
|
||||
font-size: 11px;
|
||||
color: var(--mini-warning, #b9770e);
|
||||
background: rgba(245, 166, 35, 0.14);
|
||||
display: inline-block;
|
||||
padding: 2px 8px;
|
||||
border-radius: 10px;
|
||||
margin-top: 8px;
|
||||
}
|
||||
.ma__content {
|
||||
margin-top: 12px;
|
||||
font-size: 13px;
|
||||
color: var(--mini-text);
|
||||
line-height: 1.8;
|
||||
}
|
||||
.ma__content p {
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
.ma__warn {
|
||||
margin-top: 12px;
|
||||
font-size: 13px;
|
||||
color: var(--mini-danger);
|
||||
text-align: center;
|
||||
}
|
||||
.ma__actions {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 12px;
|
||||
margin-top: 20px;
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user