HomeLease/pages/agents/agents.vue

984 lines
24 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>
<view class="agents-page">
<!-- 头部区域 -->
<custom-nav-bar3 title=""></custom-nav-bar3>
<view class="header">
<image :src="commonEnum.AGENT" class="agent-background" mode="aspectFill"></image>
</view>
<!-- 主要内容区域 -->
<view class="main-content">
<!-- 表单区域 -->
<view class="form-section">
<!-- 姓名输入 -->
<view class="form-item">
<view class="form-label">请填写您的姓名</view>
<input
v-model="formData.name"
class="form-input"
maxlength="20"
placeholder="请输入您的姓名"
/>
</view>
<!-- 联系方式输入 -->
<view class="form-item">
<view class="form-label">请填写您的联系方式</view>
<input
v-model="formData.phone"
class="form-input"
maxlength="11"
placeholder="请输入您的联系方式"
type="number"
/>
</view>
<!-- 身份证号码输入 -->
<view class="form-item">
<view class="form-label">请输入您的身份证号码</view>
<input
v-model="formData.idCard"
class="form-input"
maxlength="18"
placeholder="请输入您的身份证号码"
/>
</view>
<!-- 服务区域选择 - 三级选择 -->
<view class="form-item">
<view class="form-label">请选择您的服务区域</view>
<!-- 省份选择 -->
<view class="region-picker-item">
<view class="picker-label">省份</view>
<picker
:range="provinceList"
:value="selectedProvinceIndex"
range-key="name"
@change="onProvinceChange"
>
<view class="picker-display">
<text class="picker-text"
>{{ selectedProvince ? selectedProvince.name : '请选择省份' }}
</text>
<text class="picker-arrow">▼</text>
</view>
</picker>
</view>
<!-- 城市选择 -->
<view v-if="selectedProvince" class="region-picker-item">
<view class="picker-label">城市</view>
<picker
:range="cityList"
:value="selectedCityIndex"
range-key="name"
@change="onCityChange"
>
<view class="picker-display">
<text class="picker-text"
>{{ selectedCity ? selectedCity.name : '请选择城市' }}
</text>
<text class="picker-arrow">▼</text>
</view>
</picker>
</view>
<!-- 区县选择 -->
<view v-if="selectedCity" class="region-picker-item">
<view class="picker-label">区县</view>
<picker
:range="districtList"
:value="selectedDistrictIndex"
range-key="name"
@change="onDistrictChange"
>
<view class="picker-display">
<text class="picker-text"
>{{ selectedDistrict ? selectedDistrict.name : '请选择区县' }}
</text>
<text class="picker-arrow">▼</text>
</view>
</picker>
</view>
<!-- 显示完整地址 -->
<view v-if="selectedDistrict" class="selected-address">
<text class="address-text"
>已选择: {{ selectedProvince.name }} {{ selectedCity.name }}
{{ selectedDistrict.name }}
</text>
</view>
</view>
<!-- 详细地址输入 -->
<view class="form-item">
<view class="form-label">请输入您的详细地址</view>
<input
v-model="formData.detailAddress"
class="form-input"
maxlength="100"
placeholder="请输入您的详细地址"
/>
</view>
<!-- 协议同意 -->
<view class="agreement-section">
<view class="agreement-item" @click="toggleAgreement">
<view :class="{ checked: formData.agreed }" class="checkbox">
<text v-if="formData.agreed" class="checkmark">✓</text>
</view>
<text class="agreement-text">
我已阅读并同意
<text class="agreement-link" @click.stop="showAgreement">《代理商协议》</text>
</text>
</view>
</view>
<!-- 提交按钮 -->
<view class="submit-section">
<button
:disabled="!canSubmit || submitting"
class="submit-btn"
@click="submitApplication"
>
{{ submitting ? '提交中...' : '申请成为代理商' }}
</button>
</view>
</view>
</view>
<!-- 代理商协议模态框 -->
<view v-if="showAgreementModal" class="agreement-modal-overlay" @click="hideAgreement">
<view class="agreement-modal" @click.stop>
<view class="agreement-modal-header">
<text class="agreement-modal-title">代理商协议</text>
<text class="agreement-modal-close" @click="hideAgreement">×</text>
</view>
<scroll-view class="agreement-modal-content" scroll-y>
<rich-text :nodes="agreementContent"></rich-text>
</scroll-view>
<view class="agreement-modal-footer">
<view class="agreement-modal-checkbox" @click="toggleAgreement">
<view :class="{ checked: formData.agreed }" class="modal-checkbox">
<text v-if="formData.agreed" class="checkmark">✓</text>
</view>
<text class="modal-checkbox-text">我已阅读并同意代理商协议</text>
</view>
<button
:class="{ disabled: !formData.agreed }"
class="agreement-modal-btn"
@click="hideAgreement"
>
{{ formData.agreed ? '确定' : '请先同意协议' }}
</button>
</view>
</view>
</view>
</view>
</template>
<script>
import commonEnum from '../../enum/commonEnum'
import { applyForAgent, getAgentAgreement, getServiceAreas } from '@/api/agents'
export default {
name: 'AgentsPage',
components: {},
computed: {
commonEnum() {
return commonEnum
},
canSubmit() {
return (
// this.formData.name &&
// this.formData.phone &&
// this.formData.idCard &&
// this.selectedDistrict && // 必须选择到区县级别
// this.formData.detailAddress &&
!this.submitting
)
},
},
onLoad() {
// 页面加载时获取服务区域列表和协议内容
this.loadServiceAreas()
this.loadAgreement()
this.loadRegionTreeData()
// 重置协议同意状态,用于测试协议弹窗功能
this.formData.agreed = false
// 添加测试数据
console.log('页面加载完成,三级选择器已初始化')
},
data() {
return {
formData: {
name: '',
phone: '',
idCard: '',
serviceArea: '',
detailAddress: '',
agreed: false,
},
submitting: false,
serviceAreas: [],
agreementContent: '',
showAgreementModal: false,
// 区域ID映射
areaIdMap: {},
// 三级选择相关数据
regionTreeData: [],
// 省份相关
provinceList: [],
selectedProvince: null,
selectedProvinceIndex: -1,
// 城市相关
cityList: [],
selectedCity: null,
selectedCityIndex: -1,
// 区县相关
districtList: [],
selectedDistrict: null,
selectedDistrictIndex: -1,
}
},
methods: {
// 加载服务区域列表
async loadServiceAreas() {
try {
const response = await getServiceAreas()
if (response.code === 200 && response.data) {
// 处理服务器返回的区域数据提取所有区域名称和ID映射
const { names, idMap } = this.extractRegionData(response.data)
this.serviceAreas = names
this.areaIdMap = idMap
console.log('获取到的区域列表:', this.serviceAreas)
console.log('区域ID映射:', this.areaIdMap)
}
} catch (error) {
console.error('获取服务区域失败:', error)
// 使用默认区域列表
this.serviceAreas = [
'福建省宁德市福鼎市',
'福建省宁德市霞浦县',
'福建省宁德市古田县',
'福建省宁德市屏南县',
]
// 默认区域ID映射
this.areaIdMap = {
福建省宁德市福鼎市: 8,
福建省宁德市霞浦县: 9,
福建省宁德市古田县: 10,
福建省宁德市屏南县: 11,
}
}
},
// 从区域数据中提取区域名称和ID映射
extractRegionData(regions) {
const names = []
const idMap = {}
const extractData = regionList => {
regionList.forEach(region => {
names.push(region.name)
idMap[region.name] = region.id
if (region.children && region.children.length > 0) {
extractData(region.children)
}
})
}
extractData(regions)
return { names, idMap }
},
// 加载代理商协议
async loadAgreement() {
try {
const response = await getAgentAgreement()
if (response.code === 200 && response.data) {
this.agreementContent = response.data.content || '这里是代理商协议的详细内容...'
}
} catch (error) {
console.error('获取代理商协议失败:', error)
this.agreementContent = '这里是代理商协议的详细内容...'
}
},
// 切换协议同意状态
toggleAgreement() {
this.formData.agreed = !this.formData.agreed
},
// 显示代理商协议
showAgreement() {
this.showAgreementModal = true
},
// 隐藏代理商协议
hideAgreement() {
this.showAgreementModal = false
},
// 验证表单数据
validateForm() {
if (!this.formData.name.trim()) {
uni.showToast({
title: '请输入姓名',
icon: 'none',
})
return false
}
if (!this.formData.phone.trim()) {
uni.showToast({
title: '请输入手机号',
icon: 'none',
})
return false
}
// 验证手机号格式
const phoneRegex = /^1[3-9]\d{9}$/
if (!phoneRegex.test(this.formData.phone)) {
uni.showToast({
title: '请输入正确的手机号',
icon: 'none',
})
return false
}
if (!this.formData.idCard.trim()) {
uni.showToast({
title: '请输入身份证号',
icon: 'none',
})
return false
}
// 验证身份证号格式
const idCardRegex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
if (!idCardRegex.test(this.formData.idCard)) {
uni.showToast({
title: '请输入正确的身份证号',
icon: 'none',
})
return false
}
if (!this.formData.serviceArea) {
uni.showToast({
title: '请选择服务区域',
icon: 'none',
})
return false
}
if (!this.formData.detailAddress.trim()) {
uni.showToast({
title: '请输入详细地址',
icon: 'none',
})
return false
}
if (!this.formData.agreed) {
uni.showToast({
title: '请先同意代理商协议',
icon: 'none',
})
return false
}
return true
},
// 提交申请
async submitApplication() {
// 检查是否同意协议,如果未同意则自动弹窗
if (!this.formData.agreed) {
this.showAgreement()
uni.showToast({
title: '请先阅读并同意代理商协议',
icon: 'none',
})
return
}
if (!this.validateForm()) {
return
}
this.submitting = true
try {
// 构建请求数据
const regionId = this.getSelectedRegionId()
if (!regionId) {
uni.showToast({
title: '请选择服务区域',
icon: 'none',
})
return
}
const requestData = {
name: this.formData.name.trim(),
phone: this.formData.phone.trim(),
idCard: this.formData.idCard.trim(),
regionId: regionId,
address: this.formData.detailAddress.trim(),
}
console.log('提交代理商申请:', requestData)
console.log('三级选择信息:', {
省份: this.selectedProvince?.name,
城市: this.selectedCity?.name,
区县: this.selectedDistrict?.name,
完整地址: this.formData.serviceArea,
区域ID: regionId,
})
const response = await applyForAgent(requestData)
if (response.code === 200) {
uni.showModal({
title: '申请成功',
content: '您的代理商申请已提交我们将在3个工作日内审核并联系您。',
showCancel: false,
confirmText: '确定',
success: () => {
// 重置表单
this.resetForm()
},
})
} else {
uni.showToast({
title: response.msg || '申请失败,请重试',
icon: 'none',
})
}
} catch (error) {
console.error('提交代理商申请失败:', error)
uni.showToast({
title: '网络错误,请重试',
icon: 'none',
})
} finally {
this.submitting = false
}
},
// 重置表单
resetForm() {
this.formData = {
name: '',
phone: '',
idCard: '',
serviceArea: '',
detailAddress: '',
agreed: false,
}
// 重置三级选择
this.selectedProvince = null
this.selectedProvinceIndex = -1
this.selectedCity = null
this.selectedCityIndex = -1
this.selectedDistrict = null
this.selectedDistrictIndex = -1
this.cityList = []
this.districtList = []
},
// 三级选择相关方法
async loadRegionTreeData() {
try {
const response = await getServiceAreas()
if (response.code === 200 && response.data) {
this.regionTreeData = response.data
console.log('获取到的区域树形数据:', this.regionTreeData)
}
} catch (error) {
console.error('获取区域树形数据失败:', error)
// 使用默认的树形数据
this.regionTreeData = [
{
id: 1,
name: '福建省',
children: [
{
id: 2,
name: '宁德市',
children: [
{ id: 8, name: '福鼎市' },
{ id: 9, name: '霞浦县' },
{ id: 10, name: '古田县' },
{ id: 11, name: '屏南县' },
],
},
],
},
]
}
// 初始化三级选择数据
this.initThreeLevelData()
},
// 初始化三级选择数据
initThreeLevelData() {
// 初始化省份列表
this.provinceList = this.regionTreeData
// 初始化 areaIdMap
this.initAreaIdMap()
},
// 初始化区域ID映射
initAreaIdMap() {
const idMap = {}
const extractIds = regions => {
regions.forEach(region => {
idMap[region.name] = region.id
if (region.children && region.children.length > 0) {
extractIds(region.children)
}
})
}
extractIds(this.regionTreeData)
this.areaIdMap = idMap
console.log('区域ID映射:', this.areaIdMap)
},
// 省份选择事件
onProvinceChange(e) {
const index = e.detail.value
this.selectedProvinceIndex = index
this.selectedProvince = this.provinceList[index]
// 重置城市和区县选择
this.selectedCity = null
this.selectedCityIndex = -1
this.selectedDistrict = null
this.selectedDistrictIndex = -1
// 更新城市列表
this.cityList = this.selectedProvince.children || []
this.districtList = []
// 更新服务区域
this.updateServiceArea()
},
// 城市选择事件
onCityChange(e) {
const index = e.detail.value
this.selectedCityIndex = index
this.selectedCity = this.cityList[index]
// 重置区县选择
this.selectedDistrict = null
this.selectedDistrictIndex = -1
// 更新区县列表
this.districtList = this.selectedCity.children || []
// 更新服务区域
this.updateServiceArea()
},
// 区县选择事件
onDistrictChange(e) {
const index = e.detail.value
this.selectedDistrictIndex = index
this.selectedDistrict = this.districtList[index]
// 更新服务区域
this.updateServiceArea()
},
// 更新服务区域
updateServiceArea() {
if (this.selectedProvince && this.selectedCity && this.selectedDistrict) {
this.formData.serviceArea = `${this.selectedProvince.name}${this.selectedCity.name}${this.selectedDistrict.name}`
} else if (this.selectedProvince && this.selectedCity) {
this.formData.serviceArea = `${this.selectedProvince.name}${this.selectedCity.name}`
} else if (this.selectedProvince) {
this.formData.serviceArea = this.selectedProvince.name
} else {
this.formData.serviceArea = ''
}
},
// 获取选中区域的ID
getSelectedRegionId() {
if (this.selectedDistrict) {
return this.selectedDistrict.id
} else if (this.selectedCity) {
return this.selectedCity.id
} else if (this.selectedProvince) {
return this.selectedProvince.id
}
return null
},
},
}
</script>
<style lang="scss" scoped>
.agents-page {
position: relative;
background: #f3f5f6;
}
// 头部区域
.header {
position: relative;
background: #fedfcd;
.agent-background {
position: relative;
width: 750rpx;
}
}
// 主要内容区域
.main-content {
position: relative;
top: -34rpx;
background: #ffffff;
border-radius: 40rpx 40rpx 0 0;
margin: 0 30rpx;
padding: 40rpx;
}
// 表单区域
.form-section {
.form-title {
font-size: 36rpx;
font-weight: bold;
color: #333;
text-align: center;
margin-bottom: 60rpx;
}
.form-item {
margin-bottom: 40rpx;
.form-label {
font-size: 28rpx;
color: #333;
margin-bottom: 20rpx;
font-weight: 500;
}
.form-input {
width: 100%;
height: 80rpx;
background: #ffffff;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
padding: 0 24rpx;
font-size: 28rpx;
color: #333;
box-sizing: border-box;
&:focus {
border-color: #ff6b6b;
}
&::placeholder {
color: #999;
}
}
.form-selector {
width: 100%;
height: 80rpx;
background: #ffffff;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
padding: 0 24rpx;
display: flex;
align-items: center;
justify-content: space-between;
box-sizing: border-box;
.selector-text {
font-size: 28rpx;
color: #333;
flex: 1;
}
.arrow-icon {
font-size: 24rpx;
color: #999;
transform: rotate(90deg);
}
}
}
}
// 协议区域
.agreement-section {
margin-bottom: 60rpx;
.agreement-item {
display: flex;
align-items: center;
.checkbox {
width: 32rpx;
height: 32rpx;
border: 2rpx solid #ff6b6b;
border-radius: 6rpx;
margin-right: 20rpx;
display: flex;
align-items: center;
justify-content: center;
background: #ffffff;
&.checked {
background: #f15a04;
}
.checkmark {
color: #ffffff;
font-size: 20rpx;
font-weight: bold;
}
}
.agreement-text {
font-size: 26rpx;
color: #666;
flex: 1;
.agreement-link {
color: #f15a04;
text-decoration: underline;
}
}
}
}
// 提交区域
.submit-section {
.submit-btn {
width: 100%;
height: 88rpx;
background: #f15a04;
color: #ffffff;
border: none;
border-radius: 12rpx;
font-size: 32rpx;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
&:disabled {
background: #cccccc;
color: #999999;
}
&:active {
transform: scale(0.98);
}
}
}
// 代理商协议模态框样式
.agreement-modal-overlay {
position: fixed;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(0, 0, 0, 0.5);
z-index: 9999;
display: flex;
align-items: center;
justify-content: center;
}
.agreement-modal {
width: 90%;
max-width: 600rpx;
max-height: 80%;
background: #ffffff;
border-radius: 20rpx;
overflow: hidden;
display: flex;
flex-direction: column;
}
.agreement-modal-header {
padding: 30rpx;
border-bottom: 1rpx solid #e8e8e8;
display: flex;
align-items: center;
justify-content: space-between;
background: #f8f8f8;
.agreement-modal-title {
font-size: 32rpx;
font-weight: bold;
color: #333;
}
.agreement-modal-close {
font-size: 40rpx;
color: #999;
cursor: pointer;
padding: 10rpx;
}
}
.agreement-modal-content {
flex: 1;
padding: 50rpx;
max-width: 500rpx;
max-height: 600rpx;
overflow-y: auto;
}
.agreement-modal-footer {
padding: 30rpx;
border-top: 1rpx solid #e8e8e8;
background: #f8f8f8;
.agreement-modal-checkbox {
display: flex;
align-items: center;
margin-bottom: 20rpx;
.modal-checkbox {
width: 32rpx;
height: 32rpx;
border: 2rpx solid #ff6b6b;
border-radius: 6rpx;
margin-right: 10rpx;
display: flex;
align-items: center;
justify-content: center;
background: #ffffff;
&.checked {
background: #f15a04;
}
.checkmark {
color: #ffffff;
font-size: 20rpx;
font-weight: bold;
}
}
.modal-checkbox-text {
font-size: 26rpx;
color: #666;
}
}
.agreement-modal-btn {
width: 100%;
height: 80rpx;
background: #f15a04;
color: #ffffff;
border: none;
border-radius: 12rpx;
font-size: 28rpx;
font-weight: bold;
display: flex;
align-items: center;
justify-content: center;
&:active {
transform: scale(0.98);
}
&.disabled {
background: #cccccc;
color: #999999;
cursor: not-allowed;
&:active {
transform: none;
}
}
}
}
.debug-info {
background: #f0f0f0;
padding: 10rpx;
margin-bottom: 10rpx;
border-radius: 8rpx;
font-size: 24rpx;
color: #666;
text {
display: block;
margin-bottom: 5rpx;
}
}
// 三级选择器样式
.region-picker-item {
margin-bottom: 20rpx;
.picker-label {
font-size: 26rpx;
color: #666;
margin-bottom: 10rpx;
font-weight: 500;
}
.picker-display {
height: 80rpx;
background: #ffffff;
border: 2rpx solid #e8e8e8;
border-radius: 12rpx;
padding: 0 24rpx;
box-sizing: border-box;
display: flex;
align-items: center;
justify-content: space-between;
cursor: pointer;
&:active {
background: #f5f5f5;
}
.picker-text {
font-size: 28rpx;
color: #333;
flex: 1;
}
.picker-arrow {
font-size: 24rpx;
color: #999;
}
}
}
.selected-address {
margin-top: 20rpx;
padding: 20rpx;
background: #f8f9fa;
border-radius: 12rpx;
border: 2rpx solid #e9ecef;
.address-text {
font-size: 28rpx;
color: #495057;
font-weight: 500;
}
}
</style>