start
This commit is contained in:
195
xui/wxapp/pages/mine/comp_address/comp_address.js
Normal file
195
xui/wxapp/pages/mine/comp_address/comp_address.js
Normal file
@@ -0,0 +1,195 @@
|
||||
// pages/mine/comp_address/comp_address.js
|
||||
Component({
|
||||
properties: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
value: false
|
||||
}
|
||||
},
|
||||
|
||||
data: {
|
||||
addresses: [],
|
||||
editData: {
|
||||
_index: -1,
|
||||
label: '',
|
||||
province: '',
|
||||
city: '',
|
||||
district: '',
|
||||
address: '',
|
||||
postcode: '',
|
||||
isDefault: false
|
||||
},
|
||||
isEditing: false
|
||||
},
|
||||
|
||||
observers: {
|
||||
visible(newVal) {
|
||||
if (newVal) {
|
||||
this.initAddressData()
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
methods: {
|
||||
initAddressData() {
|
||||
const app = getApp()
|
||||
const user = app.globalData.user || {}
|
||||
const addresses = user.addresses || []
|
||||
this.setData({
|
||||
addresses: addresses.map(item => ({ ...item })),
|
||||
isEditing: false,
|
||||
editData: {
|
||||
_index: -1,
|
||||
label: '',
|
||||
province: '',
|
||||
city: '',
|
||||
district: '',
|
||||
address: '',
|
||||
postcode: '',
|
||||
isDefault: false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onClose() {
|
||||
this.triggerEvent('close')
|
||||
},
|
||||
|
||||
onSheetTap() {},
|
||||
|
||||
onAddAddress() {
|
||||
this.setData({
|
||||
isEditing: true,
|
||||
editData: {
|
||||
_index: -1,
|
||||
label: '',
|
||||
province: '',
|
||||
city: '',
|
||||
district: '',
|
||||
address: '',
|
||||
postcode: '',
|
||||
isDefault: this.data.addresses.length === 0
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onEditAddress(e) {
|
||||
const index = e.currentTarget.dataset.index
|
||||
const item = this.data.addresses[index]
|
||||
this.setData({
|
||||
isEditing: true,
|
||||
editData: {
|
||||
_index: index,
|
||||
label: item.label || '',
|
||||
province: item.province || '',
|
||||
city: item.city || '',
|
||||
district: item.district || '',
|
||||
address: item.address || '',
|
||||
postcode: item.postcode || '',
|
||||
isDefault: item.isDefault || false
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onDeleteAddress(e) {
|
||||
const index = e.currentTarget.dataset.index
|
||||
wx.showModal({
|
||||
title: '提示',
|
||||
content: '确定删除该地址吗?',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
const addresses = this.data.addresses.slice()
|
||||
addresses.splice(index, 1)
|
||||
if (addresses.length > 0 && !addresses.some(a => a.isDefault)) {
|
||||
addresses[0].isDefault = true
|
||||
}
|
||||
this.setData({ addresses })
|
||||
this.triggerEvent('save', { addresses })
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
onSetDefault(e) {
|
||||
const index = e.currentTarget.dataset.index
|
||||
const addresses = this.data.addresses.map((item, i) => ({
|
||||
...item,
|
||||
isDefault: i === index
|
||||
}))
|
||||
this.setData({ addresses })
|
||||
this.triggerEvent('save', { addresses })
|
||||
},
|
||||
|
||||
onBackToList() {
|
||||
this.setData({ isEditing: false })
|
||||
},
|
||||
|
||||
onRegionChange(e) {
|
||||
const region = e.detail.value
|
||||
this.setData({
|
||||
'editData.province': region[0] || '',
|
||||
'editData.city': region[1] || '',
|
||||
'editData.district': region[2] || ''
|
||||
})
|
||||
},
|
||||
|
||||
onFieldInput(e) {
|
||||
const field = e.currentTarget.dataset.field
|
||||
this.setData({
|
||||
[`editData.${field}`]: e.detail.value
|
||||
})
|
||||
},
|
||||
|
||||
onDefaultChange(e) {
|
||||
this.setData({
|
||||
'editData.isDefault': e.detail.value
|
||||
})
|
||||
},
|
||||
|
||||
onSaveEdit() {
|
||||
const editData = this.data.editData
|
||||
if (!editData.label.trim()) {
|
||||
wx.showToast({ title: '请输入地址标签', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!editData.province || !editData.city || !editData.district) {
|
||||
wx.showToast({ title: '请选择所在地区', icon: 'none' })
|
||||
return
|
||||
}
|
||||
if (!editData.address.trim()) {
|
||||
wx.showToast({ title: '请输入详细地址', icon: 'none' })
|
||||
return
|
||||
}
|
||||
|
||||
const addresses = this.data.addresses.slice()
|
||||
const newItem = {
|
||||
label: editData.label.trim(),
|
||||
province: editData.province,
|
||||
city: editData.city,
|
||||
district: editData.district,
|
||||
address: editData.address.trim(),
|
||||
postcode: editData.postcode.trim(),
|
||||
isDefault: editData.isDefault
|
||||
}
|
||||
|
||||
if (editData.isDefault) {
|
||||
addresses.forEach(item => { item.isDefault = false })
|
||||
}
|
||||
|
||||
if (editData._index >= 0) {
|
||||
addresses[editData._index] = newItem
|
||||
} else {
|
||||
if (addresses.length === 0) {
|
||||
newItem.isDefault = true
|
||||
}
|
||||
addresses.push(newItem)
|
||||
}
|
||||
|
||||
this.setData({
|
||||
addresses,
|
||||
isEditing: false
|
||||
})
|
||||
this.triggerEvent('save', { addresses })
|
||||
}
|
||||
}
|
||||
})
|
||||
6
xui/wxapp/pages/mine/comp_address/comp_address.json
Normal file
6
xui/wxapp/pages/mine/comp_address/comp_address.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"component": true,
|
||||
"usingComponents": {
|
||||
"t-icon": "tdesign-miniprogram/icon/icon"
|
||||
}
|
||||
}
|
||||
79
xui/wxapp/pages/mine/comp_address/comp_address.wxml
Normal file
79
xui/wxapp/pages/mine/comp_address/comp_address.wxml
Normal file
@@ -0,0 +1,79 @@
|
||||
<view class="address-overlay" wx:if="{{visible}}" bindtap="onClose">
|
||||
<view class="address-sheet" catchtap="onSheetTap">
|
||||
<view class="address-header">
|
||||
<view class="address-back" wx:if="{{isEditing}}" bindtap="onBackToList">
|
||||
<t-icon name="chevron-left" size="36rpx" color="#999" />
|
||||
</view>
|
||||
<text class="address-title">{{isEditing ? (editData._index >= 0 ? '编辑地址' : '新增地址') : '邮寄地址'}}</text>
|
||||
<view class="address-close" bindtap="onClose">
|
||||
<t-icon name="close" size="36rpx" color="#999" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="address-body" wx:if="{{!isEditing}}">
|
||||
<view class="address-empty" wx:if="{{addresses.length === 0}}">
|
||||
<t-icon name="location" size="80rpx" color="#CCCCCC" />
|
||||
<text class="address-empty-text">暂无地址,点击添加</text>
|
||||
</view>
|
||||
|
||||
<view class="address-list" wx:if="{{addresses.length > 0}}">
|
||||
<view class="address-card" wx:for="{{addresses}}" wx:key="index">
|
||||
<view class="address-card-main" bindtap="onEditAddress" data-index="{{index}}">
|
||||
<view class="address-card-top">
|
||||
<text class="address-label">{{item.label}}</text>
|
||||
<text class="address-default-tag" wx:if="{{item.isDefault}}">默认</text>
|
||||
</view>
|
||||
<view class="address-card-content">
|
||||
<text class="address-region">{{item.province}} {{item.city}} {{item.district}}</text>
|
||||
<text class="address-detail">{{item.address}}</text>
|
||||
<text class="address-postcode" wx:if="{{item.postcode}}">邮编:{{item.postcode}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="address-card-actions">
|
||||
<view class="address-action-default" bindtap="onSetDefault" data-index="{{index}}">
|
||||
<t-icon name="{{item.isDefault ? 'check-circle-filled' : 'circle'}}" size="32rpx" color="{{item.isDefault ? '#FF8500' : '#999'}}" />
|
||||
<text class="action-text {{item.isDefault ? 'active' : ''}}">{{item.isDefault ? '默认地址' : '设为默认'}}</text>
|
||||
</view>
|
||||
<view class="address-action-delete" bindtap="onDeleteAddress" data-index="{{index}}">
|
||||
<t-icon name="delete" size="32rpx" color="#999" />
|
||||
<text class="action-text">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="address-body" wx:if="{{isEditing}}">
|
||||
<view class="address-form">
|
||||
<view class="form-item">
|
||||
<text class="form-label">地址标签</text>
|
||||
<input class="form-input" value="{{editData.label}}" placeholder="如:家庭、公司" maxlength="20" bindinput="onFieldInput" data-field="label" />
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="form-label">所在地区</text>
|
||||
<picker mode="region" value="{{[editData.province, editData.city, editData.district]}}" bindchange="onRegionChange">
|
||||
<view class="form-picker">
|
||||
{{editData.province || '请选择地区'}}{{editData.city ? ' ' + editData.city : ''}}{{editData.district ? ' ' + editData.district : ''}}
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<view class="form-item">
|
||||
<text class="form-label">详细地址</text>
|
||||
<input class="form-input" value="{{editData.address}}" placeholder="请输入详细地址" maxlength="100" bindinput="onFieldInput" data-field="address" />
|
||||
</view>
|
||||
|
||||
<view class="form-item form-item-switch">
|
||||
<text class="form-label">设为默认地址</text>
|
||||
<switch checked="{{editData.isDefault}}" bindchange="onDefaultChange" color="#FF8500" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<view class="address-footer">
|
||||
<button class="address-add-btn" wx:if="{{!isEditing}}" bindtap="onAddAddress">添加新地址</button>
|
||||
<button class="address-save-btn" wx:if="{{isEditing}}" bindtap="onSaveEdit">保存</button>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
237
xui/wxapp/pages/mine/comp_address/comp_address.wxss
Normal file
237
xui/wxapp/pages/mine/comp_address/comp_address.wxss
Normal file
@@ -0,0 +1,237 @@
|
||||
.address-overlay {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
z-index: 1000;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.address-sheet {
|
||||
background: #FFFFFF;
|
||||
border-radius: 32rpx 32rpx 0 0;
|
||||
padding-bottom: env(safe-area-inset-bottom);
|
||||
animation: slideUp 0.3s ease;
|
||||
max-height: 85vh;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@keyframes slideUp {
|
||||
from { transform: translateY(100%); }
|
||||
to { transform: translateY(0); }
|
||||
}
|
||||
|
||||
.address-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 32rpx;
|
||||
position: relative;
|
||||
border-bottom: 1rpx solid #F5F5F5;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.address-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.address-back {
|
||||
position: absolute;
|
||||
left: 32rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
padding: 8rpx;
|
||||
}
|
||||
|
||||
.address-close {
|
||||
position: absolute;
|
||||
right: 32rpx;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
padding: 8rpx;
|
||||
}
|
||||
|
||||
.address-body {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.address-empty {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 120rpx 32rpx;
|
||||
}
|
||||
|
||||
.address-empty-text {
|
||||
margin-top: 24rpx;
|
||||
font-size: 28rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.address-list {
|
||||
padding: 24rpx 32rpx;
|
||||
}
|
||||
|
||||
.address-card {
|
||||
background: #FAFAFA;
|
||||
border-radius: 16rpx;
|
||||
padding: 24rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.address-card-main {
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.address-card-top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 12rpx;
|
||||
}
|
||||
|
||||
.address-label {
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.address-default-tag {
|
||||
font-size: 22rpx;
|
||||
color: #FF8500;
|
||||
background: rgba(255, 133, 0, 0.1);
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 8rpx;
|
||||
}
|
||||
|
||||
.address-card-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8rpx;
|
||||
}
|
||||
|
||||
.address-region {
|
||||
font-size: 28rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-detail {
|
||||
font-size: 28rpx;
|
||||
color: #1A1A1A;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.address-postcode {
|
||||
font-size: 24rpx;
|
||||
color: #999999;
|
||||
}
|
||||
|
||||
.address-card-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
border-top: 1rpx solid #EEEEEE;
|
||||
padding-top: 16rpx;
|
||||
}
|
||||
|
||||
.address-action-default,
|
||||
.address-action-delete {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 8rpx;
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 26rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.action-text.active {
|
||||
color: #FF8500;
|
||||
}
|
||||
|
||||
.address-footer {
|
||||
padding: 4rpx 32rpx 48rpx;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.address-add-btn {
|
||||
background: linear-gradient(135deg, #FF9B33 0%, #FF8500 100%);
|
||||
color: #FFFFFF;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
padding: 28rpx;
|
||||
border-radius: 20rpx;
|
||||
border: none;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.address-add-btn::after {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.address-form {
|
||||
padding: 0 32rpx;
|
||||
}
|
||||
|
||||
.form-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
min-height: 100rpx;
|
||||
border-bottom: 1rpx solid #F5F5F5;
|
||||
}
|
||||
|
||||
.form-item-switch {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
font-size: 30rpx;
|
||||
color: #1A1A1A;
|
||||
font-weight: 500;
|
||||
flex-shrink: 0;
|
||||
margin-right: 24rpx;
|
||||
}
|
||||
|
||||
.form-input {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
font-size: 30rpx;
|
||||
color: #1A1A1A;
|
||||
}
|
||||
|
||||
.form-picker {
|
||||
flex: 1;
|
||||
text-align: right;
|
||||
font-size: 30rpx;
|
||||
color: #666666;
|
||||
}
|
||||
|
||||
.address-save-btn {
|
||||
background: linear-gradient(135deg, #FF9B33 0%, #FF8500 100%);
|
||||
color: #FFFFFF;
|
||||
font-size: 30rpx;
|
||||
font-weight: 600;
|
||||
padding: 28rpx;
|
||||
border-radius: 20rpx;
|
||||
border: none;
|
||||
line-height: 1.5;
|
||||
}
|
||||
|
||||
.address-save-btn::after {
|
||||
border: none;
|
||||
}
|
||||
Reference in New Issue
Block a user