Browse Source

feat: page-address;

fox
Fox-33 3 weeks ago
parent
commit
e5bdaba0c6
9 changed files with 689 additions and 0 deletions
  1. +12
    -0
      pages.json
  2. +139
    -0
      pages_order/address/addressCard.vue
  3. +208
    -0
      pages_order/address/addressList.vue
  4. +249
    -0
      pages_order/address/addressPopup.vue
  5. +79
    -0
      pages_order/address/addressView.vue
  6. +2
    -0
      pages_order/product/countSelectPopup.vue
  7. BIN
      pages_order/static/address/icon-address.png
  8. BIN
      pages_order/static/address/icon-delete.png
  9. BIN
      pages_order/static/address/icon-edit.png

+ 12
- 0
pages.json View File

@ -79,9 +79,21 @@
{
"path": "product/productDetail"
},
{
"path": "order/orderConfirm/index"
},
{
"path": "order/orderList/index"
},
{
"path": "address/addressList"
},
{
"path": "comment/commentRecords"
},
{
"path": "comment/commentWrite"
},
{


+ 139
- 0
pages_order/address/addressCard.vue View File

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

+ 208
- 0
pages_order/address/addressList.vue View File

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

+ 249
- 0
pages_order/address/addressPopup.vue View File

@ -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%;
// todocheck
// 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>

+ 79
- 0
pages_order/address/addressView.vue View File

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

+ 2
- 0
pages_order/product/countSelectPopup.vue View File

@ -214,6 +214,8 @@ export default {
.footer {
width: 100%;
// todocheck
// height: 214rpx;
padding: 32rpx 40rpx;
box-sizing: border-box;


BIN
pages_order/static/address/icon-address.png View File

Before After
Width: 16  |  Height: 16  |  Size: 482 B

BIN
pages_order/static/address/icon-delete.png View File

Before After
Width: 19  |  Height: 18  |  Size: 381 B

BIN
pages_order/static/address/icon-edit.png View File

Before After
Width: 19  |  Height: 18  |  Size: 427 B

Loading…
Cancel
Save