You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
723 lines
22 KiB
723 lines
22 KiB
<template>
|
|
<view class="add-address-page">
|
|
<view class="form-card">
|
|
<view class="form-row">
|
|
<text class="form-label">收货人</text>
|
|
<input class="form-input" type="text" maxlength="20" v-model="addressForm.receiverName"
|
|
@input="onReceiverNameInput" placeholder="姓名" placeholder-class="form-placeholder" />
|
|
</view>
|
|
<view class="form-row">
|
|
<text class="form-label">电话</text>
|
|
<input class="form-input" type="number" maxlength="11" v-model="addressForm.receiverPhone"
|
|
@input="onReceiverPhoneInput" placeholder="手机号" placeholder-class="form-placeholder" />
|
|
</view>
|
|
<view v-if="!isSocialArea" class="form-row" @tap="openAreaPopup">
|
|
<text class="form-label">楼座区域</text>
|
|
<text class="form-value" :class="{'form-placeholder-text': !areaTitleInput}">
|
|
{{areaTitleInput || (areaListLoading ? '加载中...' : '选择收货地址')}}
|
|
</text>
|
|
<uni-icons type="right" size="18" color="#999"></uni-icons>
|
|
</view>
|
|
<view v-else class="form-row" @tap="openLocationPicker">
|
|
<text class="form-label">收货地址</text>
|
|
<text class="form-value" :class="{'form-placeholder-text': !addressForm.areaName}">
|
|
{{addressForm.areaName || '搜索/定位选择地址'}}
|
|
</text>
|
|
<uni-icons type="right" size="18" color="#999"></uni-icons>
|
|
</view>
|
|
<view v-if="!isSocialArea" class="form-row">
|
|
<text class="form-label">楼层</text>
|
|
<input class="form-input" type="number" v-model="addressForm.floor" @input="onFloorInput"
|
|
placeholder="所在楼层,仅限整数" placeholder-class="form-placeholder" />
|
|
</view>
|
|
<view class="form-row">
|
|
<text class="form-label">{{isSocialArea ? '门牌号' : '门牌号'}}</text>
|
|
<input class="form-input" type="text" maxlength="30" v-model="addressForm.roomNum"
|
|
@input="onRoomNumInput" :placeholder="isSocialArea ? '例:3号楼2单元301室' : '例:5号楼203室'" placeholder-class="form-placeholder" />
|
|
</view>
|
|
<view class="form-row form-row--switch">
|
|
<text class="form-label">设为默认地址</text>
|
|
<switch :checked="addressForm.isDefault === 1" @change="e => addressForm.isDefault = e.detail.value ? 1 : 0"
|
|
color="#a6ffea" />
|
|
</view>
|
|
</view>
|
|
<view class="submit-btn" :class="{'submit-btn--disabled': addressSubmitting}" @tap="submitAddress">
|
|
{{addressSubmitting ? '提交中...' : '确定'}}
|
|
</view>
|
|
<uni-popup ref="areaPopup" type="bottom" background-color="#fff">
|
|
<view class="area-popup" @tap.stop>
|
|
<view class="area-popup-title">
|
|
<text>选择楼座区域</text>
|
|
<uni-icons type="closeempty" size="24" color="#333" @tap="closeAreaPopup"></uni-icons>
|
|
</view>
|
|
<view class="area-search-box">
|
|
<input class="area-search-input" type="text" v-model="areaSearchInput" placeholder="请输入楼座名称搜索"
|
|
placeholder-class="form-placeholder" confirm-type="search" :cursor-spacing="160" />
|
|
</view>
|
|
<scroll-view scroll-y class="area-result-list">
|
|
<view v-if="filteredAreaList.length === 0" class="area-result-empty">
|
|
未找到匹配的楼座
|
|
</view>
|
|
<view v-for="item in filteredAreaList" :key="item.id" class="area-result-item" @tap="selectArea(item)">
|
|
{{item.title}}
|
|
</view>
|
|
</scroll-view>
|
|
</view>
|
|
</uni-popup>
|
|
<view v-if="showPrivacyModal" class="privacy-mask">
|
|
<view class="privacy-dialog">
|
|
<view class="privacy-title">隐私授权提示</view>
|
|
<view class="privacy-content">
|
|
选择收货地址需要使用定位能力。请先阅读并同意
|
|
<text class="privacy-link" @tap.stop="openPrivacyContract">{{privacyContractName}}</text>
|
|
后继续。
|
|
</view>
|
|
<view class="privacy-actions">
|
|
<button class="privacy-btn privacy-btn--cancel" @tap="rejectPrivacyAuthorization">不同意</button>
|
|
<button id="agree-privacy-btn" class="privacy-btn privacy-btn--agree" open-type="agreePrivacyAuthorization"
|
|
@agreeprivacyauthorization="handleAgreePrivacyAuthorization">同意并继续</button>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</view>
|
|
</template>
|
|
|
|
<script>
|
|
export default {
|
|
data() {
|
|
return {
|
|
areaList: [],
|
|
areaTitleList: [],
|
|
areaListLoading: false,
|
|
areaTitleInput: '',
|
|
areaSearchInput: '',
|
|
addressSubmitting: false,
|
|
showPrivacyModal: false,
|
|
privacyContractName: '《用户隐私保护指引》',
|
|
pendingPrivacyResolve: null,
|
|
pendingPrivacyReject: null,
|
|
addressForm: {
|
|
id: '',
|
|
regionId: '',
|
|
areaId: '',
|
|
areaName: '',
|
|
addressLng: '',
|
|
addressLat: '',
|
|
floor: '',
|
|
roomNum: '',
|
|
receiverName: '',
|
|
receiverPhone: '',
|
|
isDefault: 0
|
|
}
|
|
}
|
|
},
|
|
computed: {
|
|
isSocialArea() {
|
|
const area = this.getCurrentArea();
|
|
return area && Number(area.areaKind) === 2;
|
|
},
|
|
filteredAreaList() {
|
|
const keyword = (this.areaSearchInput || '').toString();
|
|
if (!keyword) return this.areaList;
|
|
return this.areaList.filter(item => (item.title || '').toString().indexOf(keyword) > -1);
|
|
}
|
|
},
|
|
onLoad(options) {
|
|
const id = options && options.id ? options.id : '';
|
|
uni.setNavigationBarTitle({
|
|
title: id ? '编辑地址' : '新增收货地址'
|
|
});
|
|
this.addressForm.regionId = this.getCurrentRegionId();
|
|
if (id) {
|
|
this.addressForm.id = id;
|
|
this.initEditAddress(id);
|
|
}
|
|
if (!this.isSocialArea) {
|
|
this.getAreaList().then(() => {
|
|
this.syncAreaTitle();
|
|
});
|
|
}
|
|
},
|
|
methods: {
|
|
getCurrentArea() {
|
|
try {
|
|
const area = uni.getStorageSync('area');
|
|
if (!area) return null;
|
|
return typeof area === 'object' ? area : JSON.parse(area);
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
},
|
|
getCurrentRegionId() {
|
|
try {
|
|
const areaInfo = this.getCurrentArea();
|
|
return areaInfo.id ? String(areaInfo.id) : '';
|
|
} catch (e) {
|
|
return '';
|
|
}
|
|
},
|
|
initEditAddress(id) {
|
|
const cached = uni.getStorageSync('editingAddress');
|
|
if (cached && String(cached.id) === String(id)) {
|
|
this.applyAddress(cached);
|
|
return;
|
|
}
|
|
this.tui.request("/app/userAddress/get", "GET", {
|
|
id: id
|
|
}, false, true).then((res) => {
|
|
if (res.code == 200 && res.result) {
|
|
this.applyAddress(res.result);
|
|
}
|
|
}).catch(() => {});
|
|
},
|
|
applyAddress(item) {
|
|
this.addressForm = {
|
|
id: item.id || '',
|
|
regionId: item.regionId || this.getCurrentRegionId(),
|
|
areaId: item.areaId || '',
|
|
areaName: item.areaName || '',
|
|
addressLng: item.addressLng || '',
|
|
addressLat: item.addressLat || '',
|
|
floor: item.floor || '',
|
|
roomNum: item.roomNum || '',
|
|
receiverName: item.receiverName || '',
|
|
receiverPhone: item.receiverPhone || '',
|
|
isDefault: item.isDefault || 0
|
|
};
|
|
this.areaTitleInput = item.areaName || '';
|
|
if (!this.isSocialArea) this.syncAreaTitle();
|
|
},
|
|
getAreaList() {
|
|
if (this.areaListLoading) return Promise.resolve(this.areaList);
|
|
const regionId = this.getCurrentRegionId();
|
|
if (!regionId) return Promise.resolve([]);
|
|
this.areaListLoading = true;
|
|
return this.tui.request("/app/shopArea/getByParentId/" + regionId, "GET", {}, false, true).then((res) => {
|
|
if (res.code == 200 && res.result) {
|
|
this.areaList = res.result;
|
|
this.areaTitleList = res.result.map(item => item.title);
|
|
}
|
|
return this.areaList;
|
|
}).catch(() => []).finally(() => {
|
|
this.areaListLoading = false;
|
|
});
|
|
},
|
|
syncAreaTitle() {
|
|
if (!this.addressForm.areaId || !this.areaList.length) return;
|
|
const match = this.areaList.find(item => String(item.id) === String(this.addressForm.areaId));
|
|
if (match) this.areaTitleInput = match.title;
|
|
},
|
|
openAreaPopup() {
|
|
if (this.isSocialArea) return;
|
|
this.areaSearchInput = '';
|
|
this.getAreaList();
|
|
this.$refs.areaPopup.open();
|
|
},
|
|
closeAreaPopup() {
|
|
this.$refs.areaPopup.close();
|
|
},
|
|
selectArea(item) {
|
|
if (!item) return;
|
|
this.addressForm.areaId = item.id;
|
|
this.addressForm.areaName = item.title;
|
|
this.areaTitleInput = item.title;
|
|
this.closeAreaPopup();
|
|
},
|
|
openLocationPicker() {
|
|
const openPicker = (option) => {
|
|
this.ensurePrivacyAuthorization().then(() => {
|
|
console.log('chooseLocation 入参:', option || {});
|
|
uni.chooseLocation({
|
|
...(option || {}),
|
|
success: (res) => {
|
|
console.log('chooseLocation 成功:', res);
|
|
const name = (res.name || '').trim();
|
|
const address = (res.address || '').trim();
|
|
if (!name && !address) {
|
|
this.tui.toast('请选择有效地址');
|
|
return;
|
|
}
|
|
this.applySelectedLocation({
|
|
name: address && name && address.indexOf(name) === -1 ? address + name : (name || address),
|
|
latitude: res.latitude,
|
|
longitude: res.longitude
|
|
});
|
|
},
|
|
fail: (err) => {
|
|
console.log('chooseLocation 失败:', err);
|
|
const errMsg = err && err.errMsg ? String(err.errMsg) : '';
|
|
if (errMsg.indexOf('cancel') > -1) {
|
|
return;
|
|
}
|
|
this.showLocationFailTip(err, '打开位置选择失败,可重新进入页面后再试');
|
|
}
|
|
});
|
|
}).catch(() => {});
|
|
};
|
|
const lat = this.toLocationNumber(this.addressForm.addressLat);
|
|
const lng = this.toLocationNumber(this.addressForm.addressLng);
|
|
if (this.isValidLocation(lat, lng)) {
|
|
openPicker({
|
|
latitude: lat,
|
|
longitude: lng
|
|
});
|
|
return;
|
|
}
|
|
this.ensurePrivacyAuthorization().then(() => this.getPickerCurrentLocation()).then((location) => {
|
|
openPicker(location);
|
|
}).catch(() => {});
|
|
},
|
|
applySelectedLocation(location) {
|
|
if (!location) return;
|
|
this.validateSocialAddressLocation(location.latitude, location.longitude).then(() => {
|
|
this.addressForm.areaId = '';
|
|
this.addressForm.areaName = location.name || '当前位置';
|
|
this.addressForm.addressLng = location.longitude;
|
|
this.addressForm.addressLat = location.latitude;
|
|
this.areaTitleInput = this.addressForm.areaName;
|
|
}).catch(() => {});
|
|
},
|
|
toLocationNumber(value) {
|
|
if (value === '' || value === null || value === undefined) return null;
|
|
const numberValue = Number(value);
|
|
return Number.isFinite(numberValue) ? numberValue : null;
|
|
},
|
|
isValidLocation(latitude, longitude) {
|
|
const lat = this.toLocationNumber(latitude);
|
|
const lng = this.toLocationNumber(longitude);
|
|
return lat !== null && lng !== null &&
|
|
lat >= -90 && lat <= 90 &&
|
|
lng >= -180 && lng <= 180 &&
|
|
!(lat === 0 && lng === 0);
|
|
},
|
|
ensurePrivacyAuthorization() {
|
|
return new Promise((resolve, reject) => {
|
|
// #ifdef MP-WEIXIN
|
|
if (typeof wx !== 'undefined' && wx.getPrivacySetting) {
|
|
wx.getPrivacySetting({
|
|
success: (res) => {
|
|
console.log('getPrivacySetting:', res);
|
|
if (!res || !res.needAuthorization) {
|
|
resolve();
|
|
return;
|
|
}
|
|
this.privacyContractName = res.privacyContractName || '《用户隐私保护指引》';
|
|
this.pendingPrivacyResolve = resolve;
|
|
this.pendingPrivacyReject = reject;
|
|
this.showPrivacyModal = true;
|
|
},
|
|
fail: (err) => {
|
|
console.log('getPrivacySetting 失败:', err);
|
|
resolve();
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
// #endif
|
|
resolve();
|
|
});
|
|
},
|
|
openPrivacyContract() {
|
|
// #ifdef MP-WEIXIN
|
|
if (typeof wx !== 'undefined' && wx.openPrivacyContract) {
|
|
wx.openPrivacyContract({
|
|
fail: () => {
|
|
this.tui.toast('打开隐私协议失败');
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
// #endif
|
|
this.tui.toast('当前微信版本暂不支持查看');
|
|
},
|
|
handleAgreePrivacyAuthorization() {
|
|
this.showPrivacyModal = false;
|
|
const resolve = this.pendingPrivacyResolve;
|
|
this.pendingPrivacyResolve = null;
|
|
this.pendingPrivacyReject = null;
|
|
if (typeof resolve === 'function') resolve();
|
|
},
|
|
rejectPrivacyAuthorization() {
|
|
this.showPrivacyModal = false;
|
|
const reject = this.pendingPrivacyReject;
|
|
this.pendingPrivacyResolve = null;
|
|
this.pendingPrivacyReject = null;
|
|
this.tui.toast('请先同意隐私协议后再定位');
|
|
if (typeof reject === 'function') reject();
|
|
},
|
|
getPickerCurrentLocation() {
|
|
return new Promise((resolve, reject) => {
|
|
uni.getLocation({
|
|
type: 'gcj02',
|
|
isHighAccuracy: true,
|
|
highAccuracyExpireTime: 3000,
|
|
success: (res) => {
|
|
console.log('getLocation 成功:', res);
|
|
if (this.isValidLocation(res.latitude, res.longitude)) {
|
|
resolve({
|
|
latitude: res.latitude,
|
|
longitude: res.longitude
|
|
});
|
|
} else {
|
|
console.log('getLocation 返回无效坐标:', res);
|
|
resolve({});
|
|
}
|
|
},
|
|
fail: (err) => {
|
|
console.log('getLocation 失败:', err);
|
|
const errMsg = (err && err.errMsg) || '';
|
|
const denied = errMsg.indexOf('auth deny') > -1 ||
|
|
errMsg.indexOf('authorize') > -1 ||
|
|
errMsg.indexOf('denied') > -1 ||
|
|
errMsg.indexOf('permission') > -1;
|
|
if (!denied) {
|
|
this.showLocationFailTip(err, '定位失败,可手动搜索地址');
|
|
resolve({});
|
|
return;
|
|
}
|
|
uni.showModal({
|
|
title: '需要定位权限',
|
|
content: '请选择允许定位后再选择收货地址',
|
|
confirmText: '去设置',
|
|
success: (modalRes) => {
|
|
if (modalRes.confirm) {
|
|
uni.openSetting({
|
|
complete: () => reject(err)
|
|
});
|
|
} else {
|
|
reject(err);
|
|
}
|
|
},
|
|
fail: () => reject(err)
|
|
});
|
|
}
|
|
});
|
|
});
|
|
},
|
|
showLocationFailTip(err, fallbackText) {
|
|
const errMsg = err && err.errMsg ? String(err.errMsg) : '';
|
|
if (errMsg) {
|
|
console.log('location fail:', errMsg);
|
|
}
|
|
if (errMsg.indexOf('privacy') > -1) {
|
|
this.tui.toast('请先同意隐私协议后再定位');
|
|
return;
|
|
}
|
|
this.tui.toast(fallbackText || '定位失败,请重试');
|
|
},
|
|
validateSocialAddressLocation(lat, lng) {
|
|
return new Promise((resolve, reject) => {
|
|
const currentRegionId = this.getCurrentRegionId();
|
|
const latitude = this.toLocationNumber(lat);
|
|
const longitude = this.toLocationNumber(lng);
|
|
if (!currentRegionId) {
|
|
this.tui.toast('请先选择区域');
|
|
reject();
|
|
return;
|
|
}
|
|
if (!this.isValidLocation(latitude, longitude)) {
|
|
this.tui.toast('地址坐标不合法,请重新选择');
|
|
reject();
|
|
return;
|
|
}
|
|
this.tui.request('/app/shopArea/matchByLocation', 'GET', {
|
|
lat: latitude,
|
|
lng: longitude
|
|
}, false, true).then((res) => {
|
|
const matched = res && res.code == 200 && res.result && res.result.id;
|
|
if (matched && String(res.result.id) === String(currentRegionId)) {
|
|
resolve();
|
|
} else {
|
|
this.tui.toast('该地址不在当前区域配送范围内', 1500);
|
|
reject();
|
|
}
|
|
}).catch(() => {
|
|
this.tui.toast('地址范围校验失败,请稍后重试');
|
|
reject();
|
|
});
|
|
});
|
|
},
|
|
onFloorInput(e) {
|
|
const value = (e.detail.value || '').toString();
|
|
const hasMinus = value.charAt(0) === '-';
|
|
let nextValue = value.replace(/[^\d-]/g, '').replace(/-/g, '');
|
|
if (hasMinus) nextValue = '-' + nextValue;
|
|
this.addressForm.floor = nextValue;
|
|
return nextValue;
|
|
},
|
|
onRoomNumInput(e) {
|
|
const nextValue = (e.detail.value || '').toString().slice(0, 30);
|
|
this.addressForm.roomNum = nextValue;
|
|
return nextValue;
|
|
},
|
|
onReceiverNameInput(e) {
|
|
const nextValue = (e.detail.value || '').toString().slice(0, 20);
|
|
this.addressForm.receiverName = nextValue;
|
|
return nextValue;
|
|
},
|
|
onReceiverPhoneInput(e) {
|
|
const nextValue = (e.detail.value || '').toString().replace(/\D/g, '').slice(0, 11);
|
|
this.addressForm.receiverPhone = nextValue;
|
|
return nextValue;
|
|
},
|
|
submitAddress() {
|
|
if (this.addressSubmitting) return;
|
|
const isSocial = this.isSocialArea;
|
|
if (!isSocial && !this.addressForm.areaId) return this.tui.toast('请选择楼座区域');
|
|
if (isSocial && !this.addressForm.areaName) return this.tui.toast('请选择收货地址');
|
|
if (isSocial && (!this.addressForm.addressLng || !this.addressForm.addressLat)) return this.tui.toast('请选择带定位的收货地址');
|
|
this.addressForm.floor = (this.addressForm.floor || '').toString();
|
|
this.addressForm.roomNum = (this.addressForm.roomNum || '').toString().trim();
|
|
this.addressForm.receiverName = (this.addressForm.receiverName || '').toString().trim();
|
|
this.addressForm.receiverPhone = (this.addressForm.receiverPhone || '').toString().replace(/\D/g, '');
|
|
if (!isSocial && !this.addressForm.floor) return this.tui.toast('请填写所在楼层,楼层必须为整数数字');
|
|
if (!isSocial && !/^-?\d+$/.test(this.addressForm.floor)) return this.tui.toast('楼层必须为整数');
|
|
if (isSocial) {
|
|
this.addressForm.floor = '';
|
|
this.addressForm.areaId = '';
|
|
}
|
|
if (!this.addressForm.roomNum) return this.tui.toast('请填写详细地址门牌号最多30字');
|
|
if (this.addressForm.roomNum.length > 30) return this.tui.toast('详细地址最多30字');
|
|
if (!this.addressForm.receiverName) return this.tui.toast('请填写收件人最多20字');
|
|
if (this.addressForm.receiverName.length > 20) return this.tui.toast('收货人名字最多20字');
|
|
if (!this.addressForm.receiverPhone) return this.tui.toast('请输入有效的11位手机号码');
|
|
if (!/^1[3-9]\d{9}$/.test(this.addressForm.receiverPhone)) return this.tui.toast('请输入有效的11位手机号码');
|
|
this.addressForm.userId = uni.getStorageSync('id');
|
|
this.addressForm.regionId = this.getCurrentRegionId();
|
|
if (!this.addressForm.regionId) return this.tui.toast('请先选择区域');
|
|
if (isSocial) {
|
|
this.validateSocialAddressLocation(this.addressForm.addressLat, this.addressForm.addressLng)
|
|
.then(() => this.doSubmitAddress())
|
|
.catch(() => {});
|
|
return;
|
|
}
|
|
this.doSubmitAddress();
|
|
},
|
|
doSubmitAddress() {
|
|
const url = this.addressForm.id ? "/app/userAddress/edit" : "/app/userAddress/save";
|
|
this.addressSubmitting = true;
|
|
this.tui.request(url, "POST", this.addressForm, false, true).then((res) => {
|
|
if (res.code == 200) {
|
|
const pendingAddress = res.result && typeof res.result === 'object' ?
|
|
Object.assign({}, this.addressForm, res.result) :
|
|
Object.assign({}, this.addressForm);
|
|
uni.setStorageSync('pendingSelectedAddress', pendingAddress);
|
|
uni.setStorageSync('addressListNeedsRefresh', '1');
|
|
uni.removeStorageSync('editingAddress');
|
|
this.tui.toast("保存成功", 1000);
|
|
setTimeout(() => {
|
|
uni.navigateBack();
|
|
}, 500);
|
|
} else {
|
|
this.tui.toast(res.message, 1000);
|
|
}
|
|
}).catch(() => {}).finally(() => {
|
|
this.addressSubmitting = false;
|
|
});
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.add-address-page {
|
|
min-height: 100vh;
|
|
box-sizing: border-box;
|
|
background: #f5f5f5;
|
|
padding-bottom: 40rpx;
|
|
}
|
|
|
|
.form-card {
|
|
background: #fff;
|
|
}
|
|
|
|
.form-row {
|
|
min-height: 98rpx;
|
|
box-sizing: border-box;
|
|
padding: 0 30rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
border-bottom: 1rpx solid #eee;
|
|
background: #fff;
|
|
}
|
|
|
|
.form-row--switch {
|
|
justify-content: space-between;
|
|
margin-top: 30rpx;
|
|
border-bottom: 0;
|
|
}
|
|
|
|
.form-row--switch .form-label {
|
|
width: auto;
|
|
flex: 1;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.form-label {
|
|
width: 150rpx;
|
|
flex-shrink: 0;
|
|
font-size: 30rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.form-input {
|
|
flex: 1;
|
|
min-width: 0;
|
|
height: 98rpx;
|
|
line-height: 98rpx;
|
|
font-size: 30rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.form-placeholder,
|
|
.form-placeholder-text {
|
|
color: #c7c7c7;
|
|
}
|
|
|
|
.form-value {
|
|
flex: 1;
|
|
min-width: 0;
|
|
font-size: 30rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.submit-btn {
|
|
height: 88rpx;
|
|
line-height: 88rpx;
|
|
margin: 40rpx 30rpx 0;
|
|
border-radius: 8rpx;
|
|
background: linear-gradient(90deg, #e3ff96, #a6ffea);
|
|
font-size: 34rpx;
|
|
font-weight: 700;
|
|
text-align: center;
|
|
color: #111;
|
|
}
|
|
|
|
.submit-btn--disabled {
|
|
opacity: 0.65;
|
|
}
|
|
|
|
.area-popup {
|
|
height: 760rpx;
|
|
box-sizing: border-box;
|
|
padding: 30rpx;
|
|
border-radius: 28rpx 28rpx 0 0;
|
|
background: #fff;
|
|
}
|
|
|
|
.area-popup-title {
|
|
height: 60rpx;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
font-size: 34rpx;
|
|
font-weight: 700;
|
|
color: #333;
|
|
}
|
|
|
|
.area-search-box {
|
|
margin-top: 24rpx;
|
|
padding: 18rpx 22rpx;
|
|
background: #f7f8f8;
|
|
border-radius: 16rpx;
|
|
}
|
|
|
|
.area-search-input {
|
|
width: 100%;
|
|
height: 46rpx;
|
|
line-height: 46rpx;
|
|
font-size: 28rpx;
|
|
color: #333;
|
|
}
|
|
|
|
.area-result-list {
|
|
height: 560rpx;
|
|
margin-top: 20rpx;
|
|
}
|
|
|
|
.area-result-empty,
|
|
.area-result-item {
|
|
min-height: 88rpx;
|
|
line-height: 88rpx;
|
|
padding: 0 20rpx;
|
|
box-sizing: border-box;
|
|
font-size: 30rpx;
|
|
color: #333;
|
|
border-bottom: 1rpx solid #f2f2f2;
|
|
}
|
|
|
|
.area-result-empty {
|
|
color: #999;
|
|
text-align: center;
|
|
}
|
|
|
|
.privacy-mask {
|
|
position: fixed;
|
|
left: 0;
|
|
right: 0;
|
|
top: 0;
|
|
bottom: 0;
|
|
z-index: 9999;
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
padding: 0 48rpx;
|
|
background: rgba(0, 0, 0, 0.45);
|
|
}
|
|
|
|
.privacy-dialog {
|
|
width: 100%;
|
|
padding: 42rpx 34rpx 30rpx;
|
|
border-radius: 24rpx;
|
|
background: #fff;
|
|
box-sizing: border-box;
|
|
}
|
|
|
|
.privacy-title {
|
|
font-size: 34rpx;
|
|
font-weight: 700;
|
|
color: #222;
|
|
text-align: center;
|
|
}
|
|
|
|
.privacy-content {
|
|
margin-top: 28rpx;
|
|
font-size: 28rpx;
|
|
line-height: 1.7;
|
|
color: #555;
|
|
}
|
|
|
|
.privacy-link {
|
|
color: #10b981;
|
|
}
|
|
|
|
.privacy-actions {
|
|
display: flex;
|
|
gap: 20rpx;
|
|
margin-top: 36rpx;
|
|
}
|
|
|
|
.privacy-btn {
|
|
flex: 1;
|
|
height: 80rpx;
|
|
line-height: 80rpx;
|
|
margin: 0;
|
|
padding: 0;
|
|
border-radius: 40rpx;
|
|
font-size: 28rpx;
|
|
}
|
|
|
|
.privacy-btn::after {
|
|
border: 0;
|
|
}
|
|
|
|
.privacy-btn--cancel {
|
|
color: #666;
|
|
background: #f5f5f5;
|
|
}
|
|
|
|
.privacy-btn--agree {
|
|
color: #fff;
|
|
background: #10b981;
|
|
}
|
|
</style>
|