@ -0,0 +1,139 @@ | |||||
<template> | |||||
<view class="card"> | |||||
<view class="top" @click="$emit('click')"> | |||||
<addressView :data="data"></addressView> | |||||
</view> | |||||
<view class="flex bottom"> | |||||
<view class="flex col"> | |||||
<view> | |||||
<uv-radio-group | |||||
v-model="radiovalue" | |||||
shape="circle" | |||||
size="36rpx" | |||||
iconSize="36rpx" | |||||
labelSize="24rpx" | |||||
labelColor="#9B9B9B" | |||||
activeColor="#7451DE" | |||||
@change="onRadioChange" | |||||
> | |||||
<uv-radio :name="1"> | |||||
<view>默认地址</view> | |||||
</uv-radio> | |||||
</uv-radio-group> | |||||
</view> | |||||
</view> | |||||
<button class="flex col btn" @click="onEdit"> | |||||
<image class="icon" src="@/pages_order/static/address/icon-edit.png" mode="scaleToFill"></image> | |||||
<view>编辑</view> | |||||
</button> | |||||
<button class="flex col btn" @click="onDelete"> | |||||
<image class="icon" src="@/pages_order/static/address/icon-delete.png" mode="scaleToFill"></image> | |||||
<view>删除</view> | |||||
</button> | |||||
</view> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
import addressView from './addressView.vue'; | |||||
export default { | |||||
components: { | |||||
addressView, | |||||
}, | |||||
props: { | |||||
data: { | |||||
type: Object, | |||||
default() { | |||||
return {} | |||||
} | |||||
}, | |||||
}, | |||||
data() { | |||||
return { | |||||
radiovalue: null, | |||||
} | |||||
}, | |||||
computed: { | |||||
isDefault: { | |||||
set(val) { | |||||
this.radiovalue = val ? 1 : null | |||||
if (this.data.default == val) { | |||||
return | |||||
} | |||||
// todo: set this address as default | |||||
this.$emit('defaultChange', val) | |||||
}, | |||||
get() { | |||||
return this.radiovalue == 1 ? true : false | |||||
} | |||||
}, | |||||
}, | |||||
watch: { | |||||
data: { | |||||
handler(val) { | |||||
this.isDefault = val.default | |||||
}, | |||||
immediate: true, | |||||
deep: true, | |||||
} | |||||
}, | |||||
methods: { | |||||
onRadioChange() { | |||||
this.isDefault = true | |||||
}, | |||||
onEdit() { | |||||
// todo | |||||
this.$emit('edit') | |||||
}, | |||||
onDelete() { | |||||
uni.showModal({ | |||||
title: '确认删除?', | |||||
success : e => { | |||||
if(e.confirm){ | |||||
// todo | |||||
this.$emit('delete') | |||||
} | |||||
} | |||||
}) | |||||
}, | |||||
} | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
.card { | |||||
padding: 24rpx 32rpx; | |||||
background: #FFFFFF; | |||||
border-radius: 24rpx; | |||||
.top { | |||||
padding-bottom: 24rpx; | |||||
} | |||||
.bottom { | |||||
padding-top: 24rpx; | |||||
column-gap: 24rpx; | |||||
border-top: 2rpx dashed #DADADA; | |||||
.col { | |||||
flex: 1; | |||||
column-gap: 8rpx; | |||||
font-family: PingFang SC; | |||||
font-weight: 400; | |||||
font-size: 24rpx; | |||||
line-height: 1.4; | |||||
color: #9B9B9B; | |||||
.icon { | |||||
width: 36rpx; | |||||
height: 36rpx; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
</style> |
@ -0,0 +1,208 @@ | |||||
<template> | |||||
<view class="page__view"> | |||||
<navbar title="选择地址" leftClick @leftClick="$utils.navigateBack" color="#191919" bgColor="#FFFFFF" /> | |||||
<view class="main"> | |||||
<view class="card" v-for="(item, index) in list" :key="item.id"> | |||||
<addressCard | |||||
:data="item" | |||||
@defaultChange="onDefaultChange(index, $event)" | |||||
@click="onSelect(item)" | |||||
@edit="onEdit(item)" | |||||
@delete="onDelete(item.id)" | |||||
></addressCard> | |||||
</view> | |||||
</view> | |||||
<view class="flex bottom"> | |||||
<button class="btn" @click="onAdd">新建地址</button> | |||||
</view> | |||||
<addressPopup ref="addressPopup" @submitted="getData"></addressPopup> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
import mixinsList from '@/mixins/list.js' | |||||
import addressCard from './addressCard.vue' | |||||
import addressPopup from '@/pages_order/address/addressPopup.vue' | |||||
export default { | |||||
mixins: [mixinsList], | |||||
components: { | |||||
addressCard, | |||||
addressPopup, | |||||
}, | |||||
data() { | |||||
return { | |||||
// todo | |||||
mixinsListApi: '', | |||||
} | |||||
}, | |||||
methods: { | |||||
getData() { | |||||
this.list = [ | |||||
{ | |||||
id: '001', | |||||
name: '郑文锦', | |||||
phone: '18108341643', | |||||
area: ['海南省', '海口市', '秀英区'], | |||||
address: '秀英街道5单元183室', | |||||
default: true, | |||||
}, | |||||
{ | |||||
id: '002', | |||||
name: '周俊', | |||||
phone: '13293992217', | |||||
area: ['贵州省', '遵义市', '道真仡佬族苗族自治县'], | |||||
address: '洛龙镇5幢172室', | |||||
default: false, | |||||
}, | |||||
{ | |||||
id: '003', | |||||
name: '何炜', | |||||
phone: '18108341643', | |||||
area: ['新疆维吾尔自治区', '乌鲁木齐市', '沙依巴克区'], | |||||
address: '仓房沟片区街道4单元50室', | |||||
default: false, | |||||
}, | |||||
{ | |||||
id: '004', | |||||
name: '赵萸艳', | |||||
phone: '15022123314', | |||||
area: ['海南省', '海口市', '秀英区'], | |||||
address: '海南省海口市秀英区秀英街道5单元183室', | |||||
default: false, | |||||
}, | |||||
{ | |||||
id: '005', | |||||
name: '周俊', | |||||
phone: '13293992217', | |||||
area: ['贵州省', '遵义市', '道真仡佬族苗族自治县'], | |||||
address: '贵州省遵义市道真仡佬族苗族自治县洛龙镇5幢172室', | |||||
default: false, | |||||
}, | |||||
{ | |||||
id: '006', | |||||
name: '何炜', | |||||
phone: '18108341643', | |||||
area: ['新疆维吾尔自治区', '乌鲁木齐市', '沙依巴克区'], | |||||
address: '新疆维吾尔自治区乌鲁木齐市沙依巴克区仓房沟片区街道4单元50室', | |||||
default: false, | |||||
}, | |||||
{ | |||||
id: '007', | |||||
name: '赵萸艳', | |||||
phone: '15022123314', | |||||
area: ['海南省', '海口市', '秀英区'], | |||||
address: '海南省海口市秀英区秀英街道5单元183室', | |||||
default: false, | |||||
}, | |||||
] | |||||
this.total = this.list.length | |||||
}, | |||||
onDefaultChange(index) { | |||||
console.log('onDefaultChange', index) | |||||
this.list.forEach((item, idx) => { | |||||
if (idx === index) { | |||||
item.default = true | |||||
} else { | |||||
item.default = false | |||||
} | |||||
}) | |||||
}, | |||||
onSelect(data) { | |||||
this.$store.commit('setAddressInfo', data) | |||||
this.$utils.navigateBack() | |||||
}, | |||||
onDelete(id) { | |||||
uni.showToast({ | |||||
icon: 'loading', | |||||
title: '正在删除', | |||||
}); | |||||
setTimeout(() => { | |||||
this.list = this.list.filter(item => item.id !== id) | |||||
this.total = this.list.length | |||||
uni.showToast({ | |||||
icon: 'success', | |||||
title: '删除成功', | |||||
}); | |||||
// uni.showToast({ | |||||
// icon: 'error', | |||||
// title: '删除失败', | |||||
// }); | |||||
}, 1000) | |||||
}, | |||||
onEdit(data) { | |||||
this.$refs.addressPopup.open(data) | |||||
}, | |||||
onAdd() { | |||||
this.$refs.addressPopup.open() | |||||
}, | |||||
}, | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
.page__view { | |||||
width: 100vw; | |||||
min-height: 100vh; | |||||
background-color: $uni-bg-color; | |||||
position: relative; | |||||
/deep/ .nav-bar__view { | |||||
position: fixed; | |||||
top: 0; | |||||
left: 0; | |||||
} | |||||
} | |||||
.main { | |||||
padding: calc(var(--status-bar-height) + 160rpx) 40rpx 254rpx 40rpx; | |||||
} | |||||
.card { | |||||
& + & { | |||||
margin-top: 40rpx; | |||||
} | |||||
} | |||||
.bottom { | |||||
position: fixed; | |||||
left: 0; | |||||
bottom: 0; | |||||
align-items: flex-start; | |||||
width: 100vw; | |||||
height: 214rpx; | |||||
padding: 32rpx 40rpx; | |||||
background: #FFFFFF; | |||||
box-sizing: border-box; | |||||
.btn { | |||||
width: 100%; | |||||
padding: 16rpx 0; | |||||
box-sizing: border-box; | |||||
font-family: PingFang SC; | |||||
font-weight: 500; | |||||
font-size: 36rpx; | |||||
line-height: 1; | |||||
color: #FFFFFF; | |||||
background-image: linear-gradient(to right, #4B348F, #845CFA); | |||||
border-radius: 41rpx; | |||||
} | |||||
} | |||||
</style> |
@ -0,0 +1,249 @@ | |||||
<template> | |||||
<view> | |||||
<uv-popup ref="popup" mode="bottom" bgColor="none" > | |||||
<view class="popup__view"> | |||||
<view class="flex header"> | |||||
<view class="title">新建地址</view> | |||||
<button class="btn" @click="close">关闭</button> | |||||
</view> | |||||
<view class="form"> | |||||
<uv-form | |||||
ref="form" | |||||
:model="form" | |||||
:rules="rules" | |||||
errorType="toast" | |||||
> | |||||
<view class="form-item"> | |||||
<uv-form-item prop="name" :customStyle="formItemStyle"> | |||||
<view class="form-item-label">联系人</view> | |||||
<view class="form-item-content"> | |||||
<formInput v-model="form.name"></formInput> | |||||
</view> | |||||
</uv-form-item> | |||||
</view> | |||||
<view class="form-item"> | |||||
<uv-form-item prop="phone" :customStyle="formItemStyle"> | |||||
<view class="form-item-label">手机号</view> | |||||
<view class="form-item-content"> | |||||
<formInput v-model="form.phone"></formInput> | |||||
</view> | |||||
</uv-form-item> | |||||
</view> | |||||
<view class="form-item"> | |||||
<uv-form-item prop="phone" :customStyle="formItemStyle"> | |||||
<view class="form-item-label">所在地区</view> | |||||
<view class="form-item-content"> | |||||
<picker mode="region" @change="onAreaChange" :value="form.area"> | |||||
<view class="flex region"> | |||||
<view v-if="form.area">{{ form.area.join('') }}</view> | |||||
<view v-else class="placeholder">选择省市区街道</view> | |||||
</view> | |||||
</picker> | |||||
<!-- <formInput v-model="form.phone"></formInput> --> | |||||
</view> | |||||
</uv-form-item> | |||||
</view> | |||||
<view class="form-item"> | |||||
<uv-form-item prop="address" :customStyle="formItemStyle"> | |||||
<view class="form-item-label">详细地址</view> | |||||
<view class="form-item-content"> | |||||
<formInput v-model="form.address" placeholder="小区楼栋、门牌号、村等"></formInput> | |||||
</view> | |||||
</uv-form-item> | |||||
</view> | |||||
</uv-form> | |||||
</view> | |||||
<view class="footer"> | |||||
<button class="flex btn" @click="onSave">保存</button> | |||||
</view> | |||||
</view> | |||||
</uv-popup> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
import formInput from '@/pages_order/components/formInput.vue' | |||||
export default { | |||||
components: { | |||||
formInput, | |||||
}, | |||||
data() { | |||||
return { | |||||
form: { | |||||
name: null, | |||||
phone: null, | |||||
area: null, | |||||
address: null, | |||||
}, | |||||
rules: { | |||||
'name': { | |||||
type: 'string', | |||||
required: true, | |||||
message: '请输入联系人', | |||||
}, | |||||
'phone': { | |||||
type: 'string', | |||||
required: true, | |||||
message: '请输入手机号', | |||||
}, | |||||
'area': { | |||||
type: 'array', | |||||
required: true, | |||||
message: '请选择省市区', | |||||
}, | |||||
'address': { | |||||
type: 'string', | |||||
required: true, | |||||
message: '请输入详细地址', | |||||
}, | |||||
}, | |||||
formItemStyle: { padding: 0 }, | |||||
} | |||||
}, | |||||
methods: { | |||||
open(data) { | |||||
if (data) { | |||||
const { | |||||
name, | |||||
phone, | |||||
area, | |||||
address, | |||||
} = data | |||||
this.form = { | |||||
name, | |||||
phone, | |||||
area, | |||||
address, | |||||
} | |||||
} | |||||
this.$refs.popup.open() | |||||
}, | |||||
close() { | |||||
this.$refs.popup.close() | |||||
}, | |||||
onAreaChange(e) { | |||||
this.form.area = e.detail.value | |||||
}, | |||||
async onSave() { | |||||
try { | |||||
const res = await this.$refs.form.validate() | |||||
console.log('onSave res', res) | |||||
// todo: save | |||||
this.$emit('submitted') | |||||
this.close() | |||||
} catch (err) { | |||||
console.log('onSave err', err) | |||||
} | |||||
}, | |||||
}, | |||||
} | |||||
</script> | |||||
<style lang="scss" scoped> | |||||
.popup__view { | |||||
width: 100vw; | |||||
display: flex; | |||||
flex-direction: column; | |||||
box-sizing: border-box; | |||||
background: #FFFFFF; | |||||
border-top-left-radius: 32rpx; | |||||
border-top-right-radius: 32rpx; | |||||
} | |||||
.header { | |||||
position: relative; | |||||
width: 100%; | |||||
padding: 24rpx 0; | |||||
box-sizing: border-box; | |||||
border-bottom: 2rpx solid #EEEEEE; | |||||
.title { | |||||
font-family: PingFang SC; | |||||
font-weight: 500; | |||||
font-size: 34rpx; | |||||
line-height: 1.4; | |||||
color: #181818; | |||||
} | |||||
.btn { | |||||
font-family: PingFang SC; | |||||
font-weight: 500; | |||||
font-size: 32rpx; | |||||
line-height: 1.4; | |||||
color: #8B8B8B; | |||||
position: absolute; | |||||
top: 26rpx; | |||||
left: 40rpx; | |||||
} | |||||
} | |||||
.form { | |||||
padding: 32rpx 40rpx; | |||||
&-item { | |||||
padding: 8rpx 0 6rpx 0; | |||||
& + & { | |||||
padding-top: 24rpx; | |||||
border-top: 2rpx solid #EEEEEE; | |||||
} | |||||
&-label { | |||||
margin-bottom: 14rpx; | |||||
font-family: PingFang SC; | |||||
font-weight: 400; | |||||
font-size: 26rpx; | |||||
line-height: 1.4; | |||||
color: #181818; | |||||
} | |||||
&-content { | |||||
.placeholder { | |||||
color: #C6C6C6; | |||||
font-size: 32rpx; | |||||
font-weight: 400; | |||||
} | |||||
.region { | |||||
min-height: 44rpx; | |||||
justify-content: flex-start; | |||||
} | |||||
} | |||||
} | |||||
} | |||||
.footer { | |||||
width: 100%; | |||||
// todo:check | |||||
// height: 214rpx; | |||||
padding: 32rpx 40rpx; | |||||
box-sizing: border-box; | |||||
border-top: 2rpx solid #F1F1F1; | |||||
.btn { | |||||
width: 100%; | |||||
padding: 16rpx 0; | |||||
font-family: PingFang SC; | |||||
font-weight: 500; | |||||
font-size: 36rpx; | |||||
line-height: 1.4; | |||||
color: #FFFFFF; | |||||
background-image: linear-gradient(to right, #4B348F, #845CFA); | |||||
border-radius: 41rpx; | |||||
} | |||||
} | |||||
</style> |
@ -0,0 +1,79 @@ | |||||
<template> | |||||
<view> | |||||
<template v-if="data"> | |||||
<view class="flex user"> | |||||
<view>{{ data.name }}</view> | |||||
<view>{{ data.phone }}</view> | |||||
<view class="tag" v-if="data.default">默认</view> | |||||
</view> | |||||
<view class="flex address"> | |||||
<image v-if="showIcon" class="icon" src="@/pages_order/static/address/icon-address.png" mode="scaleToFill"></image> | |||||
<view>{{ `${data.area.join('')}${data.address}` }}</view> | |||||
</view> | |||||
</template> | |||||
<template v-else> | |||||
<view>请选择地址</view> | |||||
</template> | |||||
</view> | |||||
</template> | |||||
<script> | |||||
export default { | |||||
props: { | |||||
data: { | |||||
type: Object, | |||||
default() { | |||||
return null | |||||
} | |||||
}, | |||||
showIcon: { | |||||
type: Boolean, | |||||
default: false, | |||||
} | |||||
}, | |||||
} | |||||
</script> | |||||
<style scoped lang="scss"> | |||||
.user { | |||||
justify-content: flex-start; | |||||
column-gap: 24rpx; | |||||
font-family: PingFang SC; | |||||
font-weight: 400; | |||||
font-size: 32rpx; | |||||
line-height: 1.4; | |||||
color: #181818; | |||||
.tag { | |||||
padding: 2rpx 14rpx; | |||||
font-family: PingFang SC; | |||||
font-weight: 400; | |||||
font-size: 24rpx; | |||||
line-height: 1.4; | |||||
color: #7451DE; | |||||
background: #EFEAFF; | |||||
border: 2rpx solid #7451DE; | |||||
border-radius: 8rpx; | |||||
} | |||||
} | |||||
.address { | |||||
margin-top: 16rpx; | |||||
align-items: flex-start; | |||||
justify-content: flex-start; | |||||
font-family: PingFang SC; | |||||
font-weight: 400; | |||||
font-size: 28rpx; | |||||
line-height: 1.4; | |||||
color: #9B9B9B; | |||||
.icon { | |||||
margin: 3px 8rpx 0 0; | |||||
width: 32rpx; | |||||
height: 32rpx; | |||||
} | |||||
} | |||||
</style> |