邹方成 6f7207da2d feat: 优化UI设计并重构样式系统
refactor(components): 重构ElCard、FlipGrid、YifanSelector和PaymentPopup组件样式
refactor(pages): 优化地址管理、商品详情、订单列表、积分记录和活动页面UI
style: 更新uni.scss全局样式变量和设计系统
docs: 添加说明文档记录UI优化进度
2025-12-17 14:32:55 +08:00

234 lines
6.5 KiB
Vue

<template>
<view class="wrap">
<view class="form-item">
<text class="label">姓名</text>
<input class="input" v-model="name" placeholder="请输入姓名" />
</view>
<view class="form-item">
<text class="label">手机号</text>
<input class="input" v-model="mobile" placeholder="请输入手机号" />
</view>
<view class="form-item">
<text class="label">省份</text>
<input class="input" v-model="province" placeholder="请输入省份" />
</view>
<view class="form-item">
<text class="label">城市</text>
<input class="input" v-model="city" placeholder="请输入城市" />
</view>
<view class="form-item">
<text class="label">区县</text>
<input class="input" v-model="district" placeholder="请输入区县" />
</view>
<view class="form-item">
<text class="label">详细地址</text>
<input class="input" v-model="detail" placeholder="请输入详细地址" />
</view>
<view class="form-item">
<text class="label">设为默认</text>
<switch :checked="isDefault" @change="e => isDefault = e.detail.value" />
</view>
<button class="submit" :disabled="loading" @click="onSubmit">保存</button>
<view v-if="error" class="error">{{ error }}</view>
</view>
</template>
<script setup>
import { ref } from 'vue'
import { onLoad } from '@dcloudio/uni-app'
import { addAddress, updateAddress, listAddresses, setDefaultAddress } from '../../api/appUser'
const id = ref('')
const name = ref('')
const mobile = ref('')
const province = ref('')
const city = ref('')
const district = ref('')
const detail = ref('')
let isDefault = false
const loading = ref(false)
const error = ref('')
function fill(data) {
name.value = data.name || data.realname || ''
mobile.value = data.mobile || data.phone || ''
province.value = data.province || ''
city.value = data.city || ''
district.value = data.district || ''
detail.value = data.address || data.detail || ''
isDefault = !!data.is_default
}
async function init(idParam) {
if (!idParam) {
const data = uni.getStorageSync('edit_address') || {}
if (data && data.id) fill(data)
return
}
const user_id = uni.getStorageSync('user_id')
try {
const list = await listAddresses(user_id)
const arr = Array.isArray(list) ? list : (list && (list.list || list.items)) || []
const found = arr.find(a => String(a.id) === String(idParam))
if (found) fill(found)
} catch (e) {}
}
async function onSubmit() {
const user_id = uni.getStorageSync('user_id')
if (!name.value || !mobile.value || !province.value || !city.value || !district.value || !detail.value) {
uni.showToast({ title: '请完善必填信息', icon: 'none' })
return
}
loading.value = true
error.value = ''
const payload = {
name: name.value,
mobile: mobile.value,
province: province.value,
city: city.value,
district: district.value,
address: detail.value,
is_default: isDefault
}
try {
let savedId = id.value
if (id.value) {
await updateAddress(user_id, id.value, payload)
savedId = id.value
} else {
try {
const res = await addAddress(user_id, payload)
savedId = (res && (res.id || res.address_id)) || ''
} catch (eAdd) {
const sc = eAdd && eAdd.statusCode
const bc = (eAdd && eAdd.data && (eAdd.data.code || eAdd.code)) || undefined
const msg = eAdd && (eAdd.message || eAdd.errMsg || '')
const isUniqueErr = sc === 400 && (bc === 10011 || (msg && msg.toLowerCase().includes('unique')))
if (isUniqueErr) {
try {
const list = await listAddresses(user_id)
const arr = Array.isArray(list) ? list : (list && (list.list || list.items)) || []
const found = arr.find(a => (a.mobile === mobile.value || a.phone === mobile.value) && (a.address === detail.value || a.detail === detail.value) && (a.city === city.value) && (a.district === district.value) && (a.province === province.value))
if (found) {
savedId = found.id
await updateAddress(user_id, savedId, payload)
}
} catch (_) {}
} else {
throw eAdd
}
}
}
if (isDefault) {
if (!savedId) {
try {
const list = await listAddresses(user_id)
const arr = Array.isArray(list) ? list : (list && (list.list || list.items)) || []
const found = arr.find(a => (a.mobile === mobile.value || a.phone === mobile.value) && (a.address === detail.value || a.detail === detail.value))
if (found) savedId = found.id
} catch (_) {}
}
if (savedId) {
await setDefaultAddress(user_id, savedId)
}
}
uni.showToast({ title: '保存成功', icon: 'success' })
uni.navigateBack()
} catch (e) {
error.value = e && (e.message || e.errMsg) || '保存失败'
} finally {
loading.value = false
}
}
onLoad((opts) => {
id.value = (opts && opts.id) || ''
init(id.value)
})
</script>
<style lang="scss" scoped>
/* ============================================
奇盒潮玩 - 地址编辑页面
采用暖橙色调的表单设计
============================================ */
.wrap {
padding: $spacing-lg;
min-height: 100vh;
background: $bg-page;
}
/* 表单项 */
.form-item {
display: flex;
align-items: center;
background: #FFFFFF;
border-radius: $radius-lg;
padding: $spacing-lg $spacing-xl;
margin-bottom: $spacing-md;
box-shadow: $shadow-sm;
transition: all 0.2s;
&:focus-within {
box-shadow: $shadow-md;
transform: translateY(-2rpx);
}
}
.label {
width: 160rpx;
font-size: $font-md;
font-weight: 600;
color: $text-main;
flex-shrink: 0;
}
.input {
flex: 1;
font-size: $font-md;
color: $text-main;
background: transparent;
height: 48rpx;
}
/* 提交按钮 */
.submit {
width: 100%;
height: 96rpx;
line-height: 96rpx;
margin-top: 60rpx;
background: $gradient-brand !important;
color: #FFFFFF !important;
border-radius: $radius-round;
font-size: $font-lg;
font-weight: 800;
border: none;
box-shadow: $shadow-warm;
transition: all 0.2s ease;
&:active {
transform: scale(0.96);
box-shadow: none;
}
&[disabled] {
opacity: 0.6;
box-shadow: none;
background: $text-disabled !important;
}
}
/* 错误提示 */
.error {
color: $color-error;
font-size: $font-sm;
margin-top: $spacing-lg;
padding: $spacing-md;
background: rgba($color-error, 0.1);
border-radius: $radius-md;
text-align: center;
font-weight: 500;
}
</style>