小程序停车场名称动态化实现方案
📋 需求分析
当前问题
- 停车场名称固定: 页面顶部显示的停车场名称是固定的"欧洲新城-停车场"
- 访问地址固定: 下方的访问地址选择器显示的是固定的小区信息
- 缺乏动态性: 没有根据当前管家的小区信息动态调整
目标效果
- 动态停车场名称: 根据当前管家所管理的小区动态显示停车场名称
- 动态访问地址: 访问地址选择器根据管家的小区动态加载楼栋、单元、房间信息
- 管家角色适配: 针对管家角色优化地址选择和业主信息查询
🏗️ 技术方案
1. 获取管家小区信息的策略
方案A: 从用户信息中获取(推荐)
// 在getUserRole方法中扩展管家信息获取
async getUserRole() {try {const userInfo = uni.getStorageSync('userInfo');if (userInfo && userInfo.role) {this.currentUserRole = userInfo.role;// 如果是管家角色,获取管家的小区信息if (this.currentUserRole === 'manager') {await this.loadManagerCommunityInfo(userInfo);}}// 其他现有逻辑...} catch (error) {console.error('获取用户信息失败:', error);}
}
方案B: 通过API查询管家信息
// 新增方法:查询管家的小区信息
async loadManagerCommunityInfo(userInfo) {try {// 如果用户信息中已有小区信息,直接使用if (userInfo.userInfo && userInfo.userInfo.community) {const managerCommunity = {name: userInfo.userInfo.community,province: userInfo.userInfo.province || '黑龙江省',city: userInfo.userInfo.city || '哈尔滨市',district: userInfo.userInfo.district || '香坊区'};this.setManagerCommunityInfo(managerCommunity);return;}// 如果没有小区信息,通过API查询const phone = userInfo.phone || userInfo.userInfo?.phone;if (phone) {const response = await this.queryManagerCommunityByPhone(phone);if (response && response.data) {this.setManagerCommunityInfo(response.data);}}} catch (error) {console.error('加载管家小区信息失败:', error);// 使用默认小区信息this.useDefaultCommunityInfo();}
}
2. 动态更新停车场信息
修改updateParkingLotInfo方法
async updateParkingLotInfo(userInfo) {try {let addressInfo;// 如果是管家角色,优先使用管家的小区信息if (this.currentUserRole === 'manager' && this.managerCommunityInfo) {addressInfo = {province: this.managerCommunityInfo.province,city: this.managerCommunityInfo.city,district: this.managerCommunityInfo.district,community: this.managerCommunityInfo.name};console.log('👨💼 [管家角色] 使用管家小区信息:', addressInfo);} else {// 其他角色使用原有逻辑addressInfo = await this.getAddressInfo(userInfo);}// 构建停车场全名const fullName = `${addressInfo.community}-停车场`;const fullAddress = `${addressInfo.province}${addressInfo.city}${addressInfo.district}${addressInfo.community}`;// 更新停车场信息this.parkingLotInfo = {fullName: fullName,fullAddress: fullAddress,buildingInfo: this.parkingLotInfo.buildingInfo || ''};// 更新页面标题uni.setNavigationBarTitle({title: fullName});console.log('✅ 停车场信息已更新:', this.parkingLotInfo);} catch (error) {console.error('❌ 更新停车场信息失败:', error);}
}
3. 动态加载地址数据
修改loadAddressData方法
async loadAddressData() {try {console.log('🚀 开始加载四级地址数据');let communityName;// 如果是管家角色,使用管家的小区信息if (this.currentUserRole === 'manager' && this.managerCommunityInfo) {communityName = this.managerCommunityInfo.name;console.log('👨💼 [管家角色] 使用管家小区名称:', communityName);} else {// 其他角色使用原有逻辑const parkInfo = uni.getStorageSync('parkInfo');communityName = parkInfo?.name || this.currentCommunityName || '四季上东';}// URL编码处理if (communityName && typeof communityName === 'string' && communityName.includes('%')) {try {communityName = decodeURIComponent(communityName);} catch (e) {console.error('解码小区名称失败:', e);}}console.log('📍 最终使用的小区名称:', communityName);// 显示加载提示uni.showLoading({title: '加载地址数据...',mask: true});// 调用API加载地址数据const response = await uni.request({url: `https://csharphrb.picp.vip/parking/community/getAllCommunity?community=${encodeURIComponent(communityName)}`,method: 'GET',header: {'content-type': 'application/json'},timeout: 10000});// 处理响应数据的逻辑保持不变...} catch (error) {console.error('❌ 加载地址数据失败:', error);// 错误处理逻辑...} finally {uni.hideLoading();}
}
🔧 具体实现步骤
步骤1: 在data中添加管家小区信息
data() {return {// 现有数据...// 新增:管家小区信息managerCommunityInfo: null, // 管家的小区信息isManagerCommunityLoaded: false, // 是否已加载管家小区信息}
}
步骤2: 新增管家小区信息相关方法
methods: {// 现有方法...// 新增:设置管家小区信息setManagerCommunityInfo(communityInfo) {this.managerCommunityInfo = communityInfo;this.isManagerCommunityLoaded = true;// 更新当前小区名称this.currentCommunityName = communityInfo.name;// 保存到本地存储const parkInfo = {name: communityInfo.name,fullName: `${communityInfo.name}-停车场`,province: communityInfo.province,city: communityInfo.city,district: communityInfo.district};uni.setStorageSync('parkInfo', parkInfo);console.log('✅ 管家小区信息已设置:', this.managerCommunityInfo);},// 新增:通过手机号查询管家小区信息async queryManagerCommunityByPhone(phone) {try {// 这里需要调用后端API查询管家信息// 假设API接口为 /parking/butler/getCommunityByPhoneconst response = await uni.request({url: `https://csharphrb.picp.vip/parking/butler/getCommunityByPhone?phone=${phone}`,method: 'GET',header: {'content-type': 'application/json'},timeout: 10000});if (response.statusCode === 200 && response.data.code === '0') {return response.data;} else {throw new Error('查询管家小区信息失败');}} catch (error) {console.error('查询管家小区信息失败:', error);return null;}},// 新增:使用默认小区信息useDefaultCommunityInfo() {const defaultCommunity = {name: '四季上东',province: '黑龙江省',city: '哈尔滨市',district: '香坊区'};this.setManagerCommunityInfo(defaultCommunity);}
}
步骤3: 修改页面加载逻辑
async onLoad(options) {try {console.log('🔍 onLoad开始执行,接收到参数:', options);// 获取用户角色(这里会处理管家小区信息)await this.getUserRole();// 处理扫码传入的地址参数if (options) {// 现有逻辑...}// 初始化地址数据 - 确保在管家小区信息加载后执行if (this.currentUserRole === 'manager') {// 等待管家小区信息加载完成await this.waitForManagerCommunityInfo();}await this.loadCurrentCommunityInfo();// 其他现有逻辑...} catch (error) {console.error('onLoad错误:', error);}
},// 新增:等待管家小区信息加载完成
async waitForManagerCommunityInfo() {let attempts = 0;const maxAttempts = 10;while (!this.isManagerCommunityLoaded && attempts < maxAttempts) {await new Promise(resolve => setTimeout(resolve, 100));attempts++;}if (!this.isManagerCommunityLoaded) {console.warn('⚠️ 管家小区信息加载超时,使用默认信息');this.useDefaultCommunityInfo();}
}
🎯 后端API支持
需要新增的API接口
1. 根据管家手机号查询小区信息
@RestController
@RequestMapping("/parking/butler")
public class ButlerController {@GetMapping("/getCommunityByPhone")public ResponseEntity<Result> getCommunityByPhone(@RequestParam String phone) {try {// 根据手机号查询管家信息Butler butler = butlerService.getByPhone(phone);if (butler != null) {Map<String, Object> communityInfo = new HashMap<>();communityInfo.put("name", butler.getCommunity());communityInfo.put("province", butler.getProvince());communityInfo.put("city", butler.getCity());communityInfo.put("district", butler.getDistrict());Result result = new Result();result.setCode("0");result.setData(communityInfo);result.setMsg("查询成功");return ResponseEntity.ok(result);} else {Result result = new Result();result.setCode("1");result.setMsg("未找到管家信息");return ResponseEntity.ok(result);}} catch (Exception e) {Result result = new Result();result.setCode("1");result.setMsg("查询失败: " + e.getMessage());return ResponseEntity.ok(result);}}
}
2. 确保Butler实体类包含小区信息字段
@Data
@TableName("butler")
public class Butler {@TableId(value = "id", type = IdType.AUTO)private Integer id;private String name;private String phone;private String openid;// 新增小区相关字段private String community; // 小区名称private String province; // 省份private String city; // 城市private String district; // 区域// 其他现有字段...
}
📱 前端UI优化
1. 添加管家小区信息显示
<template><!-- 在停车场名称下方添加管家小区提示 --><view class="name"><text class="name-css">{{ parkingLotInfo.fullName }}</text><!-- 管家角色显示当前管理的小区 --><view v-if="currentUserRole === 'manager' && managerCommunityInfo" class="manager-community-info"><text class="manager-label">当前管理小区:</text><text class="community-name">{{ managerCommunityInfo.name }}</text></view></view></template><style>
.manager-community-info {margin-top: 10rpx;display: flex;align-items: center;justify-content: center;
}.manager-label {font-size: 24rpx;color: #666;margin-right: 8rpx;
}.community-name {font-size: 26rpx;color: #025def;font-weight: 500;
}
</style>
2. 优化地址选择器提示
<!-- 在地址选择器中添加管家专用提示 -->
<u-form-item leftIcon="home" labelPosition="left" :leftIconStyle="{ 'color': '#025def' }" labelWidth="90" borderBottom="false" label="访问地址"><!-- 管家角色专用提示 --><view v-if="currentUserRole === 'manager'" class="manager-address-tip"><text class="tip-text">请选择要代为预约的业主地址</text></view><!-- 现有地址选择器内容... -->
</u-form-item>
🧪 测试方案
1. 功能测试
- 管家登录后停车场名称正确显示
- 地址选择器加载管家小区的楼栋信息
- 选择地址后正确查询业主信息
- 非管家角色不受影响
2. 异常测试
- 管家小区信息查询失败时的降级处理
- 网络异常时的错误提示
- 数据格式异常的处理
3. 性能测试
- 页面加载速度
- API响应时间
- 内存使用情况
📋 实施清单
前端修改
- 修改getUserRole方法,添加管家小区信息加载
- 新增管家小区信息相关方法
- 修改updateParkingLotInfo方法
- 修改loadAddressData方法
- 优化UI显示
后端修改
- 新增Butler小区信息查询API
- 确保Butler实体类包含小区字段
- 测试API接口
测试验证
- 功能测试
- 异常测试
- 性能测试
1. 修改form.vue的data部分
在现有的data()方法中添加管家小区信息:
data() {return {// 现有数据保持不变...currentUserRole: 'owner',// 新增:管家小区信息相关managerCommunityInfo: null, // 管家的小区信息isManagerCommunityLoaded: false, // 是否已加载管家小区信息managerLoadingTimeout: null, // 加载超时定时器// 现有的其他数据...parkingLotInfo: {fullName: '',fullAddress: '',buildingInfo: ''},}
}
2. 修改getUserRole方法
在现有的getUserRole方法中添加管家小区信息处理:
// 在form.vue的methods中修改现有的getUserRole方法
async getUserRole() {try {const userInfo = uni.getStorageSync('userInfo');// 获取角色if (userInfo && userInfo.role) {this.currentUserRole = userInfo.role;console.log('👤 当前用户角色:', this.currentUserRole);// 🆕 如果是管家角色,加载管家的小区信息if (this.currentUserRole === 'manager') {console.log('👨💼 检测到管家角色,开始加载小区信息');await this.loadManagerCommunityInfo(userInfo);}} else {this.currentUserRole = 'owner';}// 获取电话号码的现有逻辑保持不变...let phone = '';if (userInfo && userInfo.phone) {phone = userInfo.phone;} else if (userInfo && userInfo.userInfo && userInfo.userInfo.phone) {phone = userInfo.userInfo.phone;}// 管家角色:联系电话初始为空,选择业主后自动填充业主电话// 其他角色:自动填充当前用户电话if (this.currentUserRole === 'manager') {this.model1.code = ''; // 管家角色初始为空console.log('👨💼 [管家角色] 联系电话初始化为空,等待选择业主后填充');} else if (phone) {this.model1.code = phone; // 其他角色自动填充console.log('👤 [其他角色] 联系电话自动填充:', phone);}// 现有的其他逻辑保持不变...this.checkButlerInfo(userInfo);this.updateReasonOptions();await this.updateParkingLotInfo(userInfo);if (this.currentUserRole === 'owner') {this.loadMonthlyTicketInfo();}} catch (error) {console.error('获取用户信息失败:', error);this.currentUserRole = 'owner';}
}
3. 新增管家小区信息处理方法
在form.vue的methods中添加以下新方法:
// 🆕 加载管家小区信息
async loadManagerCommunityInfo(userInfo) {try {console.log('🏠 开始加载管家小区信息:', userInfo);// 方案1: 从用户信息中直接获取小区信息if (userInfo.userInfo && userInfo.userInfo.community) {const managerCommunity = {name: userInfo.userInfo.community,province: userInfo.userInfo.province || '黑龙江省',city: userInfo.userInfo.city || '哈尔滨市',district: userInfo.userInfo.district || '香坊区'};this.setManagerCommunityInfo(managerCommunity);console.log('✅ 从用户信息中获取到管家小区信息');return;}// 方案2: 通过手机号查询管家小区信息const phone = userInfo.phone || userInfo.userInfo?.phone;if (phone) {console.log('📞 通过手机号查询管家小区信息:', phone);const response = await this.queryManagerCommunityByPhone(phone);if (response && response.data) {this.setManagerCommunityInfo(response.data);console.log('✅ 通过API查询到管家小区信息');return;}}// 方案3: 使用默认小区信息console.log('⚠️ 未找到管家小区信息,使用默认值');this.useDefaultCommunityInfo();} catch (error) {console.error('❌ 加载管家小区信息失败:', error);this.useDefaultCommunityInfo();}
},// 🆕 设置管家小区信息
setManagerCommunityInfo(communityInfo) {this.managerCommunityInfo = communityInfo;this.isManagerCommunityLoaded = true;// 更新当前小区名称this.currentCommunityName = communityInfo.name;// 保存到本地存储,供其他方法使用const parkInfo = {name: communityInfo.name,fullName: `${communityInfo.name}-停车场`,province: communityInfo.province,city: communityInfo.city,district: communityInfo.district,fullAddress: `${communityInfo.province}${communityInfo.city}${communityInfo.district}${communityInfo.name}`};uni.setStorageSync('parkInfo', parkInfo);console.log('✅ 管家小区信息已设置:', this.managerCommunityInfo);console.log('✅ parkInfo已更新:', parkInfo);
},// 🆕 通过手机号查询管家小区信息
async queryManagerCommunityByPhone(phone) {try {const response = await uni.request({url: `https://csharphrb.picp.vip/parking/butler/getCommunityByPhone?phone=${phone}`,method: 'GET',header: {'content-type': 'application/json'},timeout: 10000});console.log('🔍 管家小区查询API响应:', response);if (response.statusCode === 200 && response.data.code === '0') {return response.data;} else {console.warn('⚠️ 查询管家小区信息失败:', response.data.msg);return null;}} catch (error) {console.error('❌ 查询管家小区信息API调用失败:', error);return null;}
},// 🆕 使用默认小区信息
useDefaultCommunityInfo() {const defaultCommunity = {name: '四季上东',province: '黑龙江省',city: '哈尔滨市',district: '香坊区'};this.setManagerCommunityInfo(defaultCommunity);console.log('📍 使用默认管家小区信息:', defaultCommunity);
},// 🆕 等待管家小区信息加载完成
async waitForManagerCommunityInfo() {let attempts = 0;const maxAttempts = 20; // 最多等待2秒while (!this.isManagerCommunityLoaded && attempts < maxAttempts) {await new Promise(resolve => setTimeout(resolve, 100));attempts++;}if (!this.isManagerCommunityLoaded) {console.warn('⚠️ 管家小区信息加载超时,使用默认信息');this.useDefaultCommunityInfo();}console.log(`✅ 管家小区信息加载完成,耗时: ${attempts * 100}ms`);
}
4. 修改updateParkingLotInfo方法
在现有的updateParkingLotInfo方法中添加管家角色处理:
// 修改现有的updateParkingLotInfo方法
async updateParkingLotInfo(userInfo) {try {let addressInfo;// 🆕 如果是管家角色且已加载小区信息,优先使用管家的小区信息if (this.currentUserRole === 'manager' && this.managerCommunityInfo) {addressInfo = {province: this.managerCommunityInfo.province,city: this.managerCommunityInfo.city,district: this.managerCommunityInfo.district,community: this.managerCommunityInfo.name};console.log('👨💼 [管家角色] 使用管家小区信息更新停车场:', addressInfo);} else {// 其他角色使用原有逻辑addressInfo = await this.getAddressInfo(userInfo);console.log('👤 [其他角色] 使用原有逻辑获取地址信息:', addressInfo);}// 检查本地存储中是否有更新的小区信息(保持原有逻辑)const parkInfo = uni.getStorageSync('parkInfo');if (parkInfo && parkInfo.name) {let fullName = parkInfo.fullName || `${parkInfo.name}-停车场`;let fullAddress = parkInfo.fullAddress;if (!fullAddress) {fullAddress = `${parkInfo.province || '黑龙江省'}${parkInfo.city || '哈尔滨市'}${parkInfo.district || '香坊区'}${parkInfo.name}`;}// 更新停车场信息this.parkingLotInfo = {fullName: fullName,fullAddress: fullAddress,buildingInfo: this.parkingLotInfo.buildingInfo || ''};console.log("🔍 使用本地存储更新的停车场信息:", this.parkingLotInfo);// 🆕 更新页面标题uni.setNavigationBarTitle({title: fullName});return;}// 如果没有本地存储的信息,使用获取到的地址信息构建const fullName = `${addressInfo.community}-停车场`;const fullAddress = `${addressInfo.province}${addressInfo.city}${addressInfo.district}${addressInfo.community}`;// 更新停车场信息this.parkingLotInfo = {fullName: fullName,fullAddress: fullAddress,buildingInfo: ''};// 🆕 更新页面标题uni.setNavigationBarTitle({title: fullName});console.log('✅ 停车场信息已更新:', this.parkingLotInfo);} catch (error) {console.error('❌ 更新停车场信息失败:', error);}
}
5. 修改onLoad方法
在现有的onLoad方法中添加管家角色的特殊处理:
async onLoad(options) {try {console.log('🔍 onLoad开始执行,接收到参数:', options);// 获取用户角色(这里会处理管家小区信息)await this.getUserRole();// 🆕 如果是管家角色,等待小区信息加载完成if (this.currentUserRole === 'manager') {console.log('👨💼 管家角色,等待小区信息加载完成...');await this.waitForManagerCommunityInfo();}// 处理扫码传入的地址参数(保持原有逻辑)if (options) {// 现有的参数处理逻辑...const decodedParams = {};for (const key in options) {if (options.hasOwnProperty(key)) {try {decodedParams[key] = decodeURIComponent(options[key]);} catch (e) {decodedParams[key] = options[key];}}}// 现有的小区信息处理逻辑...if (decodedParams.community) {// 只有非管家角色才处理扫码的小区信息if (this.currentUserRole !== 'manager') {const parkInfo = {name: decodedParams.community,fullName: `${decodedParams.community}-停车场`,province: decodedParams.province || '黑龙江省',city: decodedParams.city || '哈尔滨市',district: decodedParams.district || '香坊区',address: decodedParams.address || '',fullAddress: decodedParams.fullAddress || ''};uni.setStorageSync('parkInfo', parkInfo);this.parkingLotInfo = {fullName: parkInfo.fullName,fullAddress: `${parkInfo.province}${parkInfo.city}${parkInfo.district}${parkInfo.address || parkInfo.name}`,buildingInfo: ''};console.log('🔍 非管家角色,使用扫码的停车场信息:', this.parkingLotInfo);} else {console.log('👨💼 管家角色,忽略扫码的小区信息,使用管家自己的小区');}}// 处理管家信息(保持原有逻辑)if (decodedParams.butlerName || decodedParams.butlerPhone || decodedParams.butlerId) {this.processButlerInfo(decodedParams);}await this.processScannedAddressParams(decodedParams);}// 初始化地址数据await this.loadCurrentCommunityInfo();// 监听TabBar状态更新事件(保持原有逻辑)uni.$on('updateTabBarIndex', (index) => {// TabBar状态更新});} catch (error) {console.error('onLoad错误:', error);uni.showToast({title: '页面加载失败',icon: 'none'});}
}
6. 修改loadAddressData方法
在现有的loadAddressData方法中添加管家角色处理:
// 修改现有的loadAddressData方法
async loadAddressData() {try {console.log('🚀 开始加载四级地址数据');let communityName;// 🆕 如果是管家角色,优先使用管家的小区信息if (this.currentUserRole === 'manager' && this.managerCommunityInfo) {communityName = this.managerCommunityInfo.name;console.log('👨💼 [管家角色] 使用管家小区名称:', communityName);} else {// 其他角色使用原有逻辑const parkInfo = uni.getStorageSync('parkInfo');communityName = parkInfo?.name || this.currentCommunityName || '四季上东';console.log('👤 [其他角色] 使用原有逻辑获取小区名称:', communityName);}// URL编码处理(保持原有逻辑)try {if (communityName && typeof communityName === 'string' && communityName.includes('%')) {communityName = decodeURIComponent(communityName);console.log('📍 检测到编码的小区名称,已解码');}} catch (e) {console.error('解码小区名称失败:', e);}console.log('📍 最终使用的小区名称:', communityName);// 显示加载提示uni.showLoading({title: '加载地址数据...',mask: true});// 调用API加载地址数据(保持原有逻辑)const response = await uni.request({url: `https://csharphrb.picp.vip/parking/community/getAllCommunity?community=${encodeURIComponent(communityName)}`,method: 'GET',header: {'content-type': 'application/json'},timeout: 10000});// 后续的数据处理逻辑保持不变...console.log('📍 地址数据API响应:', response);if (response.statusCode !== 200) {throw new Error(`请求失败,状态码: ${response.statusCode}`);}if (!response.data || response.data.code !== '0') {throw new Error(response.data?.msg || '获取地址数据失败');}if (!Array.isArray(response.data.data)) {throw new Error('返回数据格式错误');}if (response.data.data.length === 0) {throw new Error(`未找到小区"${communityName}"的地址数据`);}// 检查数据结构const hasValidData = response.data.data.some(item =>item.building && item.units && item.floor && item.roomnumber);if (!hasValidData) {throw new Error('地址数据结构不完整');}// 处理地址数据this.processAddressData(response.data.data);console.log('✅ 地址数据加载成功');} catch (error) {console.error('❌ 加载地址数据失败:', error);uni.showToast({title: error.message || '加载地址数据失败',icon: 'none',duration: 3000});// 设置空的地址数据this.addressRange = [[], [], [], []];} finally {uni.hideLoading();}
}