beefast-website/src/components/PartnerRequest.vue
2025-03-01 09:26:47 +08:00

505 lines
11 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>
<div class="partner-request-container" @touchstart="handleTouchStart">
<div class="request-card">
<h2 class="page-title">合伙人申请</h2>
<form @submit.prevent="submitRequest" class="request-form">
<div class="form-group">
<label for="name">您的姓名</label>
<input
type="text"
id="name"
v-model="formData.name"
placeholder="请输入您的姓名"
required
/>
</div>
<div class="form-group">
<label for="phone">您的电话</label>
<input
type="tel"
id="phone"
v-model="formData.phone"
placeholder="请输入您的联系电话"
required
pattern="[0-9]{11}"
/>
</div>
<div class="form-group">
<label>合伙类型</label>
<div class="partner-type-selector">
<div
class="partner-type-option"
:class="{ 'active': formData.partnerType === 'community' }"
@click="selectPartnerType('community')"
>
<div class="option-radio">
<div class="radio-inner" v-if="formData.partnerType === 'community'"></div>
</div>
<div class="option-label">小区合伙人</div>
</div>
<div
class="partner-type-option"
:class="{ 'active': formData.partnerType === 'city' }"
@click="selectPartnerType('city')"
>
<div class="option-radio">
<div class="radio-inner" v-if="formData.partnerType === 'city'"></div>
</div>
<div class="option-label">城市合伙人</div>
</div>
</div>
</div>
<div class="form-group">
<label for="serviceArea">
{{ formData.partnerType === 'community' ? '服务小区' : '服务城市' }}
</label>
<input
type="text"
id="serviceArea"
v-model="formData.serviceArea"
:placeholder="formData.partnerType === 'community' ? '请输入小区名称' : '请输入城市名称'"
required
/>
</div>
<div class="form-actions">
<button type="button" class="btn-cancel" @click="goBack">取消</button>
<button type="submit" class="btn-submit" :disabled="isSubmitting">
{{ isSubmitting ? '提交中...' : '提交申请' }}
</button>
</div>
</form>
</div>
<!-- 提交成功弹窗 -->
<div class="success-modal" v-if="showSuccessModal">
<div class="modal-content">
<div class="success-icon"></div>
<h3>申请提交成功</h3>
<p>我们将尽快审核您的合伙人申请</p>
<button @click="closeSuccessModal" class="btn-confirm">确定</button>
</div>
</div>
</div>
</template>
<script>
import { ref, reactive, onMounted, onBeforeUnmount } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import apiClient from '../services/api'
export default {
name: 'PartnerRequest',
setup() {
const router = useRouter()
const route = useRoute()
const isSubmitting = ref(false)
const showSuccessModal = ref(false)
const userId = ref('')
const lastTouchEnd = ref(0)
const formData = reactive({
name: '',
phone: '',
partnerType: 'community', // 默认选择小区服务商
serviceArea: ''
})
onMounted(() => {
// 从URL获取userId
userId.value = route.query.userid || ''
if (!userId.value) {
console.warn('未找到用户ID可能影响提交功能')
}
// 检测是否在小程序环境中
checkMiniProgramEnvironment()
// 设置页面标题
document.title = '合伙人申请 | 蜂快到家'
// 添加额外的触摸事件处理
const handleTouchEnd = (event) => {
const now = Date.now()
if (now - lastTouchEnd.value <= 300) {
event.preventDefault()
}
lastTouchEnd.value = now
}
const handleTouchMove = (event) => {
if (event.touches.length > 1) {
event.preventDefault()
}
}
document.addEventListener('touchend', handleTouchEnd, { passive: false })
document.addEventListener('touchmove', handleTouchMove, { passive: false })
// 保存引用以便在组件卸载时移除
window._partnerRequestTouchHandlers = {
handleTouchEnd,
handleTouchMove
}
})
onBeforeUnmount(() => {
// 移除事件监听器
if (window._partnerRequestTouchHandlers) {
document.removeEventListener('touchend', window._partnerRequestTouchHandlers.handleTouchEnd)
document.removeEventListener('touchmove', window._partnerRequestTouchHandlers.handleTouchMove)
delete window._partnerRequestTouchHandlers
}
})
const handleTouchStart = (event) => {
// 防止双击缩放
if (event.touches.length > 1) {
event.preventDefault()
}
}
const checkMiniProgramEnvironment = () => {
// 检测是否在微信小程序环境中
const ua = navigator.userAgent.toLowerCase()
const isMiniProgram = ua.indexOf('miniprogram') > -1 || window.__wxjs_environment === 'miniprogram'
console.log('Is Mini Program:', isMiniProgram)
}
const selectPartnerType = (type) => {
formData.partnerType = type
// 切换类型时清空服务区域
formData.serviceArea = ''
}
const submitRequest = async () => {
try {
if (!userId.value) {
alert('缺少用户ID无法提交申请')
return
}
isSubmitting.value = true
// 构建提交数据,添加 user_id
const submitData = {
user_id: userId.value,
name: formData.name,
phone: formData.phone,
type: formData.partnerType,
service_target: formData.serviceArea
}
// 使用 apiClient 而不是 axios
const response = await apiClient.post('/api/feedback/partner-apply', submitData)
console.log('提交成功:', response.data)
// 显示成功弹窗
showSuccessModal.value = true
} catch (error) {
console.error('提交失败:', error)
alert('提交失败,请稍后重试')
} finally {
isSubmitting.value = false
}
}
const closeSuccessModal = () => {
showSuccessModal.value = false
// 返回上一页或小程序页面
goBack()
}
const goBack = () => {
// 如果在小程序环境中,调用小程序的返回方法
if (window.wx && window.wx.miniProgram) {
window.wx.miniProgram.navigateBack({ delta: 1 })
} else {
// 否则使用路由返回
router.back()
}
}
return {
formData,
isSubmitting,
showSuccessModal,
submitRequest,
closeSuccessModal,
goBack,
handleTouchStart,
selectPartnerType
}
}
}
</script>
<style scoped>
.partner-request-container {
/* 添加触摸相关样式 */
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
touch-action: manipulation;
min-height: 100vh;
display: flex;
flex-direction: column;
align-items: center;
padding: 20px 15px;
background: linear-gradient(to bottom, #FFCC00, #FFFFFF);
}
.request-card {
width: 100%;
max-width: 90%;
background-color: #FFFFFF;
border-radius: 20px;
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
padding: 25px 20px;
margin-top: 20px;
}
.page-title {
font-size: 22px;
font-weight: bold;
color: #333333;
text-align: center;
margin-bottom: 25px;
}
.request-form {
display: flex;
flex-direction: column;
gap: 20px;
}
.form-group {
display: flex;
flex-direction: column;
gap: 8px;
}
.form-group label {
font-size: 16px;
font-weight: 500;
color: #333333;
}
.form-group input {
padding: 12px 15px;
border: 1px solid #DDDDDD;
border-radius: 8px;
font-size: 16px;
color: #333333;
background-color: #F9F9F9;
transition: border-color 0.3s, box-shadow 0.3s;
}
.form-group input:focus {
border-color: #FFCC00;
box-shadow: 0 0 0 2px rgba(255, 204, 0, 0.2);
outline: none;
}
/* 合伙类型选择器样式 */
.partner-type-selector {
display: flex;
gap: 15px;
}
.partner-type-option {
flex: 1;
display: flex;
align-items: center;
padding: 12px 15px;
border: 1px solid #DDDDDD;
border-radius: 8px;
background-color: #F9F9F9;
cursor: pointer;
transition: all 0.3s;
}
.partner-type-option.active {
border-color: #FFCC00;
background-color: rgba(255, 204, 0, 0.1);
}
.option-radio {
width: 20px;
height: 20px;
border-radius: 50%;
border: 2px solid #DDDDDD;
display: flex;
align-items: center;
justify-content: center;
margin-right: 10px;
transition: all 0.3s;
}
.partner-type-option.active .option-radio {
border-color: #FFCC00;
}
.radio-inner {
width: 10px;
height: 10px;
border-radius: 50%;
background-color: #FFCC00;
}
.option-label {
font-size: 16px;
color: #333333;
}
.form-actions {
display: flex;
justify-content: space-between;
margin-top: 10px;
}
.btn-cancel,
.btn-submit,
.btn-confirm {
padding: 12px 25px;
border-radius: 8px;
font-size: 16px;
font-weight: 500;
cursor: pointer;
transition: all 0.3s;
}
.btn-cancel {
background-color: #F5F5F5;
color: #666666;
border: 1px solid #DDDDDD;
}
.btn-submit {
background-color: #FFCC00;
color: #333333;
border: none;
}
.btn-submit:disabled {
background-color: #FFE580;
cursor: not-allowed;
}
.btn-cancel:hover {
background-color: #EEEEEE;
}
.btn-submit:hover:not(:disabled) {
background-color: #FFD633;
}
/* 成功弹窗样式 */
.success-modal {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
}
.modal-content {
background-color: #FFFFFF;
border-radius: 15px;
padding: 30px;
width: 80%;
max-width: 350px;
text-align: center;
display: flex;
flex-direction: column;
align-items: center;
}
.success-icon {
width: 60px;
height: 60px;
background-color: #FFCC00;
border-radius: 50%;
display: flex;
justify-content: center;
align-items: center;
font-size: 30px;
color: white;
margin-bottom: 20px;
}
.modal-content h3 {
font-size: 20px;
margin-bottom: 10px;
color: #333333;
}
.modal-content p {
color: #666666;
margin-bottom: 25px;
}
.btn-confirm {
background-color: #FFCC00;
color: #333333;
border: none;
width: 100%;
}
.btn-confirm:hover {
background-color: #FFD633;
}
/* 响应式调整 */
@media (max-width: 480px) {
.request-card {
padding: 20px 15px;
}
.page-title {
font-size: 20px;
margin-bottom: 20px;
}
.form-group label {
font-size: 15px;
}
.form-group input,
.btn-cancel,
.btn-submit {
padding: 10px 12px;
font-size: 15px;
}
.partner-type-selector {
flex-direction: column;
gap: 10px;
}
.partner-type-option {
padding: 10px 12px;
}
.option-label {
font-size: 15px;
}
}
</style>