505 lines
11 KiB
Vue
505 lines
11 KiB
Vue
<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> |