This commit is contained in:
lik
2026-05-25 12:34:16 +08:00
parent c614b19b78
commit 1e7aa55533
986 changed files with 23880 additions and 0 deletions

View 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 })
}
}
})

View File

@@ -0,0 +1,6 @@
{
"component": true,
"usingComponents": {
"t-icon": "tdesign-miniprogram/icon/icon"
}
}

View 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>

View 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;
}