Files
template-nuxt4/app/pages/about/join/personal.vue
2026-04-29 01:33:33 +08:00

285 lines
8.2 KiB
Vue
Raw Permalink 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>
<div class="join-page">
<div class="page-header">
<h1 class="page-title">个人会员申请</h1>
<p class="page-desc">加入我们共同推动决策咨询事业发展</p>
</div>
<div class="join-content">
<a-steps :current="currentStep" class="steps-wrap">
<a-step title="填写信息" />
<a-step title="上传资料" />
<a-step title="提交审核" />
</a-steps>
<a-form :model="formData" class="join-form" layout="vertical">
<!-- 步骤1填写信息 -->
<div v-show="currentStep === 0">
<h3 class="section-title">个人信息</h3>
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="姓名" name="name" required>
<a-input v-model:value="formData.name" placeholder="请输入您的姓名" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="性别" name="gender">
<a-select v-model:value="formData.gender" placeholder="请选择">
<a-select-option value="male"></a-select-option>
<a-select-option value="female"></a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="出生年月" name="birthday">
<a-date-picker v-model:value="formData.birthday" style="width: 100%" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="学历" name="education">
<a-select v-model:value="formData.education" placeholder="请选择">
<a-select-option value="bachelor">本科</a-select-option>
<a-select-option value="master">硕士</a-select-option>
<a-select-option value="doctor">博士</a-select-option>
</a-select>
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="职称/职务" name="title">
<a-input v-model:value="formData.title" placeholder="如:教授、研究员" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="工作单位" name="organization">
<a-input v-model:value="formData.organization" placeholder="请输入工作单位" />
</a-form-item>
</a-col>
</a-row>
<a-row :gutter="24">
<a-col :span="12">
<a-form-item label="联系电话" name="phone" required>
<a-input v-model:value="formData.phone" placeholder="请输入联系电话" />
</a-form-item>
</a-col>
<a-col :span="12">
<a-form-item label="邮箱" name="email">
<a-input v-model:value="formData.email" placeholder="请输入邮箱" />
</a-form-item>
</a-col>
</a-row>
<a-form-item label="研究方向/专业领域" name="researchArea">
<a-input v-model:value="formData.researchArea" placeholder="请输入研究方向" />
</a-form-item>
<a-form-item label="个人简介" name="bio">
<a-textarea v-model:value="formData.bio" :rows="4" placeholder="请简要介绍您的学术背景和工作经历" />
</a-form-item>
</div>
<!-- 步骤2上传资料 -->
<div v-show="currentStep === 1">
<h3 class="section-title">资质证明材料</h3>
<p class="section-desc">请上传相关证明材料以便我们审核您的入会资格</p>
<a-form-item label="身份证">
<a-upload :before-upload="beforeUpload" :custom-request="handleUpload('idCard')">
<a-button><UploadOutlined /> 上传身份证</a-button>
</a-upload>
</a-form-item>
<a-form-item label="学历/学位证明">
<a-upload :before-upload="beforeUpload" :custom-request="handleUpload('diploma')">
<a-button><UploadOutlined /> 上传学历证明</a-button>
</a-upload>
</a-form-item>
<a-form-item label="职称证明">
<a-upload :before-upload="beforeUpload" :custom-request="handleUpload('certificate')">
<a-button><UploadOutlined /> 上传职称证明</a-button>
</a-upload>
</a-form-item>
<a-form-item label="研究成果或获奖证明(可选)">
<a-upload :before-upload="beforeUpload" :custom-request="handleUpload('achievements')" multiple>
<a-button><UploadOutlined /> 上传材料</a-button>
</a-upload>
<div class="upload-hint">可上传多份材料支持 JPGPNGPDF 格式</div>
</a-form-item>
</div>
<!-- 步骤3确认提交 -->
<div v-show="currentStep === 2" class="confirm-section">
<a-result
sub-title="请确认您填写的信息和上传的材料准确无误"
title="确认提交申请"
>
<template #icon>
<CheckCircleOutlined style="font-size: 80px; color: #52c41a" />
</template>
<template #extra>
<a-button :loading="submitting" size="large" type="primary" @click="handleSubmit">
确认提交
</a-button>
</template>
</a-result>
</div>
<!-- 步骤按钮 -->
<div class="step-actions">
<a-button v-if="currentStep > 0" @click="currentStep--">上一步</a-button>
<a-button v-if="currentStep < 2" type="primary" @click="handleNext">下一步</a-button>
</div>
</a-form>
</div>
</div>
</template>
<script lang="ts" setup>
import { message } from 'ant-design-vue'
import { CheckCircleOutlined, UploadOutlined } from '@ant-design/icons-vue'
useHead({ title: '个人会员申请 - 决策咨询网' })
const currentStep = ref(0)
const submitting = ref(false)
const formData = reactive({
name: '',
gender: undefined,
birthday: undefined,
education: undefined,
title: '',
organization: '',
phone: '',
email: '',
researchArea: '',
bio: '',
idCard: '',
diploma: '',
certificate: '',
achievements: [] as string[],
})
function beforeUpload(file: File) {
const isLt10M = file.size / 1024 / 1024 < 10
if (!isLt10M) {
message.error('文件大小不能超过 10MB')
return false
}
return true
}
function handleUpload(type: string) {
return async (option: any) => {
try {
// TODO: 调用上传API
option.onSuccess()
message.success('上传成功')
} catch {
option.onError()
message.error('上传失败')
}
}
}
function handleNext() {
if (currentStep.value === 0) {
if (!formData.name || !formData.phone) {
message.warning('请填写必填项')
return
}
}
currentStep.value++
}
async function handleSubmit() {
submitting.value = true
try {
// TODO: 调用API提交申请
message.success('提交成功,请等待审核')
navigateTo('/about/join')
} catch (e: any) {
message.error(e?.message || '提交失败')
} finally {
submitting.value = false
}
}
</script>
<style scoped>
.join-page {
max-width: 800px;
margin: 0 auto;
padding: 40px 20px;
}
.page-header {
text-align: center;
margin-bottom: 40px;
}
.page-title {
font-size: 28px;
font-weight: 700;
color: #1f2937;
margin: 0 0 12px;
}
.page-desc {
font-size: 16px;
color: #6b7280;
margin: 0;
}
.join-content {
background: #fff;
border-radius: 16px;
padding: 40px;
box-shadow: 0 4px 16px rgba(0,0,0,0.08);
}
.steps-wrap {
margin-bottom: 40px;
}
.section-title {
font-size: 18px;
font-weight: 600;
color: #1f2937;
margin: 0 0 20px;
}
.section-desc {
font-size: 14px;
color: #6b7280;
margin: -10px 0 20px;
}
.upload-hint {
font-size: 12px;
color: #9ca3af;
margin-top: 8px;
}
.confirm-section {
padding: 40px 0;
}
.step-actions {
display: flex;
justify-content: center;
gap: 16px;
margin-top: 32px;
padding-top: 24px;
border-top: 1px solid #f0f0f0;
}
</style>