import Toast from 'tdesign-miniprogram/toast/index'; import { fetchDeliveryAddress, fetchDeliveryAddressList, createAddress, updateAddress } from '../../../../services/address/fetchAddress'; import { areaData } from '../../../../config/index'; import { resolveAddress, rejectAddress } from '../../../../services/address/list'; // 添加日志工具 const logger = { info: (module, message, data = {}) => { console.log(`[${new Date().toISOString()}] [INFO] [${module}] ${message}`, data); }, debug: (module, message, data = {}) => { console.log(`[${new Date().toISOString()}] [DEBUG] [${module}] ${message}`, data); }, error: (module, message, data = {}) => { console.error(`[${new Date().toISOString()}] [ERROR] [${module}] ${message}`, data); }, warn: (module, message, data = {}) => { console.warn(`[${new Date().toISOString()}] [WARN] [${module}] ${message}`, data); } }; const innerPhoneReg = '^1(?:3\\d|4[4-9]|5[0-35-9]|6[67]|7[0-8]|8\\d|9\\d)\\d{8}$'; const innerNameReg = '^[a-zA-Z\\d\\u4e00-\\u9fa5]+$'; const labelsOptions = [ { id: 0, name: '家' }, { id: 1, name: '公司' }, ]; Page({ options: { multipleSlots: true, }, externalClasses: ['theme-wrapper-class'], data: { locationState: { labelIndex: null, addressId: '', addressTag: '', cityCode: '', cityName: '', countryCode: '', countryName: '', detailAddress: '', districtCode: '', districtName: '', isDefault: false, name: '', phone: '', provinceCode: '', provinceName: '', isEdit: false, isOrderDetail: false, isOrderSure: false, }, areaData: areaData, labels: labelsOptions, areaPickerVisible: false, submitActive: false, visible: false, labelValue: '', columns: 3, }, privateData: { verifyTips: '', }, onLoad(options) { logger.info('ADDRESS_EDIT_PAGE', '地址编辑页面加载', { options }); const { id } = options; this.init(id); }, onUnload() { logger.info('ADDRESS_EDIT_PAGE', '地址编辑页面卸载', { hasSaved: this.hasSava }); if (!this.hasSava) { logger.debug('ADDRESS_EDIT_PAGE', '页面卸载时未保存,取消地址编辑'); rejectAddress(); } }, hasSava: false, isWeixinImport: false, // 标记是否为微信地址导入 init(id) { logger.info('ADDRESS_EDIT_PAGE', '初始化地址编辑页面', { addressId: id }); if (id) { logger.debug('ADDRESS_EDIT_PAGE', '编辑模式,获取地址详情'); this.getAddressDetail(Number(id)); } else { logger.debug('ADDRESS_EDIT_PAGE', '新建模式,检查用户是否有现有地址'); this.checkUserAddressesAndSetDefault(); } }, // 检查用户地址数量,如果没有地址则自动开启默认地址开关 checkUserAddressesAndSetDefault() { logger.info('ADDRESS_EDIT_PAGE', '开始检查用户现有地址数量'); fetchDeliveryAddressList().then((addressList) => { const addressCount = addressList ? addressList.length : 0; logger.info('ADDRESS_EDIT_PAGE', '用户地址数量检查完成', { addressCount, willSetDefault: addressCount === 0 }); if (addressCount === 0) { // 用户没有地址,自动开启默认地址开关 logger.info('ADDRESS_EDIT_PAGE', '用户没有现有地址,自动开启默认地址开关'); this.setData({ 'locationState.isDefault': true }); Toast({ context: this, selector: '#t-toast', message: '已自动设置为默认地址', theme: 'success', duration: 2000, }); } else { logger.debug('ADDRESS_EDIT_PAGE', '用户已有地址,保持默认地址开关为关闭状态'); } }).catch((err) => { logger.error('ADDRESS_EDIT_PAGE', '检查用户地址数量失败', { error: err.message || err }); // 检查失败时,为了安全起见,不自动开启默认地址开关 logger.warn('ADDRESS_EDIT_PAGE', '由于检查失败,不自动开启默认地址开关'); }); }, getAddressDetail(id) { logger.info('ADDRESS_EDIT_PAGE', '开始获取地址详情', { addressId: id }); // 获取地址列表,然后找到对应的地址 fetchDeliveryAddressList().then((addressList) => { logger.debug('ADDRESS_EDIT_PAGE', '获取地址列表成功,查找目标地址', { totalCount: addressList.length, targetId: id }); const address = addressList.find(addr => addr.id == id); if (address) { logger.info('ADDRESS_EDIT_PAGE', '找到目标地址,设置编辑数据', { addressId: address.id, name: address.name, phone: address.phone, isDefault: address.isDefault }); const detail = { addressId: address.id, name: address.name, phone: address.phone, provinceName: address.province_name, provinceCode: address.province_code, cityName: address.city_name, cityCode: address.city_code, districtName: address.district_name, districtCode: address.district_code, detailAddress: address.detail_address, isDefault: Boolean(address.is_default), addressTag: address.address_tag || '', isEdit: true }; this.setData({ locationState: detail }, () => { const { isLegal, tips } = this.onVerifyInputLegal(); this.setData({ submitActive: isLegal, }); this.privateData.verifyTips = tips; logger.debug('ADDRESS_EDIT_PAGE', '地址数据设置完成', { isLegal, tips: tips || '无验证提示' }); }); } else { logger.warn('ADDRESS_EDIT_PAGE', '未找到目标地址', { addressId: id }); Toast({ context: this, selector: '#t-toast', message: '地址不存在', icon: '', duration: 1000, }); } }).catch((err) => { logger.error('ADDRESS_EDIT_PAGE', '获取地址详情失败', { addressId: id, error: err.message || err }); console.error('获取地址详情失败:', err); Toast({ context: this, selector: '#t-toast', message: '获取地址详情失败', icon: '', duration: 1000, }); }); }, onInputValue(e) { const { item } = e.currentTarget.dataset; logger.debug('ADDRESS_EDIT_PAGE', '用户输入值变化', { field: item, eventType: e.type }); if (item === 'address') { const { selectedOptions = [] } = e.detail; logger.info('ADDRESS_EDIT_PAGE', '用户选择地区', { selectedCount: selectedOptions.length, province: selectedOptions[0]?.label, city: selectedOptions[1]?.label, district: selectedOptions[2]?.label }); this.setData( { 'locationState.provinceCode': selectedOptions.length > 0 ? selectedOptions[0].value : '', 'locationState.provinceName': selectedOptions.length > 0 ? selectedOptions[0].label : '', 'locationState.cityName': selectedOptions.length > 1 ? selectedOptions[1].label : '', 'locationState.cityCode': selectedOptions.length > 1 ? selectedOptions[1].value : '', 'locationState.districtCode': selectedOptions.length > 2 ? selectedOptions[2].value : '', 'locationState.districtName': selectedOptions.length > 2 ? selectedOptions[2].label : '', areaPickerVisible: false, }, () => { const { isLegal, tips } = this.onVerifyInputLegal(); this.setData({ submitActive: isLegal, }); this.privateData.verifyTips = tips; logger.debug('ADDRESS_EDIT_PAGE', '地区选择后验证结果', { isLegal, tips }); }, ); } else { const { value = '' } = e.detail; logger.debug('ADDRESS_EDIT_PAGE', '用户输入字段值', { field: item, valueLength: value.length, value: item === 'phone' ? value.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') : value.substring(0, 20) }); this.setData( { [`locationState.${item}`]: value, }, () => { const { isLegal, tips } = this.onVerifyInputLegal(); this.setData({ submitActive: isLegal, }); this.privateData.verifyTips = tips; logger.debug('ADDRESS_EDIT_PAGE', '字段输入后验证结果', { field: item, isLegal, tips }); }, ); } }, onPickArea() { this.setData({ areaPickerVisible: true }); }, onPickLabels(e) { const { item } = e.currentTarget.dataset; const { locationState: { labelIndex = undefined }, labels = [], } = this.data; let payload = { labelIndex: item, addressTag: labels[item].name, }; if (item === labelIndex) { payload = { labelIndex: null, addressTag: '' }; } this.setData({ 'locationState.labelIndex': payload.labelIndex, }); this.triggerEvent('triggerUpdateValue', payload); }, addLabels() { this.setData({ visible: true, }); }, confirmHandle() { const { labels, labelValue } = this.data; this.setData({ visible: false, labels: [...labels, { id: labels[labels.length - 1].id + 1, name: labelValue }], labelValue: '', }); }, cancelHandle() { this.setData({ visible: false, labelValue: '', }); }, onCheckDefaultAddress({ detail }) { const { value } = detail; this.setData({ 'locationState.isDefault': value, }); }, onVerifyInputLegal() { const { name, phone, detailAddress, districtName } = this.data.locationState; const prefixPhoneReg = String(this.properties.phoneReg || innerPhoneReg); const prefixNameReg = String(this.properties.nameReg || innerNameReg); const nameRegExp = new RegExp(prefixNameReg); const phoneRegExp = new RegExp(prefixPhoneReg); if (!name || !name.trim()) { return { isLegal: false, tips: '请填写收货人', }; } if (!nameRegExp.test(name)) { return { isLegal: false, tips: '收货人仅支持输入中文、英文(区分大小写)、数字', }; } if (!phone || !phone.trim()) { return { isLegal: false, tips: '请填写手机号', }; } // 如果是微信导入,跳过手机号格式验证 if (this.isWeixinImport) { console.log('[地址编辑-验证] 微信导入模式,跳过手机号格式验证:', phone); } else if (!phoneRegExp.test(phone)) { return { isLegal: false, tips: '请填写正确的手机号', }; } if (!districtName || !districtName.trim()) { return { isLegal: false, tips: '请选择省市区信息', }; } if (!detailAddress || !detailAddress.trim()) { return { isLegal: false, tips: '请完善详细地址', }; } if (detailAddress && detailAddress.trim().length > 50) { return { isLegal: false, tips: '详细地址不能超过50个字符', }; } return { isLegal: true, tips: '添加成功', }; }, builtInSearch({ code, name }) { return new Promise((resolve, reject) => { wx.getSetting({ success: (res) => { if (res.authSetting[code] === false) { wx.showModal({ title: `获取${name}失败`, content: `获取${name}失败,请在【右上角】-小程序【设置】项中,将【${name}】开启。`, confirmText: '去设置', confirmColor: '#FA550F', cancelColor: '取消', success(res) { if (res.confirm) { wx.openSetting({ success(settinRes) { if (settinRes.authSetting[code] === true) { resolve(); } else { console.warn('用户未打开权限', name, code); reject(); } }, }); } else { reject(); } }, fail() { reject(); }, }); } else { resolve(); } }, fail() { reject(); }, }); }); }, onSearchAddress() { this.builtInSearch({ code: 'scope.userLocation', name: '地址位置' }).then(() => { wx.chooseLocation({ success: (res) => { if (res.name) { this.triggerEvent('addressParse', { address: res.address, name: res.name, latitude: res.latitude, longitude: res.longitude, }); } else { Toast({ context: this, selector: '#t-toast', message: '地点为空,请重新选择', icon: '', duration: 1000, }); } }, fail: function (res) { console.warn(`wx.chooseLocation fail: ${JSON.stringify(res)}`); if (res.errMsg !== 'chooseLocation:fail cancel') { Toast({ context: this, selector: '#t-toast', message: '地点错误,请重新选择', icon: '', duration: 1000, }); } }, }); }); }, formSubmit() { logger.info('ADDRESS_EDIT_PAGE', '用户提交地址表单', { hasSubmitActive: this.data.submitActive, addressId: this.data.locationState.addressId, isEdit: this.data.locationState.isEdit }); const { submitActive } = this.data; if (!submitActive) { logger.warn('ADDRESS_EDIT_PAGE', '表单验证失败,无法提交', { verifyTips: this.privateData.verifyTips }); Toast({ context: this, selector: '#t-toast', message: this.privateData.verifyTips, icon: '', duration: 1000, }); return; } const { locationState } = this.data; // 构造API请求数据 const addressData = { name: locationState.name, phone: locationState.phone, province: locationState.provinceName, city: locationState.cityName, district: locationState.districtName, detail: locationState.detailAddress, is_default: locationState.isDefault ? 1 : 0, }; logger.info('ADDRESS_EDIT_PAGE', '准备提交地址数据', { isEdit: locationState.isEdit, addressId: locationState.addressId, locationState: { name: locationState.name, phone: locationState.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'), provinceName: locationState.provinceName, cityName: locationState.cityName, districtName: locationState.districtName, detailAddress: locationState.detailAddress, isDefault: locationState.isDefault }, addressData: { ...addressData, phone: addressData.phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2') } }); const isEdit = locationState.addressId && locationState.isEdit; logger.info('ADDRESS_EDIT_PAGE', `准备${isEdit ? '更新' : '创建'}地址`, { isEdit, addressId: locationState.addressId, name: addressData.name, phone: addressData.phone, province: addressData.provinceName, city: addressData.cityName, district: addressData.districtName, isDefault: addressData.isDefault, addressTag: addressData.addressTag }); const apiCall = isEdit ? updateAddress(locationState.addressId, addressData) : createAddress(addressData); apiCall.then((result) => { this.hasSava = true; logger.info('ADDRESS_EDIT_PAGE', `地址${isEdit ? '更新' : '创建'}成功`, { isEdit, addressId: result.id || locationState.addressId, resultData: result, resultType: typeof result, resultKeys: result ? Object.keys(result) : 'null' }); Toast({ context: this, selector: '#t-toast', message: isEdit ? '地址更新成功' : '地址创建成功', theme: 'success', duration: 1000, }); // 返回给地址列表页面的数据 - 优先使用服务器返回的数据 const addressResult = { id: result.id || locationState.addressId, addressId: result.id || locationState.addressId, phone: result.phone || locationState.phone, name: result.name || locationState.name, provinceName: result.provinceName || locationState.provinceName, provinceCode: locationState.provinceCode, // 服务器不返回code,使用本地数据 cityName: result.cityName || locationState.cityName, cityCode: locationState.cityCode, // 服务器不返回code,使用本地数据 districtName: result.districtName || locationState.districtName, districtCode: locationState.districtCode, // 服务器不返回code,使用本地数据 detailAddress: result.detailAddress || locationState.detailAddress, isDefault: result.isDefault !== undefined ? (result.isDefault ? 1 : 0) : (locationState.isDefault ? 1 : 0), addressTag: locationState.addressTag || '', isEdit: isEdit }; logger.debug('ADDRESS_EDIT_PAGE', '准备返回地址列表页面', { addressResult }); resolveAddress(addressResult); wx.navigateBack({ delta: 1 }); }).catch((err) => { logger.error('ADDRESS_EDIT_PAGE', `地址${isEdit ? '更新' : '创建'}失败`, { isEdit, addressId: locationState.addressId, error: err.message || err, addressData }); console.error('保存地址失败:', err); Toast({ context: this, selector: '#t-toast', message: isEdit ? '地址更新失败' : '地址创建失败', icon: '', duration: 1000, }); }); }, getWeixinAddress(e) { console.log('[地址编辑-微信导入] 开始处理微信地址数据'); console.log('[地址编辑-微信导入] 接收到的事件对象:', e); console.log('[地址编辑-微信导入] 事件详情数据:', e.detail); const { locationState } = this.data; console.log('[地址编辑-微信导入] 当前locationState:', locationState); const weixinAddress = e.detail; console.log('[地址编辑-微信导入] 微信地址数据:', weixinAddress); const mergedState = { ...locationState, ...weixinAddress }; console.log('[地址编辑-微信导入] 合并后的地址状态:', mergedState); // 设置微信导入标记 this.isWeixinImport = true; console.log('[地址编辑-微信导入] 设置微信导入标记,跳过手机号验证'); this.setData( { locationState: mergedState, }, () => { console.log('[地址编辑-微信导入] setData完成,开始验证输入合法性'); const { isLegal, tips } = this.onVerifyInputLegal(); console.log('[地址编辑-微信导入] 验证结果:', { isLegal, tips }); this.setData({ submitActive: isLegal, }); this.privateData.verifyTips = tips; console.log('[地址编辑-微信导入] 提交按钮状态更新为:', isLegal); console.log('[地址编辑-微信导入] 验证提示信息:', tips); console.log('[地址编辑-微信导入] 微信地址数据处理完成'); // 重置微信导入标记 this.isWeixinImport = false; }, ); }, });