miniprogram: 用永平版本替换(含超级个体、会员详情、提现等)
- 来源: 一场soul的创业实验-永平/soul/miniprogram - 新增: addresses/agreement/privacy/withdraw-records 等页面 - 新增: components/icon, utils/chapterAccessManager, readingTracker - 删除: 上传脚本、部署说明等冗余文件 - 同步永平最新结构和功能 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
123
miniprogram/pages/addresses/addresses.js
Normal file
123
miniprogram/pages/addresses/addresses.js
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
* 收货地址列表页
|
||||
* 参考 Next.js: app/view/my/addresses/page.tsx
|
||||
*/
|
||||
|
||||
const app = getApp()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statusBarHeight: 44,
|
||||
isLoggedIn: false,
|
||||
addressList: [],
|
||||
loading: true
|
||||
},
|
||||
|
||||
onLoad() {
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight || 44
|
||||
})
|
||||
this.checkLogin()
|
||||
},
|
||||
|
||||
onShow() {
|
||||
if (this.data.isLoggedIn) {
|
||||
this.loadAddresses()
|
||||
}
|
||||
},
|
||||
|
||||
// 检查登录状态
|
||||
checkLogin() {
|
||||
const isLoggedIn = app.globalData.isLoggedIn
|
||||
const userId = app.globalData.userInfo?.id
|
||||
|
||||
if (!isLoggedIn || !userId) {
|
||||
wx.showModal({
|
||||
title: '需要登录',
|
||||
content: '请先登录后再管理收货地址',
|
||||
confirmText: '去登录',
|
||||
success: (res) => {
|
||||
if (res.confirm) {
|
||||
wx.switchTab({ url: '/pages/my/my' })
|
||||
} else {
|
||||
wx.navigateBack()
|
||||
}
|
||||
}
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
this.setData({ isLoggedIn: true })
|
||||
this.loadAddresses()
|
||||
},
|
||||
|
||||
// 加载地址列表
|
||||
async loadAddresses() {
|
||||
const userId = app.globalData.userInfo?.id
|
||||
if (!userId) return
|
||||
|
||||
this.setData({ loading: true })
|
||||
|
||||
try {
|
||||
const res = await app.request(`/api/miniprogram/user/addresses?userId=${userId}`)
|
||||
if (res.success && res.list) {
|
||||
this.setData({
|
||||
addressList: res.list,
|
||||
loading: false
|
||||
})
|
||||
} else {
|
||||
this.setData({ addressList: [], loading: false })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载地址列表失败:', e)
|
||||
this.setData({ loading: false })
|
||||
wx.showToast({ title: '加载失败', icon: 'none' })
|
||||
}
|
||||
},
|
||||
|
||||
// 编辑地址
|
||||
editAddress(e) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
wx.navigateTo({ url: `/pages/addresses/edit?id=${id}` })
|
||||
},
|
||||
|
||||
// 删除地址
|
||||
deleteAddress(e) {
|
||||
const id = e.currentTarget.dataset.id
|
||||
|
||||
wx.showModal({
|
||||
title: '确认删除',
|
||||
content: '确定要删除该收货地址吗?',
|
||||
confirmColor: '#FF3B30',
|
||||
success: async (res) => {
|
||||
if (res.confirm) {
|
||||
try {
|
||||
const result = await app.request(`/api/miniprogram/user/addresses/${id}`, {
|
||||
method: 'DELETE'
|
||||
})
|
||||
|
||||
if (result.success) {
|
||||
wx.showToast({ title: '删除成功', icon: 'success' })
|
||||
this.loadAddresses()
|
||||
} else {
|
||||
wx.showToast({ title: result.message || '删除失败', icon: 'none' })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('删除地址失败:', e)
|
||||
wx.showToast({ title: '删除失败', icon: 'none' })
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
|
||||
// 新增地址
|
||||
addAddress() {
|
||||
wx.navigateTo({ url: '/pages/addresses/edit' })
|
||||
},
|
||||
|
||||
// 返回
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
}
|
||||
})
|
||||
5
miniprogram/pages/addresses/addresses.json
Normal file
5
miniprogram/pages/addresses/addresses.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"usingComponents": {},
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
66
miniprogram/pages/addresses/addresses.wxml
Normal file
66
miniprogram/pages/addresses/addresses.wxml
Normal file
@@ -0,0 +1,66 @@
|
||||
<!--收货地址列表页-->
|
||||
<view class="page">
|
||||
<!-- 导航栏 -->
|
||||
<view class="nav-bar" style="padding-top: {{statusBarHeight}}px;">
|
||||
<view class="nav-back" bindtap="goBack">
|
||||
<text class="back-icon">‹</text>
|
||||
</view>
|
||||
<text class="nav-title">收货地址</text>
|
||||
<view class="nav-placeholder"></view>
|
||||
</view>
|
||||
<view style="height: {{statusBarHeight + 44}}px;"></view>
|
||||
|
||||
<view class="content">
|
||||
<!-- 加载状态 -->
|
||||
<view class="loading-state" wx:if="{{loading}}">
|
||||
<text class="loading-text">加载中...</text>
|
||||
</view>
|
||||
|
||||
<!-- 空状态 -->
|
||||
<view class="empty-state" wx:elif="{{addressList.length === 0}}">
|
||||
<text class="empty-icon">📍</text>
|
||||
<text class="empty-text">暂无收货地址</text>
|
||||
<text class="empty-tip">点击下方按钮添加</text>
|
||||
</view>
|
||||
|
||||
<!-- 地址列表 -->
|
||||
<view class="address-list" wx:else>
|
||||
<view
|
||||
class="address-card"
|
||||
wx:for="{{addressList}}"
|
||||
wx:key="id"
|
||||
>
|
||||
<view class="address-header">
|
||||
<text class="receiver-name">{{item.name}}</text>
|
||||
<text class="receiver-phone">{{item.phone}}</text>
|
||||
<text class="default-tag" wx:if="{{item.isDefault}}">默认</text>
|
||||
</view>
|
||||
<text class="address-text">{{item.fullAddress}}</text>
|
||||
<view class="address-actions">
|
||||
<view
|
||||
class="action-btn edit-btn"
|
||||
bindtap="editAddress"
|
||||
data-id="{{item.id}}"
|
||||
>
|
||||
<text class="action-icon">✏️</text>
|
||||
<text class="action-text">编辑</text>
|
||||
</view>
|
||||
<view
|
||||
class="action-btn delete-btn"
|
||||
bindtap="deleteAddress"
|
||||
data-id="{{item.id}}"
|
||||
>
|
||||
<text class="action-icon">🗑️</text>
|
||||
<text class="action-text">删除</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 新增按钮 -->
|
||||
<view class="add-btn" bindtap="addAddress">
|
||||
<text class="add-icon">➕</text>
|
||||
<text class="add-text">新增收货地址</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
217
miniprogram/pages/addresses/addresses.wxss
Normal file
217
miniprogram/pages/addresses/addresses.wxss
Normal file
@@ -0,0 +1,217 @@
|
||||
/**
|
||||
* 收货地址列表页样式
|
||||
*/
|
||||
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: #000000;
|
||||
padding-bottom: 200rpx;
|
||||
}
|
||||
|
||||
/* ===== 导航栏 ===== */
|
||||
.nav-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
backdrop-filter: blur(40rpx);
|
||||
border-bottom: 1rpx solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
.nav-bar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 32rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-back:active {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 48rpx;
|
||||
color: #ffffff;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.nav-placeholder {
|
||||
width: 64rpx;
|
||||
}
|
||||
|
||||
/* ===== 内容区 ===== */
|
||||
.content {
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
/* ===== 加载状态 ===== */
|
||||
.loading-state {
|
||||
padding: 240rpx 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.loading-text {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
/* ===== 空状态 ===== */
|
||||
.empty-state {
|
||||
padding: 240rpx 0;
|
||||
text-align: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.empty-icon {
|
||||
font-size: 96rpx;
|
||||
margin-bottom: 24rpx;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.empty-text {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.empty-tip {
|
||||
font-size: 24rpx;
|
||||
color: rgba(255, 255, 255, 0.4);
|
||||
}
|
||||
|
||||
/* ===== 地址列表 ===== */
|
||||
.address-list {
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
.address-card {
|
||||
background: #1c1c1e;
|
||||
border-radius: 24rpx;
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.05);
|
||||
padding: 32rpx;
|
||||
margin-bottom: 24rpx;
|
||||
}
|
||||
|
||||
/* 地址头部 */
|
||||
.address-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.receiver-name {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.receiver-phone {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.default-tag {
|
||||
font-size: 22rpx;
|
||||
color: #00CED1;
|
||||
background: rgba(0, 206, 209, 0.2);
|
||||
padding: 6rpx 16rpx;
|
||||
border-radius: 8rpx;
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
/* 地址文本 */
|
||||
.address-text {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.6);
|
||||
line-height: 1.6;
|
||||
display: block;
|
||||
margin-bottom: 24rpx;
|
||||
padding-bottom: 24rpx;
|
||||
border-bottom: 2rpx solid rgba(255, 255, 255, 0.05);
|
||||
}
|
||||
|
||||
/* 操作按钮 */
|
||||
.address-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 32rpx;
|
||||
}
|
||||
|
||||
.action-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8rpx;
|
||||
padding: 8rpx 0;
|
||||
}
|
||||
|
||||
.action-btn:active {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.edit-btn {
|
||||
color: #00CED1;
|
||||
}
|
||||
|
||||
.delete-btn {
|
||||
color: #FF3B30;
|
||||
}
|
||||
|
||||
.action-icon {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.action-text {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
/* ===== 新增按钮 ===== */
|
||||
.add-btn {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: 16rpx;
|
||||
padding: 32rpx;
|
||||
background: #00CED1;
|
||||
border-radius: 24rpx;
|
||||
font-weight: 600;
|
||||
margin-top: 48rpx;
|
||||
}
|
||||
|
||||
.add-btn:active {
|
||||
opacity: 0.8;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.add-icon {
|
||||
font-size: 36rpx;
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
.add-text {
|
||||
font-size: 32rpx;
|
||||
color: #000000;
|
||||
}
|
||||
201
miniprogram/pages/addresses/edit.js
Normal file
201
miniprogram/pages/addresses/edit.js
Normal file
@@ -0,0 +1,201 @@
|
||||
/**
|
||||
* 地址编辑页(新增/编辑)
|
||||
* 参考 Next.js: app/view/my/addresses/[id]/page.tsx
|
||||
*/
|
||||
|
||||
const app = getApp()
|
||||
|
||||
Page({
|
||||
data: {
|
||||
statusBarHeight: 44,
|
||||
isEdit: false, // 是否为编辑模式
|
||||
addressId: null,
|
||||
|
||||
// 表单数据
|
||||
name: '',
|
||||
phone: '',
|
||||
province: '',
|
||||
city: '',
|
||||
district: '',
|
||||
detail: '',
|
||||
isDefault: false,
|
||||
|
||||
// 地区选择器
|
||||
region: [],
|
||||
|
||||
saving: false
|
||||
},
|
||||
|
||||
onLoad(options) {
|
||||
this.setData({
|
||||
statusBarHeight: app.globalData.statusBarHeight || 44
|
||||
})
|
||||
|
||||
// 如果有 id 参数,则为编辑模式
|
||||
if (options.id) {
|
||||
this.setData({
|
||||
isEdit: true,
|
||||
addressId: options.id
|
||||
})
|
||||
this.loadAddress(options.id)
|
||||
}
|
||||
},
|
||||
|
||||
// 加载地址详情(编辑模式)
|
||||
async loadAddress(id) {
|
||||
wx.showLoading({ title: '加载中...', mask: true })
|
||||
|
||||
try {
|
||||
const res = await app.request(`/api/miniprogram/user/addresses/${id}`)
|
||||
if (res.success && res.data) {
|
||||
const addr = res.data
|
||||
this.setData({
|
||||
name: addr.name || '',
|
||||
phone: addr.phone || '',
|
||||
province: addr.province || '',
|
||||
city: addr.city || '',
|
||||
district: addr.district || '',
|
||||
detail: addr.detail || '',
|
||||
isDefault: addr.isDefault || false,
|
||||
region: [addr.province, addr.city, addr.district]
|
||||
})
|
||||
} else {
|
||||
wx.showToast({ title: '加载失败', icon: 'none' })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('加载地址详情失败:', e)
|
||||
wx.showToast({ title: '加载失败', icon: 'none' })
|
||||
} finally {
|
||||
wx.hideLoading()
|
||||
}
|
||||
},
|
||||
|
||||
// 表单输入
|
||||
onNameInput(e) {
|
||||
this.setData({ name: e.detail.value })
|
||||
},
|
||||
|
||||
onPhoneInput(e) {
|
||||
this.setData({ phone: e.detail.value.replace(/\D/g, '').slice(0, 11) })
|
||||
},
|
||||
|
||||
onDetailInput(e) {
|
||||
this.setData({ detail: e.detail.value })
|
||||
},
|
||||
|
||||
// 地区选择
|
||||
onRegionChange(e) {
|
||||
const region = e.detail.value
|
||||
this.setData({
|
||||
region,
|
||||
province: region[0],
|
||||
city: region[1],
|
||||
district: region[2]
|
||||
})
|
||||
},
|
||||
|
||||
// 切换默认地址
|
||||
onDefaultChange(e) {
|
||||
this.setData({ isDefault: e.detail.value })
|
||||
},
|
||||
|
||||
// 表单验证
|
||||
validateForm() {
|
||||
const { name, phone, province, city, district, detail } = this.data
|
||||
|
||||
if (!name || name.trim().length === 0) {
|
||||
wx.showToast({ title: '请输入收货人姓名', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
if (!phone || phone.length !== 11) {
|
||||
wx.showToast({ title: '请输入正确的手机号', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
if (!province || !city || !district) {
|
||||
wx.showToast({ title: '请选择省市区', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
if (!detail || detail.trim().length === 0) {
|
||||
wx.showToast({ title: '请输入详细地址', icon: 'none' })
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
},
|
||||
|
||||
// 保存地址
|
||||
async saveAddress() {
|
||||
if (!this.validateForm()) return
|
||||
if (this.data.saving) return
|
||||
|
||||
this.setData({ saving: true })
|
||||
wx.showLoading({ title: '保存中...', mask: true })
|
||||
|
||||
const { isEdit, addressId, name, phone, province, city, district, detail, isDefault } = this.data
|
||||
const userId = app.globalData.userInfo?.id
|
||||
|
||||
if (!userId) {
|
||||
wx.hideLoading()
|
||||
wx.showToast({ title: '请先登录', icon: 'none' })
|
||||
this.setData({ saving: false })
|
||||
return
|
||||
}
|
||||
|
||||
const addressData = {
|
||||
userId,
|
||||
name,
|
||||
phone,
|
||||
province,
|
||||
city,
|
||||
district,
|
||||
detail,
|
||||
fullAddress: `${province}${city}${district}${detail}`,
|
||||
isDefault
|
||||
}
|
||||
|
||||
try {
|
||||
let res
|
||||
if (isEdit) {
|
||||
// 编辑模式 - PUT 请求
|
||||
res = await app.request(`/api/miniprogram/user/addresses/${addressId}`, {
|
||||
method: 'PUT',
|
||||
data: addressData
|
||||
})
|
||||
} else {
|
||||
// 新增模式 - POST 请求
|
||||
res = await app.request('/api/miniprogram/user/addresses', {
|
||||
method: 'POST',
|
||||
data: addressData
|
||||
})
|
||||
}
|
||||
|
||||
if (res.success) {
|
||||
wx.hideLoading()
|
||||
wx.showToast({
|
||||
title: isEdit ? '保存成功' : '添加成功',
|
||||
icon: 'success'
|
||||
})
|
||||
setTimeout(() => {
|
||||
wx.navigateBack()
|
||||
}, 1500)
|
||||
} else {
|
||||
wx.hideLoading()
|
||||
wx.showToast({ title: res.message || '保存失败', icon: 'none' })
|
||||
this.setData({ saving: false })
|
||||
}
|
||||
} catch (e) {
|
||||
console.error('保存地址失败:', e)
|
||||
wx.hideLoading()
|
||||
wx.showToast({ title: '保存失败', icon: 'none' })
|
||||
this.setData({ saving: false })
|
||||
}
|
||||
},
|
||||
|
||||
// 返回
|
||||
goBack() {
|
||||
wx.navigateBack()
|
||||
}
|
||||
})
|
||||
5
miniprogram/pages/addresses/edit.json
Normal file
5
miniprogram/pages/addresses/edit.json
Normal file
@@ -0,0 +1,5 @@
|
||||
{
|
||||
"usingComponents": {},
|
||||
"navigationStyle": "custom",
|
||||
"enablePullDownRefresh": false
|
||||
}
|
||||
101
miniprogram/pages/addresses/edit.wxml
Normal file
101
miniprogram/pages/addresses/edit.wxml
Normal file
@@ -0,0 +1,101 @@
|
||||
<!--地址编辑页-->
|
||||
<view class="page">
|
||||
<!-- 导航栏 -->
|
||||
<view class="nav-bar" style="padding-top: {{statusBarHeight}}px;">
|
||||
<view class="nav-back" bindtap="goBack">
|
||||
<text class="back-icon">‹</text>
|
||||
</view>
|
||||
<text class="nav-title">{{isEdit ? '编辑地址' : '新增地址'}}</text>
|
||||
<view class="nav-placeholder"></view>
|
||||
</view>
|
||||
<view style="height: {{statusBarHeight + 44}}px;"></view>
|
||||
|
||||
<view class="content">
|
||||
<view class="form-card">
|
||||
<!-- 收货人 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="label-icon">👤</text>
|
||||
<text class="label-text">收货人</text>
|
||||
</view>
|
||||
<input
|
||||
class="form-input"
|
||||
placeholder="请输入收货人姓名"
|
||||
placeholder-class="input-placeholder"
|
||||
value="{{name}}"
|
||||
bindinput="onNameInput"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 手机号 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="label-icon">📱</text>
|
||||
<text class="label-text">手机号</text>
|
||||
</view>
|
||||
<input
|
||||
class="form-input"
|
||||
type="number"
|
||||
placeholder="请输入11位手机号"
|
||||
placeholder-class="input-placeholder"
|
||||
value="{{phone}}"
|
||||
bindinput="onPhoneInput"
|
||||
maxlength="11"
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 地区选择 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="label-icon">📍</text>
|
||||
<text class="label-text">所在地区</text>
|
||||
</view>
|
||||
<picker
|
||||
mode="region"
|
||||
value="{{region}}"
|
||||
bindchange="onRegionChange"
|
||||
class="region-picker"
|
||||
>
|
||||
<view class="picker-value">
|
||||
{{province || city || district ? province + ' ' + city + ' ' + district : '请选择省市区'}}
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
|
||||
<!-- 详细地址 -->
|
||||
<view class="form-item">
|
||||
<view class="form-label">
|
||||
<text class="label-icon">🏠</text>
|
||||
<text class="label-text">详细地址</text>
|
||||
</view>
|
||||
<textarea
|
||||
class="form-textarea"
|
||||
placeholder="请输入街道、门牌号等详细地址"
|
||||
placeholder-class="input-placeholder"
|
||||
value="{{detail}}"
|
||||
bindinput="onDetailInput"
|
||||
maxlength="200"
|
||||
auto-height
|
||||
/>
|
||||
</view>
|
||||
|
||||
<!-- 设为默认 -->
|
||||
<view class="form-item form-switch">
|
||||
<view class="form-label">
|
||||
<text class="label-icon">⭐</text>
|
||||
<text class="label-text">设为默认地址</text>
|
||||
</view>
|
||||
<switch
|
||||
checked="{{isDefault}}"
|
||||
bindchange="onDefaultChange"
|
||||
color="#00CED1"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 保存按钮 -->
|
||||
<view class="save-btn {{saving ? 'btn-disabled' : ''}}" bindtap="saveAddress">
|
||||
{{saving ? '保存中...' : '保存'}}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
186
miniprogram/pages/addresses/edit.wxss
Normal file
186
miniprogram/pages/addresses/edit.wxss
Normal file
@@ -0,0 +1,186 @@
|
||||
/**
|
||||
* 地址编辑页样式
|
||||
*/
|
||||
|
||||
.page {
|
||||
min-height: 100vh;
|
||||
background: #000000;
|
||||
padding-bottom: 200rpx;
|
||||
}
|
||||
|
||||
/* ===== 导航栏 ===== */
|
||||
.nav-bar {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 100;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
backdrop-filter: blur(40rpx);
|
||||
border-bottom: 1rpx solid rgba(255, 255, 255, 0.05);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 0 32rpx;
|
||||
height: 88rpx;
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.nav-back:active {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
}
|
||||
|
||||
.back-icon {
|
||||
font-size: 48rpx;
|
||||
color: #ffffff;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.nav-title {
|
||||
flex: 1;
|
||||
text-align: center;
|
||||
font-size: 36rpx;
|
||||
font-weight: 600;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.nav-placeholder {
|
||||
width: 64rpx;
|
||||
}
|
||||
|
||||
/* ===== 内容区 ===== */
|
||||
.content {
|
||||
padding: 32rpx;
|
||||
}
|
||||
|
||||
/* ===== 表单卡片 ===== */
|
||||
.form-card {
|
||||
background: #1c1c1e;
|
||||
border-radius: 32rpx;
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.05);
|
||||
padding: 32rpx;
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
/* 表单项 */
|
||||
.form-item {
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
|
||||
.form-item:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.form-label {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12rpx;
|
||||
margin-bottom: 16rpx;
|
||||
}
|
||||
|
||||
.label-icon {
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.label-text {
|
||||
font-size: 28rpx;
|
||||
color: rgba(255, 255, 255, 0.7);
|
||||
}
|
||||
|
||||
/* 输入框 */
|
||||
.form-input {
|
||||
width: 100%;
|
||||
padding: 24rpx 32rpx;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 24rpx;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.form-input:focus {
|
||||
border-color: rgba(0, 206, 209, 0.5);
|
||||
}
|
||||
|
||||
.input-placeholder {
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
/* 地区选择器 */
|
||||
.region-picker {
|
||||
width: 100%;
|
||||
padding: 24rpx 32rpx;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 24rpx;
|
||||
}
|
||||
|
||||
.picker-value {
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
|
||||
.picker-value:empty::before {
|
||||
content: '请选择省市区';
|
||||
color: rgba(255, 255, 255, 0.3);
|
||||
}
|
||||
|
||||
/* 多行文本框 */
|
||||
.form-textarea {
|
||||
width: 100%;
|
||||
padding: 24rpx 32rpx;
|
||||
background: rgba(0, 0, 0, 0.3);
|
||||
border: 2rpx solid rgba(255, 255, 255, 0.1);
|
||||
border-radius: 24rpx;
|
||||
color: #ffffff;
|
||||
font-size: 28rpx;
|
||||
min-height: 160rpx;
|
||||
line-height: 1.6;
|
||||
}
|
||||
|
||||
.form-textarea:focus {
|
||||
border-color: rgba(0, 206, 209, 0.5);
|
||||
}
|
||||
|
||||
/* 开关项 */
|
||||
.form-switch {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 16rpx 0;
|
||||
}
|
||||
|
||||
.form-switch .form-label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
/* ===== 保存按钮 ===== */
|
||||
.save-btn {
|
||||
padding: 32rpx;
|
||||
background: #00CED1;
|
||||
border-radius: 24rpx;
|
||||
text-align: center;
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #000000;
|
||||
margin-top: 48rpx;
|
||||
}
|
||||
|
||||
.save-btn:active {
|
||||
opacity: 0.8;
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
.btn-disabled {
|
||||
opacity: 0.5;
|
||||
pointer-events: none;
|
||||
}
|
||||
Reference in New Issue
Block a user