'!'
This commit is contained in:
34
src/pagesAddress/Switch/switch.scss
Normal file
34
src/pagesAddress/Switch/switch.scss
Normal file
@@ -0,0 +1,34 @@
|
||||
@import '@/assets/_color.scss';
|
||||
|
||||
.zy-switch {
|
||||
width: 2em;
|
||||
height: 1em;
|
||||
display: inline-block;
|
||||
background: white;
|
||||
border: 1rpx solid $border2;
|
||||
border-radius: 1em;
|
||||
font-size: 50rpx;
|
||||
position: relative;
|
||||
align-items: center;
|
||||
transition: all .3s;
|
||||
.zy-switch-item {
|
||||
position: absolute;
|
||||
width: 1em;
|
||||
height: 1em;
|
||||
border-radius: 100%;
|
||||
box-shadow: 0 6rpx 2rpx 0 rgba(0, 0, 0, 0.05), 0 4rpx 4rpx 0 rgba(0, 0, 0, 0.1), 0 6rpx 6rpx 0 rgba(0, 0, 0, 0.05);
|
||||
transition: .3s;
|
||||
background: white;
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
.switch-on {
|
||||
flex-direction: row-reverse;
|
||||
background: $maincolor;
|
||||
.zy-switch-item {
|
||||
left: 1em;
|
||||
}
|
||||
}
|
||||
.switch-disabled {
|
||||
opacity: .5;
|
||||
}
|
||||
77
src/pagesAddress/Switch/switch.vue
Normal file
77
src/pagesAddress/Switch/switch.vue
Normal file
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
滑块组件
|
||||
*/
|
||||
<template>
|
||||
<div
|
||||
class="zy-switch"
|
||||
@click="onChange"
|
||||
:class="{
|
||||
'switch-on': currentValue,
|
||||
'switch-disabled': disabled
|
||||
}"
|
||||
:style="{'font-size': size + 'rpx'}"
|
||||
>
|
||||
<div class="zy-switch-item"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'ZySwitch',
|
||||
props: {
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
value: {
|
||||
type: [Boolean, Number, String],
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: '50'
|
||||
},
|
||||
trueValue: {
|
||||
type: [Boolean, Number, String],
|
||||
default: true
|
||||
},
|
||||
falseValue: {
|
||||
type: [Boolean, Number, String],
|
||||
default: false
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
if (val === this.trueValue || val === this.falseValue) {
|
||||
this.updateModel()
|
||||
} else {
|
||||
throw 'Value should be trueValue or falseValue'
|
||||
}
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
currentValue: this.value
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onChange () {
|
||||
console.log('onchange')
|
||||
if (this.disabled) return false
|
||||
let checked = !this.currentValue
|
||||
this.currentValue = checked
|
||||
let value = checked ? this.trueValue : this.falseValue
|
||||
this.$emit('input:value', value)
|
||||
|
||||
// this.$emit('on-change', value)
|
||||
},
|
||||
updateModel () {
|
||||
this.currentValue = this.value === this.trueValue
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './switch';
|
||||
</style>
|
||||
29
src/pagesAddress/addressCmp/address-item.scss
Normal file
29
src/pagesAddress/addressCmp/address-item.scss
Normal file
@@ -0,0 +1,29 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.address-item {
|
||||
@extend %pdtb;
|
||||
border-bottom: 1rpx solid $border3;
|
||||
margin: 0 50rpx;
|
||||
position: relative;
|
||||
#{&}-title {
|
||||
color: $text1;
|
||||
font-size: 34rpx;
|
||||
@extend %oneline;
|
||||
width: 500rpx;
|
||||
}
|
||||
#{&}-address {
|
||||
color: $text3;
|
||||
font-size: 28rpx;
|
||||
padding-top: 10rpx;
|
||||
@extend %oneline;
|
||||
// border: 1px solid red;
|
||||
}
|
||||
.title{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
&-distance{
|
||||
color:$text3;
|
||||
font-size: 28rpx;
|
||||
}
|
||||
}
|
||||
33
src/pagesAddress/addressCmp/address-item.vue
Normal file
33
src/pagesAddress/addressCmp/address-item.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<div class="address-item">
|
||||
<div class="title">
|
||||
<div class="address-item-title">{{title}}</div>
|
||||
<div class="address-item-distance" v-if="!isKM">{{distance.toFixed(1)}}米</div>
|
||||
<div class="address-item-distance" v-else >{{(distance/1000).toFixed(1)}}千米</div>
|
||||
</div>
|
||||
<div class="address-item-address">{{address}}</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
title: String,
|
||||
address: String,
|
||||
distance:Number
|
||||
},
|
||||
computed: {
|
||||
isKM(){
|
||||
let isKM = true // 是否为千米
|
||||
if(String(this.distance).split('.')[0].length<4){
|
||||
isKM = false
|
||||
}
|
||||
return isKM
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./address-item.scss";
|
||||
</style>
|
||||
43
src/pagesAddress/addressCmp/waybill-address.scss
Normal file
43
src/pagesAddress/addressCmp/waybill-address.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.waybill-address {
|
||||
border-bottom: 1rpx solid $border2;
|
||||
@extend %flex-center;
|
||||
// @extend %pdlr;
|
||||
padding: 30rpx;
|
||||
min-height: 140rpx;
|
||||
#{&}-left {
|
||||
flex: auto;
|
||||
|
||||
}
|
||||
#{&}-right {
|
||||
flex: none;
|
||||
// width: 100rpx;
|
||||
.icon-editor {
|
||||
@extend %icon-editor;
|
||||
@extend %bg-no-repeat-center;
|
||||
background-size: 40rpx;
|
||||
width: 100rpx;
|
||||
height: 100rpx;
|
||||
}
|
||||
}
|
||||
#{&}-address {
|
||||
font-size: 30rpx;
|
||||
color: $text1;
|
||||
margin-bottom: 10rpx;
|
||||
}
|
||||
#{&}-contact {
|
||||
font-size: 30rpx;
|
||||
color: $text3;
|
||||
}
|
||||
.isDefault {
|
||||
font-size: 22rpx;
|
||||
display: inline-block;
|
||||
@extend %flex-center;
|
||||
padding: 10rpx;
|
||||
background: $danger;
|
||||
color: white;
|
||||
border-radius: 10rpx;;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
43
src/pagesAddress/addressCmp/waybill-address.vue
Normal file
43
src/pagesAddress/addressCmp/waybill-address.vue
Normal file
@@ -0,0 +1,43 @@
|
||||
<template>
|
||||
<div class="waybill-address">
|
||||
<div class="waybill-address-left" @click="handlePick">
|
||||
<div class="waybill-address-address">
|
||||
<span class="isDefault" v-if="address.isDefault">默认</span>
|
||||
{{address.address}}
|
||||
</div>
|
||||
<div class="waybill-address-contact">
|
||||
{{address.consigneeName}} {{address.consigneeMobile}}
|
||||
</div>
|
||||
</div>
|
||||
<!-- 编辑 -->
|
||||
<div class="waybill-address-right" @click="toEditor">
|
||||
<div class="icon-editor"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
address: Object,
|
||||
isManager: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 跳转到编辑页面
|
||||
toEditor () {
|
||||
this.$emit('on-edit', this.address)
|
||||
},
|
||||
async handlePick () {
|
||||
console.log('选择')
|
||||
this.$emit('on-pick', this.address)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './waybill-address.scss';
|
||||
</style>
|
||||
34
src/pagesAddress/create-address-cop/create-address.scss
Normal file
34
src/pagesAddress/create-address-cop/create-address.scss
Normal file
@@ -0,0 +1,34 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.create-address {
|
||||
padding: 20rpx 50rpx;
|
||||
.consigneeName,
|
||||
.consigneeMobile,
|
||||
.map-address,
|
||||
.address,
|
||||
.isDefault {
|
||||
border-bottom: 1rpx solid $border2;
|
||||
}
|
||||
.btn-save {
|
||||
@extend %btn-linearGradient;
|
||||
margin-top: 60rpx;
|
||||
width: 100%;
|
||||
border-radius: 0;
|
||||
height: 80rpx;
|
||||
}
|
||||
.btn-delete {
|
||||
margin-top: 60rpx;
|
||||
@extend %flex-center;
|
||||
.icon-delete {
|
||||
@extend %icon-clearAll;
|
||||
@extend %bg-no-repeat-center;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
background-size: 40rpx;
|
||||
@extend %bgwhite;
|
||||
box-shadow: 0 4rpx 8rpx rgba(black, .3);
|
||||
border: 1rpx solid $border1;
|
||||
}
|
||||
}
|
||||
}
|
||||
223
src/pagesAddress/create-address-cop/index.vue
Normal file
223
src/pagesAddress/create-address-cop/index.vue
Normal file
@@ -0,0 +1,223 @@
|
||||
<template>
|
||||
<div class="create-address">
|
||||
<!-- 联系人 -->
|
||||
<div class="consigneeName">
|
||||
<input-label
|
||||
label="联系人:"
|
||||
:maxlength="16"
|
||||
placeholder="请填写收货人的姓名"
|
||||
v-model:value="form.consigneeName"
|
||||
></input-label>
|
||||
</div>
|
||||
<!-- 手机号 -->
|
||||
<div class="consigneeMobile">
|
||||
<input-label
|
||||
label="手机号:"
|
||||
type="number"
|
||||
placeholder="请填写收货人的手机号码"
|
||||
:maxlength="11"
|
||||
v-model:value="form.consigneeMobile"
|
||||
></input-label>
|
||||
</div>
|
||||
<!-- 收货地址 -->
|
||||
<picker mode ="region" :value="addressInfo.value" @change="selectCity">
|
||||
<input-label
|
||||
label="省市区:"
|
||||
placeholder="点击选择省市区"
|
||||
v-model:value="modelValue"
|
||||
isText
|
||||
suffix
|
||||
></input-label>
|
||||
</picker>
|
||||
|
||||
<div class="map-address" @click="toPosition">
|
||||
<input-label
|
||||
label="收货地址:"
|
||||
placeholder="点击选择收货地址"
|
||||
v-model:value="mapAddress"
|
||||
isText
|
||||
suffix
|
||||
></input-label>
|
||||
</div>
|
||||
<!-- 门牌号 -->
|
||||
<div class="address">
|
||||
<input-label
|
||||
label="详细地址:"
|
||||
:maxlength="30"
|
||||
placeholder="详细地址,例:1栋1单元801"
|
||||
v-model:value="form.detailAddress"
|
||||
></input-label>
|
||||
</div>
|
||||
<!-- 设为默认地址 -->
|
||||
<div class="isDefault">
|
||||
<switch-label
|
||||
label="设为默认地址:"
|
||||
v-model:value="form.isDefault"
|
||||
></switch-label>
|
||||
</div>
|
||||
<!-- 保存 -->
|
||||
<!-- <button @click="saveAddress">保存地址</button> -->
|
||||
<div class="btn-save" @click="saveAddress">保存地址</div>
|
||||
<!-- 删除按钮 -->
|
||||
<div class="btn-delete" v-if="address" @click="deleteAddress">
|
||||
<div class="icon-delete"></div>
|
||||
</div>
|
||||
<!-- loading -->
|
||||
<ZyLoading></ZyLoading>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ZyLoading from '@/components/Loading/loading'
|
||||
import InputLabel from '../input-label/input-lebel.vue'
|
||||
import SwitchLabel from '../switch-label/switch-label.vue'
|
||||
import {isRequire, isMobile} from '@/utils/validate.js'
|
||||
import {toast,jumpPage} from '@/utils/uniapi.js'
|
||||
import {mapGetters, mapActions} from 'vuex'
|
||||
import {errToast} from '@/utils/uniapi.js'
|
||||
export default {
|
||||
props: {
|
||||
address: Object // 用来标识是否是编辑状态
|
||||
},
|
||||
components: {
|
||||
ZyLoading, InputLabel, SwitchLabel
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
id: 0,
|
||||
form: {
|
||||
consigneeName: '',
|
||||
consigneeMobile: '',
|
||||
detailAddress: '',
|
||||
isDefault: false
|
||||
},
|
||||
lat: null,
|
||||
lng: null,
|
||||
mapAddress: '',
|
||||
addressInfo:{
|
||||
code:['510000','510100','510106'],
|
||||
postcode:610036, // 邮编
|
||||
value:['四川省','成都市','金牛区']
|
||||
},
|
||||
modelValue:'四川省/成都市/金牛区'
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.address) {
|
||||
let item = this.address
|
||||
this.id = item.id
|
||||
this.form.consigneeName = item.consigneeName
|
||||
this.form.consigneeMobile = item.consigneeMobile
|
||||
this.form.detailAddress = item.detailAddress
|
||||
this.mapAddress = item.address
|
||||
this.form.isDefault = !!item.isDefault
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
// console.log('销毁')
|
||||
// 修改changeCity为当前地位的城市
|
||||
this.$store.commit('indexPage/changeCity', this.location.city)
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
location: 'indexPage/myLocation',
|
||||
curPickAddress: 'addressVue/curPickAddress'
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
curPickAddress (address) {
|
||||
console.log(address)
|
||||
if (address) {
|
||||
this.mapAddress = address.address + address.title
|
||||
this.lat = address.location.lat
|
||||
this.lng = address.location.lng
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
addAddressList: 'addressVue/addListItem'
|
||||
}),
|
||||
async saveAddress () {
|
||||
let {consigneeName, consigneeMobile, detailAddress} = this.form
|
||||
let isDefault = this.form.isDefault ? 1 : 0
|
||||
let mapAddress = this.mapAddress
|
||||
consigneeName = consigneeName.trim()
|
||||
consigneeMobile = consigneeMobile.trim()
|
||||
detailAddress = detailAddress.trim()
|
||||
mapAddress = mapAddress.trim()
|
||||
const {lat, lng} = this
|
||||
// console.log(consigneeName, consigneeMobile, detailAddress, mapAddress, lat, lng)
|
||||
if (!isRequire(consigneeName)) {
|
||||
toast('请填写正确的联系人')
|
||||
return false
|
||||
}
|
||||
if (!isMobile(consigneeMobile)) {
|
||||
toast('请填写正确的手机号')
|
||||
return false
|
||||
}
|
||||
if (!isRequire(mapAddress)) {
|
||||
toast('请选择收货地址')
|
||||
return false
|
||||
}
|
||||
if (!isRequire(detailAddress)) {
|
||||
toast('请填写正确门牌号')
|
||||
return false
|
||||
}
|
||||
// 校验通过
|
||||
if (this.address) {
|
||||
// 保存编辑
|
||||
let json = {
|
||||
id: this.id,
|
||||
consigneeName,
|
||||
consigneeMobile,
|
||||
detailAddress,
|
||||
cityCode:this.addressInfo.code[1],
|
||||
districtCode :this.addressInfo.code[2],
|
||||
address: mapAddress,
|
||||
isDefault
|
||||
}
|
||||
if (this.lat) json.lat = this.lat
|
||||
if (this.lng) json.lng = this.lng
|
||||
this.$emit('handle-update', json)
|
||||
} else {
|
||||
try {
|
||||
await this.addAddressList({
|
||||
consigneeName,
|
||||
consigneeMobile,
|
||||
address: mapAddress,
|
||||
detailAddress,
|
||||
cityCode:this.addressInfo.code[1],
|
||||
districtCode :this.addressInfo.code[2],
|
||||
lng,
|
||||
lat,
|
||||
isDefault
|
||||
})
|
||||
uni.navigateBack({delta: 1})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
errToast(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 选择省市区
|
||||
selectCity(e){
|
||||
this.modelValue = e.detail.value.join('/')
|
||||
this.addressInfo = e.detail
|
||||
// store.commit('indexPage/changeCity', e.detail.value[1])
|
||||
},
|
||||
// 跳转到收货地址选择
|
||||
toPosition () {
|
||||
jumpPage('navigateTo',`/pagesAddress/position-address/index?showMine=false&districtName=${this.addressInfo.value[2]}`)
|
||||
},
|
||||
// 删除
|
||||
deleteAddress () {
|
||||
this.$emit('handle-delete', this.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './create-address.scss';
|
||||
</style>
|
||||
35
src/pagesAddress/create-address/create-address.scss
Normal file
35
src/pagesAddress/create-address/create-address.scss
Normal file
@@ -0,0 +1,35 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.create-address {
|
||||
padding: 20rpx 50rpx;
|
||||
.consigneeName,
|
||||
.consigneeMobile,
|
||||
.map-address,
|
||||
.address,
|
||||
.isDefault {
|
||||
border-bottom: 1rpx solid $border2;
|
||||
}
|
||||
.btn-save {
|
||||
@extend %btn-linearGradient;
|
||||
margin-top: 60rpx;
|
||||
width: 100%;
|
||||
border-radius: 0;
|
||||
height: 80rpx;
|
||||
border-radius: 20rpx;
|
||||
}
|
||||
.btn-delete {
|
||||
margin-top: 60rpx;
|
||||
@extend %flex-center;
|
||||
.icon-delete {
|
||||
@extend %icon-clearAll;
|
||||
@extend %bg-no-repeat-center;
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 50%;
|
||||
background-size: 40rpx;
|
||||
@extend %bgwhite;
|
||||
box-shadow: 0 4rpx 8rpx rgba(black, .3);
|
||||
border: 1rpx solid $border1;
|
||||
}
|
||||
}
|
||||
}
|
||||
248
src/pagesAddress/create-address/index.vue
Normal file
248
src/pagesAddress/create-address/index.vue
Normal file
@@ -0,0 +1,248 @@
|
||||
<template>
|
||||
<div class="create-address">
|
||||
<!-- 联系人 -->
|
||||
<div class="consigneeName">
|
||||
<input-label
|
||||
label="联系人:"
|
||||
:maxlength="16"
|
||||
placeholder="请填写收货人的姓名"
|
||||
v-model:value="form.consigneeName"
|
||||
></input-label>
|
||||
</div>
|
||||
<!-- 手机号 -->
|
||||
<div class="consigneeMobile">
|
||||
<input-label
|
||||
label="手机号:"
|
||||
type="number"
|
||||
placeholder="请填写收货人的手机号码"
|
||||
:maxlength="11"
|
||||
v-model:value="form.consigneeMobile"
|
||||
></input-label>
|
||||
</div>
|
||||
<!-- 收货地址 -->
|
||||
<!-- <div class="map-address" @click="toPosition">
|
||||
<input-label
|
||||
label="收货地址:"
|
||||
placeholder="点击选择收货地址"
|
||||
v-model:value="mapAddress"
|
||||
isText
|
||||
suffix
|
||||
></input-label>
|
||||
</div> -->
|
||||
<!-- /:value="modelValue" -->
|
||||
<picker mode ="region" :value="addressInfo.value" @change="selectCity">
|
||||
<input-label
|
||||
label="省市区:"
|
||||
placeholder="点击选择省市区"
|
||||
v-model:value="modelValue"
|
||||
isText
|
||||
suffix
|
||||
></input-label>
|
||||
</picker>
|
||||
|
||||
<div class="map-address" @click="toPosition">
|
||||
<input-label
|
||||
label="收货地址:"
|
||||
placeholder="点击选择收货地址"
|
||||
v-model:value="mapAddress"
|
||||
isText
|
||||
suffix
|
||||
></input-label>
|
||||
</div>
|
||||
<!-- 门牌号 -->
|
||||
<div class="address">
|
||||
<input-label
|
||||
label="详细地址:"
|
||||
:maxlength="30"
|
||||
placeholder="例:1栋1单元801"
|
||||
v-model:value="form.detailAddress"
|
||||
></input-label>
|
||||
</div>
|
||||
<!-- 设为默认地址 -->
|
||||
<div class="isDefault">
|
||||
<switch-label
|
||||
label="设为默认地址:"
|
||||
v-model:value="form.isDefault"
|
||||
></switch-label>
|
||||
</div>
|
||||
<!-- 保存 -->
|
||||
<!-- <button @click="saveAddress">保存地址</button> -->
|
||||
<div class="btn-save" @click="saveAddress">保存地址</div>
|
||||
<!-- 删除按钮 -->
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<div class="btn-delete" v-if="address" @click="deleteAddress">
|
||||
<div class="icon-delete"></div>
|
||||
</div>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- #ifdef MP-TOUTIAO -->
|
||||
<div class="btn-delete" v-if="JSON.stringify(address)!=='{}'" @click="deleteAddress">
|
||||
<div class="icon-delete"></div>
|
||||
</div>
|
||||
<!-- #endif -->
|
||||
|
||||
<!-- loading -->
|
||||
<ZyLoading></ZyLoading>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ZyLoading from '@/components/Loading/loading'
|
||||
import InputLabel from '../input-label/input-lebel.vue'
|
||||
import SwitchLabel from '../switch-label/switch-label.vue'
|
||||
import {isRequire, isMobile} from '@/utils/validate.js'
|
||||
import {toast,jumpPage} from '@/utils/uniapi.js'
|
||||
import {mapGetters, mapActions} from 'vuex'
|
||||
import { errToast } from '@/utils/uniapi.js'
|
||||
import {store} from "@/store";
|
||||
export default {
|
||||
props: {
|
||||
address: Object // 用来标识是否是编辑状态
|
||||
},
|
||||
components: {
|
||||
ZyLoading, InputLabel, SwitchLabel
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
id: 0,
|
||||
form: {
|
||||
consigneeName: '',
|
||||
consigneeMobile: '',
|
||||
detailAddress: '',
|
||||
isDefault: false
|
||||
},
|
||||
lat: null,
|
||||
lng: null,
|
||||
mapAddress: '',
|
||||
addressInfo:{
|
||||
code:['510000','510100','510106'],
|
||||
postcode:610036, // 邮编
|
||||
value:['四川省','成都市','金牛区']
|
||||
},
|
||||
modelValue:'四川省/成都市/金牛区'
|
||||
}
|
||||
},
|
||||
created () {
|
||||
if (this.address) {
|
||||
let item = this.address
|
||||
this.id = item.id
|
||||
this.form.consigneeName = item.consigneeName
|
||||
this.form.consigneeMobile = item.consigneeMobile
|
||||
this.form.detailAddress = item.detailAddress
|
||||
this.mapAddress = item.address
|
||||
this.form.isDefault = !!item.isDefault
|
||||
}
|
||||
},
|
||||
destroyed () {
|
||||
// console.log('销毁')
|
||||
// 修改changeCity为当前地位的城市
|
||||
store.commit('indexPage/changeCity', this.location.city)
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
location: 'indexPage/myLocation',
|
||||
curPickAddress: 'addressVue/curPickAddress'
|
||||
})
|
||||
},
|
||||
watch: {
|
||||
curPickAddress (address) {
|
||||
if (address) {
|
||||
this.mapAddress = address.address + address.title
|
||||
this.lat = address.location.lat
|
||||
this.lng = address.location.lng
|
||||
}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
addAddressList: 'addressVue/addListItem'
|
||||
}),
|
||||
async saveAddress () {
|
||||
let {consigneeName, consigneeMobile, detailAddress} = this.form
|
||||
let isDefault = this.form.isDefault ? 1 : 0
|
||||
let mapAddress = this.mapAddress
|
||||
consigneeName = consigneeName.trim()
|
||||
consigneeMobile = consigneeMobile.trim()
|
||||
detailAddress = detailAddress.trim()
|
||||
mapAddress = mapAddress.trim()
|
||||
const { lat, lng } = this
|
||||
// console.log(consigneeName, consigneeMobile, detailAddress, mapAddress, lat, lng)
|
||||
if (!isRequire(consigneeName)) {
|
||||
toast('请填写正确的联系人')
|
||||
return false
|
||||
}
|
||||
if (!isMobile(consigneeMobile)) {
|
||||
toast('请填写正确的手机号')
|
||||
return false
|
||||
}
|
||||
if (!isRequire(mapAddress)) {
|
||||
toast('请选择收货地址')
|
||||
return false
|
||||
}
|
||||
if (!isRequire(detailAddress)) {
|
||||
toast('请填写详细地址')
|
||||
return false
|
||||
}
|
||||
let flag = false
|
||||
// #ifndef MP-TOUTIAO
|
||||
flag = this.address ? true : false
|
||||
// #endif
|
||||
|
||||
// #ifdef MP-TOUTIAO
|
||||
flag = JSON.stringify(this.address)!=='{}' ? true : false
|
||||
// #endif
|
||||
// 校验通过
|
||||
if (flag) {
|
||||
// 保存编辑
|
||||
let json = {
|
||||
id: this.id,
|
||||
consigneeName,
|
||||
consigneeMobile,
|
||||
detailAddress,
|
||||
address: mapAddress,
|
||||
isDefault
|
||||
}
|
||||
if (this.lat) json.lat = this.lat
|
||||
if (this.lng) json.lng = this.lng
|
||||
this.$emit('handle-update', json)
|
||||
} else {
|
||||
try {
|
||||
await this.addAddressList({
|
||||
consigneeName,
|
||||
consigneeMobile,
|
||||
address: mapAddress,
|
||||
detailAddress,
|
||||
cityCode:this.addressInfo.code[1],
|
||||
districtCode :this.addressInfo.code[2],
|
||||
lng,
|
||||
lat,
|
||||
isDefault
|
||||
})
|
||||
uni.navigateBack({delta: 1})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
errToast(e)
|
||||
}
|
||||
}
|
||||
},
|
||||
// 跳转到收货地址选择
|
||||
toPosition () {
|
||||
jumpPage('navigateTo',`/pagesAddress/position-address/index?showMine=false&districtName=${this.addressInfo.value[2]}`)
|
||||
},
|
||||
// 选择省市区
|
||||
selectCity(e){
|
||||
this.modelValue = e.detail.value.join('/')
|
||||
this.addressInfo = e.detail
|
||||
// store.commit('indexPage/changeCity', e.detail.value[1])
|
||||
},
|
||||
// 删除
|
||||
deleteAddress () {
|
||||
this.$emit('handle-delete', this.id)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './create-address.scss';
|
||||
</style>
|
||||
3
src/pagesAddress/edit-address/edit-address.scss
Normal file
3
src/pagesAddress/edit-address/edit-address.scss
Normal file
@@ -0,0 +1,3 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.edit-address {}
|
||||
72
src/pagesAddress/edit-address/index.vue
Normal file
72
src/pagesAddress/edit-address/index.vue
Normal file
@@ -0,0 +1,72 @@
|
||||
<template>
|
||||
<div class="edit-address">
|
||||
<create-address
|
||||
v-if="address"
|
||||
:address="address"
|
||||
@handle-update="handleUpdate"
|
||||
@handle-delete="handleDelete"
|
||||
></create-address>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CreateAddress from '@/pagesAddress/create-address-cop/index.vue'
|
||||
import {mapActions} from 'vuex'
|
||||
import {msgData} from '@/config.js'
|
||||
import {modal, errToast} from '@/utils/uniapi.js'
|
||||
export default {
|
||||
components: {
|
||||
CreateAddress
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
address: null
|
||||
}
|
||||
},
|
||||
onLoad (query) {
|
||||
console.log('onload')
|
||||
let address = JSON.parse(decodeURIComponent(query.address))
|
||||
// console.log(address)
|
||||
this.address = address
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
delAddressItem: 'addressVue/delListItem',
|
||||
updateAddressItem: 'addressVue/updateListItem'
|
||||
}),
|
||||
async handleUpdate (json) {
|
||||
try {
|
||||
this.showLoad()
|
||||
await this.updateAddressItem(json)
|
||||
uni.navigateBack({delta: 1})
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
errToast(e)
|
||||
} finally {
|
||||
this.hideLoad()
|
||||
}
|
||||
},
|
||||
async handleDelete (id) {
|
||||
try {
|
||||
this.showLoad()
|
||||
console.log(id)
|
||||
const confirm = await modal('', msgData.delWaybillAddress)
|
||||
if (confirm) {
|
||||
// 删除地址
|
||||
await this.delAddressItem(id)
|
||||
uni.navigateBack({delta: 1})
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
errToast(e)
|
||||
} finally {
|
||||
this.hideLoad()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './edit-address.scss';
|
||||
</style>
|
||||
30
src/pagesAddress/input-label/input-label.scss
Normal file
30
src/pagesAddress/input-label/input-label.scss
Normal file
@@ -0,0 +1,30 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.input-label {
|
||||
@extend %flex-left;
|
||||
min-height: 100rpx;
|
||||
@extend %pdtb;
|
||||
box-sizing: border-box;
|
||||
.label {
|
||||
width: 160rpx;
|
||||
flex: none;
|
||||
font-size: 30rpx;
|
||||
color: $text1;
|
||||
}
|
||||
.input, .isText {
|
||||
flex: auto;
|
||||
font-size: 30rpx;
|
||||
color: $text1;
|
||||
}
|
||||
.placeholder {
|
||||
color: $info;
|
||||
}
|
||||
.icon-right-aw {
|
||||
flex: none;
|
||||
@extend %icon-aw-right-slim;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
@extend %bg-no-repeat-center;
|
||||
@extend %bg-size-100;
|
||||
}
|
||||
}
|
||||
81
src/pagesAddress/input-label/input-lebel.vue
Normal file
81
src/pagesAddress/input-label/input-lebel.vue
Normal file
@@ -0,0 +1,81 @@
|
||||
<template>
|
||||
<div class="input-label">
|
||||
<div class="label">{{label}}</div>
|
||||
<input
|
||||
v-if="!isText"
|
||||
class="input"
|
||||
:type="type"
|
||||
placeholder-class="placeholder"
|
||||
:placeholder="placeholder"
|
||||
@input="handleInput"
|
||||
:maxlength="maxlength"
|
||||
:disabled="disabled"
|
||||
:value="currentValue"
|
||||
>
|
||||
<div v-if="isText" :class="{
|
||||
'isText': true,
|
||||
'placeholder': !currentValue
|
||||
}">{{currentValue || placeholder}}</div>
|
||||
<div class="icon-right-aw" v-if="suffix"></div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default: 'text'
|
||||
},
|
||||
placeholder: {
|
||||
type: String,
|
||||
default: '请填写'
|
||||
},
|
||||
maxlength: {
|
||||
type: Number,
|
||||
default: 140
|
||||
},
|
||||
disabled: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
suffix: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
isText: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
currentValue: this.value
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
this.currentValue = val
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleInput(e) {
|
||||
let value = e.target.value
|
||||
this.currentValue = value
|
||||
this.$emit('update:value',value)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import './input-label.scss';
|
||||
</style>
|
||||
95
src/pagesAddress/mine-address/index.vue
Normal file
95
src/pagesAddress/mine-address/index.vue
Normal file
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<div class="mine-address">
|
||||
<div class="mine-address-top">
|
||||
<WaybillAddress
|
||||
class="address-item"
|
||||
v-for="address in addressListFilter"
|
||||
:key="address.id"
|
||||
:address="address"
|
||||
@on-pick="handlePick"
|
||||
@on-edit="goEdit"
|
||||
:isManager="true"
|
||||
></WaybillAddress>
|
||||
</div>
|
||||
<div
|
||||
class="mine-address-bottom"
|
||||
@click="toCreateAddress"
|
||||
>
|
||||
新建收货地址
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapActions, mapGetters, mapMutations } from 'vuex'
|
||||
// import WaybillAddress from '@/components/addressCmp/waybill-address.vue'
|
||||
import WaybillAddress from '../addressCmp/waybill-address.vue'
|
||||
import { errToast,jumpPage } from '@/utils/uniapi.js'
|
||||
export default {
|
||||
// props: {
|
||||
// manager: {
|
||||
// type: Boolean,
|
||||
// default: false
|
||||
// }
|
||||
// },
|
||||
components: {
|
||||
WaybillAddress
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
isManager: false,
|
||||
addressListFilter: []
|
||||
}
|
||||
},
|
||||
async onShow() {
|
||||
try {
|
||||
await this.getAddressList()
|
||||
let arr = this.addressList || []
|
||||
this.addressListFilter = arr.filter(item => item.detailAddress !== '自提订单:详细地址')
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
errToast(e)
|
||||
}
|
||||
},
|
||||
onLoad(query) {
|
||||
let { isManager = false } = query
|
||||
this.isManager = isManager
|
||||
// console.log('isManager', isManager)
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
addressList: 'addressVue/addressList'
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
...mapActions({
|
||||
getAddressList: 'addressVue/getList'
|
||||
}),
|
||||
...mapMutations({
|
||||
storeWaybillAd: 'addressVue/storeWaybillAd'
|
||||
}),
|
||||
toCreateAddress() {
|
||||
jumpPage('navigateTo','/pagesAddress/create-address/index')
|
||||
},
|
||||
// 选择地址
|
||||
handlePick(address) {
|
||||
console.log(address)
|
||||
if (this.isManager) {
|
||||
|
||||
} else {
|
||||
// 存储地址
|
||||
this.storeWaybillAd([address])
|
||||
uni.navigateBack({ delta: 1 })
|
||||
}
|
||||
},
|
||||
// 跳转到编辑页面
|
||||
goEdit(address) {
|
||||
jumpPage('navigateTo',`/pagesAddress/edit-address/index?address=${encodeURIComponent(JSON.stringify(address))}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./mine-address.scss";
|
||||
</style>
|
||||
19
src/pagesAddress/mine-address/mine-address.scss
Normal file
19
src/pagesAddress/mine-address/mine-address.scss
Normal file
@@ -0,0 +1,19 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.mine-address {
|
||||
$bottomH: 100rpx;
|
||||
#{&}-top {
|
||||
height: calc(100vh - 100rpx);
|
||||
overflow-y: auto;
|
||||
box-sizing: border-box;
|
||||
border-top: 1rpx solid $border2;
|
||||
}
|
||||
#{&}-bottom {
|
||||
height: $bottomH;
|
||||
box-sizing: border-box;;
|
||||
background-color: $maincolor;
|
||||
color: white;
|
||||
@extend %flex-center;
|
||||
font-size: 36rpx;
|
||||
}
|
||||
}
|
||||
111
src/pagesAddress/pick-city/index.vue
Normal file
111
src/pagesAddress/pick-city/index.vue
Normal file
@@ -0,0 +1,111 @@
|
||||
<template>
|
||||
<div class="pick-city">
|
||||
<!-- 输入框 -->
|
||||
<div class="pick-city-search-input">
|
||||
<search-input placeholder="输入城市名进行搜索" :searchBtnShow="false" @on-change="keywordChange" :focus="false"></search-input>
|
||||
</div>
|
||||
<!-- 当前定位城市 -->
|
||||
<div class="content">
|
||||
<div class="address-label">
|
||||
<div class="icon-position"></div>
|
||||
<div class="label-text">当前定位城市<span class="span" @click="pickCity(location.city)">{{location.city}}</span></div>
|
||||
</div>
|
||||
<!-- 热门城市 -->
|
||||
<div class="hot-city">
|
||||
<div class="label-title">热门城市</div>
|
||||
<div class="city-list">
|
||||
<div v-for="city in hotCity" :key="city.id" class="list-item" @click="pickCity(city.name)">
|
||||
{{city.nickName}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 搜索城市 -->
|
||||
<div class="search-list">
|
||||
<div class="city-item" v-for="city in cityList" :key="city.id" @click="pickCity(city)">
|
||||
{{city.name}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- loading -->
|
||||
<ZyLoading></ZyLoading>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ZyLoading from '@/components/Loading/loading'
|
||||
import SearchInput from '@/components/commonCmp/search-input/search-input.vue'
|
||||
import {errToast} from '@/utils/uniapi.js'
|
||||
import { mapGetters } from 'vuex'
|
||||
|
||||
import apiAddress from '@/apis/address'
|
||||
import {hotCity} from "@/apis/config"
|
||||
import {store} from "@/store"
|
||||
export default {
|
||||
components: {
|
||||
ZyLoading, SearchInput
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
cityList: [], // 搜索历史
|
||||
hotCity: hotCity
|
||||
}
|
||||
},
|
||||
async created () {},
|
||||
onShow () {
|
||||
const historyCity = uni.getStorageSync('historyCity')
|
||||
this.cityList = historyCity ? JSON.parse(historyCity) : []
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
location: 'indexPage/myLocation'
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
async keywordChange (keyword) {
|
||||
this.cityList=[]
|
||||
keyword = keyword.trim()
|
||||
if (!keyword) return false
|
||||
this.showLoad()
|
||||
try {
|
||||
let province = await apiAddress.getCity({keyword:keyword,level:1}) // 省
|
||||
let city = await apiAddress.getCity({keyword:keyword,level:2}) // 市
|
||||
let area = await apiAddress.getCity({keyword:keyword,level:3}) // 区
|
||||
this.cityList = [...province, ...city, ...area]
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.cityList = []
|
||||
errToast(e)
|
||||
} finally {
|
||||
this.hideLoad()
|
||||
}
|
||||
// console.log(this.cityList)
|
||||
},
|
||||
pickCity (city) {
|
||||
if (typeof city === 'string') {
|
||||
store.commit('indexPage/changeCity', city)
|
||||
} else {
|
||||
store.commit('indexPage/changeCity', city.name)
|
||||
// 存储历史城市
|
||||
const historyCity = uni.getStorageSync('historyCity')
|
||||
const history = historyCity ? JSON.parse(historyCity) : []
|
||||
history.unshift(city)
|
||||
// 找到后面位置的相同ID移除
|
||||
// 去除重复
|
||||
const noRepeatHistory = []
|
||||
for (let i = 0; i < history.length; i++) {
|
||||
const cityItem = history[i]
|
||||
if (noRepeatHistory.find(item => item.code === cityItem.code)) continue
|
||||
else noRepeatHistory.push(cityItem)
|
||||
}
|
||||
if (noRepeatHistory.length > 10) history.pop()
|
||||
uni.setStorageSync('historyCity', JSON.stringify(noRepeatHistory))
|
||||
}
|
||||
uni.navigateBack({delta: 1})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./pick-city.scss";
|
||||
</style>
|
||||
68
src/pagesAddress/pick-city/pick-city.scss
Normal file
68
src/pagesAddress/pick-city/pick-city.scss
Normal file
@@ -0,0 +1,68 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.pick-city {
|
||||
#{&}-search-input {
|
||||
@extend %pdlr;
|
||||
box-sizing: border-box;
|
||||
height: 100rpx;
|
||||
border-bottom: 1rpx solid $border3;
|
||||
}
|
||||
.content {
|
||||
height: calc(100vh - 100rpx);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.address-label {
|
||||
@extend %flex-left;
|
||||
@extend %pd20;
|
||||
font-size: 30rpx;
|
||||
color: $text2;
|
||||
height: 60rpx;
|
||||
border-bottom: 1rpx solid $border3;
|
||||
.icon-position {
|
||||
@extend %icon-position-small-text2;
|
||||
@extend %bg-no-repeat-center;
|
||||
@extend %bg-size-100;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
flex: none;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.span {
|
||||
padding-left: 10rpx;
|
||||
font-weight: 600;
|
||||
color: $text1;
|
||||
}
|
||||
}
|
||||
.hot-city {
|
||||
@extend %pd20;
|
||||
.label-title {
|
||||
font-size: 28rpx;
|
||||
color: $text3;
|
||||
}
|
||||
.city-list {
|
||||
font-size: 28rpx;
|
||||
@extend %flex-between;
|
||||
flex-flow: row wrap;
|
||||
}
|
||||
.list-item {
|
||||
flex: none;
|
||||
@extend %flex-center;
|
||||
width: 160rpx;
|
||||
height: 70rpx;
|
||||
background-color: $border3;
|
||||
margin-top: 20rpx;
|
||||
color: $text1;
|
||||
border-radius: 10rpx;
|
||||
}
|
||||
}
|
||||
.search-list {
|
||||
@extend %pd20;
|
||||
.city-item {
|
||||
font-size: 32rpx;
|
||||
color: $text1;
|
||||
@extend %flex-left;
|
||||
border-bottom: 1rpx solid $border3;
|
||||
height: 100rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
67
src/pagesAddress/pick-store/index.vue
Normal file
67
src/pagesAddress/pick-store/index.vue
Normal file
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="pick-store">
|
||||
<div class="shop-item" :class="{'is-open': item.status === 1, 'is-here': item.storeID == storeID[0]}" @click="changeStore(item.storeID)" v-for="(item, index) in storeArr" :key="index">
|
||||
<div class="store-name">
|
||||
<div class="status">{{item.status === 1 ? '营业中' : '休息中'}}</div>
|
||||
<div class="name">{{item.name}}</div>
|
||||
</div>
|
||||
<div class="store-distance">距离{{item.distance}}m</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters } from "vuex";
|
||||
import {store} from "@/store";
|
||||
import apiStore from '@/apis/apiStore'
|
||||
import loginApi from '@/apis/login'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
storeArr: [],
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
storeMap:"indexPage/storeMap",
|
||||
storeID:"indexPage/storeID",
|
||||
brandID: 'indexPage/brandID',
|
||||
waybillSLG:"indexPage/waybillSLG",
|
||||
isLogin: "login/isLogin"
|
||||
}),
|
||||
},
|
||||
created() {
|
||||
// 重排序storeMap
|
||||
// console.log(this.storeMap);
|
||||
if (this.storeMap) {
|
||||
const arr = [];
|
||||
for (let key in this.storeMap) {
|
||||
arr[this.storeMap[key].index] = {
|
||||
...this.storeMap[key],
|
||||
storeID: +key,
|
||||
};
|
||||
}
|
||||
// 排除empty
|
||||
this.storeArr = arr.filter((item) => item);
|
||||
}
|
||||
// console.log("this.storeArr", this.storeArr);
|
||||
},
|
||||
methods: {
|
||||
async changeStore(storeID) {
|
||||
if(storeID === this.storeID[0]) return
|
||||
|
||||
store.commit('indexPage/changeStoreID', [+storeID]) // 改变当前门店id
|
||||
|
||||
uni.navigateBack({ delta: 1 });
|
||||
|
||||
await apiStore.getWayBillFeeMinus(storeID) // 获取该店铺的运营策略
|
||||
|
||||
if (this.isLogin) await loginApi.updateUserLastInfo(+storeID, this.brandID)
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./pick-store.scss";
|
||||
</style>
|
||||
44
src/pagesAddress/pick-store/pick-store.scss
Normal file
44
src/pagesAddress/pick-store/pick-store.scss
Normal file
@@ -0,0 +1,44 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.pick-store {
|
||||
.shop-item {
|
||||
font-size: 32rpx;
|
||||
border-bottom: 1rpx solid $border2;
|
||||
@extend %pd20;
|
||||
@extend %flex-between;
|
||||
height: 100rpx;
|
||||
box-sizing: border-box;
|
||||
margin: 0 20rpx;
|
||||
.name, .store-distance {
|
||||
color: $info;
|
||||
}
|
||||
.store-distance {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
.store-name {
|
||||
@extend %flex-left;
|
||||
.status {
|
||||
background-color: $text3;
|
||||
color: white;
|
||||
border-radius: 50rpx;
|
||||
font-size: 20rpx;
|
||||
padding: 5rpx 10rpx;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
}
|
||||
.is-here {
|
||||
background-color: rgba($maincolor, .1);
|
||||
border-top-left-radius: 20rpx;
|
||||
border-top-right-radius: 20rpx;
|
||||
}
|
||||
.is-open {
|
||||
.status {
|
||||
background-color: $maincolor;
|
||||
@extend %ani-bounceIn;
|
||||
}
|
||||
.name, .store-distance {
|
||||
color: $text1;
|
||||
}
|
||||
}
|
||||
}
|
||||
279
src/pagesAddress/position-address/index.vue
Normal file
279
src/pagesAddress/position-address/index.vue
Normal file
@@ -0,0 +1,279 @@
|
||||
<template>
|
||||
<div class="position-address">
|
||||
<!-- 顶部搜索 -->
|
||||
<div class="search-address">
|
||||
<div class="left">
|
||||
<div
|
||||
class="btn-city-pick"
|
||||
@click="toCityPick"
|
||||
>
|
||||
<div class="city-name">{{districtName ? districtName : cityChange}}</div>
|
||||
<div class="icon-arraw-bottom"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right">
|
||||
<search-input
|
||||
placeholder="请输入收货地址"
|
||||
:searchBtnShow="false"
|
||||
@on-change="keywordChange"
|
||||
:focus="false"
|
||||
></search-input>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 列表 -->
|
||||
<div
|
||||
class="near-address"
|
||||
v-if="nearPois.length > 0 && !keyword "
|
||||
>
|
||||
<!-- 我的收货地址 -->
|
||||
<div v-if="showMine && isLogin && isShowShop">
|
||||
<div
|
||||
class="address-label"
|
||||
v-if="addressList.length"
|
||||
>
|
||||
<div class="icon-home"></div>
|
||||
<div class="label-text">我的收货地址</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="item in addressListFilter"
|
||||
:key="item.id"
|
||||
@click="pickAddress(item)"
|
||||
>
|
||||
<!-- @click.native="pickAddress(item)" -->
|
||||
<AddressItem
|
||||
:title="item.address"
|
||||
:address="item.consigneeName + ' ' + item.consigneeMobile"
|
||||
:distance="item.distance"
|
||||
></AddressItem>
|
||||
</div>
|
||||
|
||||
<!-- #ifndef MP-TOUTIAO -->
|
||||
<!-- 新增地址 -->
|
||||
<div
|
||||
v-if="iSExistWeixinApp"
|
||||
class="add-newAddress"
|
||||
@click="toCreateAddress"
|
||||
>
|
||||
<div class="add">新增地址</div>
|
||||
<div class="right-aw"></div>
|
||||
</div>
|
||||
<!-- #endif -->
|
||||
|
||||
</div>
|
||||
|
||||
<!-- 附近地址 -->
|
||||
<div class="address-label">
|
||||
<div class="icon-position"></div>
|
||||
<div class="label-text">附近地址</div>
|
||||
</div>
|
||||
<div
|
||||
v-for="item in nearPois"
|
||||
:key="item.id"
|
||||
@click="pickAddress(item)"
|
||||
>
|
||||
<!-- @click.native="pickAddress(item)" -->
|
||||
<AddressItem
|
||||
:title="item.title"
|
||||
:address="item.address"
|
||||
:distance="item.distance"
|
||||
></AddressItem>
|
||||
</div>
|
||||
</div>
|
||||
<!-- 搜索地址 -->
|
||||
<div
|
||||
class="search-list"
|
||||
v-if="keyword"
|
||||
>
|
||||
<div
|
||||
v-for="item in searchPois"
|
||||
:key="item.id"
|
||||
@click="pickAddress(item)"
|
||||
>
|
||||
<!-- @click.native="pickAddress(item)" -->
|
||||
<AddressItem
|
||||
:title="item.title"
|
||||
:address="item.address"
|
||||
:distance="item.distance"
|
||||
></AddressItem>
|
||||
</div>
|
||||
</div>
|
||||
<!-- loading -->
|
||||
<ZyLoading></ZyLoading>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ZyLoading from '@/components/Loading/loading'
|
||||
import SearchInput from '@/components/commonCmp/search-input/search-input.vue'
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import { toast,errToast,jumpPage } from '@/utils/uniapi.js'
|
||||
import AddressItem from '../addressCmp/address-item.vue'
|
||||
import {getDistance} from '@/utils/index.js'
|
||||
import {store} from "@/store";
|
||||
import apiAddress from '@/apis/address'
|
||||
export default {
|
||||
components: {
|
||||
ZyLoading, SearchInput, AddressItem
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
keyword: '',
|
||||
nearPois: [],
|
||||
searchPois: [],
|
||||
choisePosition: false,
|
||||
showMine: true,
|
||||
type: '',
|
||||
curLat:0,
|
||||
curLng:0,
|
||||
addressListFilter: [],
|
||||
districtName:''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.curLat = this.location.lat
|
||||
this.curLng = this.location.lat
|
||||
},
|
||||
computed: {
|
||||
...mapGetters({
|
||||
location: 'indexPage/myLocation',
|
||||
vuexPois: 'indexPage/pois',
|
||||
cityChange: 'indexPage/cityChange',
|
||||
addressList: 'addressVue/addressList',
|
||||
isLogin: 'login/isLogin',
|
||||
isShowShop: "isShowShop",
|
||||
iSExistWeixinApp: "login/iSExistWeixinApp",
|
||||
})
|
||||
},
|
||||
onLoad(query) {
|
||||
if (this.addressList && this.addressList.length > 0) {
|
||||
this.addressList.sort(this.ArraySort('distance'))
|
||||
}
|
||||
this.choisePosition = query.choisePosition
|
||||
|
||||
this.districtName = query.districtName || ""
|
||||
if (query.showMine) {
|
||||
this.showMine = query.showMine && JSON.parse(query.showMine)
|
||||
}
|
||||
this.type = query.type
|
||||
},
|
||||
async created() {
|
||||
try {
|
||||
this.showLoad()
|
||||
this.addressListFilter = this.addressList.filter(item => item.detailAddress !== '自提订单:详细地址')
|
||||
let latitude = this.location.lat
|
||||
let longitude = this.location.lng
|
||||
|
||||
let pois = this.vuexPois && this.vuexPois.length > 0 ? this.vuexPois : (await apiAddress.posToCity({ latitude, longitude, extensions: 1 })).pois
|
||||
|
||||
this.nearPois = pois.map(item => ({
|
||||
id: item.id,
|
||||
title: item.name,
|
||||
address: item.address,
|
||||
location: {
|
||||
lat: item.location.split(',')[1],
|
||||
lng: item.location.split(',')[0]
|
||||
},
|
||||
distance: getDistance(item.location.split(',')[1],item.location.split(',')[0])
|
||||
}))
|
||||
this.nearPois.sort(this.ArraySort('distance'))
|
||||
|
||||
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.nearPois = []
|
||||
errToast(e)
|
||||
} finally {
|
||||
this.hideLoad()
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({
|
||||
storeWaybillAd: 'addressVue/storeWaybillAd',
|
||||
updateMapPick: 'waybill/updateMapPick'
|
||||
}),
|
||||
//新增地址
|
||||
toCreateAddress() {
|
||||
jumpPage('navigateTo','/pagesAddress/create-address/index')
|
||||
},
|
||||
async keywordChange(val) {
|
||||
try {
|
||||
this.keyword = val.trim()
|
||||
if (!this.keyword) return false
|
||||
this.searchPois = []
|
||||
let res = await apiAddress.getSuggestion(this.keyword, this.districtName ? this.districtName : this.cityChange)
|
||||
|
||||
res.pois.map((item)=>{
|
||||
this.searchPois.push({
|
||||
id: item.id,
|
||||
title: item.name,
|
||||
address: item.address,
|
||||
location: {
|
||||
lat: item.location.split(',')[1],
|
||||
lng: item.location.split(',')[0]
|
||||
},
|
||||
distance:getDistance(item.location.split(',')[1],item.location.split(',')[0])
|
||||
})
|
||||
})
|
||||
this.searchPois.sort(this.ArraySort('distance'))
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
this.searchPois = []
|
||||
errToast(e)
|
||||
}
|
||||
},
|
||||
|
||||
// 跳转到城市选择
|
||||
toCityPick() {
|
||||
if(!this.showMine) return toast('禁止选择城市')
|
||||
jumpPage('navigateTo','/pagesAddress/pick-city/index')
|
||||
},
|
||||
// 选择地址
|
||||
pickAddress(address) {
|
||||
console.log('选中一个地址信息',address)
|
||||
if (this.choisePosition) {
|
||||
// console.log(address)
|
||||
let reLocation = {}
|
||||
if (address.hasOwnProperty('location')) {
|
||||
// 其他地址
|
||||
reLocation.lat = address.location.lat
|
||||
reLocation.lng = address.location.lng
|
||||
reLocation.address = address.title
|
||||
} else {
|
||||
// 我的收货地址
|
||||
reLocation.lat = address.lat
|
||||
reLocation.lng = address.lng
|
||||
reLocation.address = address.address
|
||||
this.storeWaybillAd([address])
|
||||
}
|
||||
// 设置重新加载标识
|
||||
store.commit('indexPage/indexNeedReload', true) // 首页
|
||||
store.commit('goodPage/changeIsNeedReload', true) // 分类
|
||||
store.commit('cartPage/cartNeedReload', true) // 购物车
|
||||
|
||||
// 存储切换的坐标地址
|
||||
store.commit('indexPage/saveReLocation', reLocation)
|
||||
} else {
|
||||
if (this.type === 'waybill') {
|
||||
// 处理物流地址选择
|
||||
this.updateMapPick(address)
|
||||
} else {
|
||||
this.$store.commit('addressVue/setCurPickAddress', address)
|
||||
}
|
||||
}
|
||||
uni.navigateBack({ delta: 1 })
|
||||
},
|
||||
// 数组排序
|
||||
ArraySort(property){
|
||||
return function (a,b){
|
||||
let value1=a[property]
|
||||
let value2=b[property]
|
||||
return value1-value2
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./position-address.scss";
|
||||
</style>
|
||||
77
src/pagesAddress/position-address/position-address.scss
Normal file
77
src/pagesAddress/position-address/position-address.scss
Normal file
@@ -0,0 +1,77 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.position-address {
|
||||
.search-address {
|
||||
box-sizing: border-box;
|
||||
@extend %flex-center;
|
||||
@extend %pd20;
|
||||
height: 100rpx;
|
||||
// background: #ccc;
|
||||
border-bottom: 1rpx solid $border2;
|
||||
}
|
||||
.left {
|
||||
flex: none;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.right {
|
||||
flex: auto;
|
||||
}
|
||||
.btn-city-pick {
|
||||
@extend %flex-center;
|
||||
font-size: 30rpx;
|
||||
color: $text2;
|
||||
.icon-arraw-bottom {
|
||||
@extend %icon-aw-bottom;
|
||||
@extend %bg-no-repeat-center;
|
||||
width: 20rpx;
|
||||
height: 20rpx;
|
||||
@extend %bg-size-100;
|
||||
margin-left: 10rpx;
|
||||
}
|
||||
}
|
||||
.near-address, .search-list {
|
||||
height: calc(100vh - 100rpx);
|
||||
overflow-y: auto;
|
||||
}
|
||||
.add-newAddress{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin: 0 50rpx;
|
||||
padding: 16rpx 0;
|
||||
border-bottom: 1rpx solid #EBEEF5;
|
||||
.add{
|
||||
font-size: 28rpx;
|
||||
color: rgb(64, 158, 255);
|
||||
}
|
||||
.right-aw{
|
||||
flex: none;
|
||||
@extend %icon-aw-right-slim;
|
||||
width: 50rpx;
|
||||
height: 30rpx;
|
||||
background-position: right center;
|
||||
background-repeat: no-repeat;
|
||||
background-size: 30rpx;
|
||||
}
|
||||
}
|
||||
.address-label {
|
||||
@extend %flex-left;
|
||||
@extend %pd20;
|
||||
font-size: 28rpx;
|
||||
color: $text3;
|
||||
.icon-position, .icon-home {
|
||||
@extend %bg-no-repeat-center;
|
||||
@extend %bg-size-100;
|
||||
width: 30rpx;
|
||||
height: 30rpx;
|
||||
flex: none;
|
||||
margin-right: 10rpx;
|
||||
}
|
||||
.icon-position {
|
||||
@extend %icon-position-small;
|
||||
}
|
||||
.icon-home {
|
||||
@extend %icon-home;
|
||||
}
|
||||
}
|
||||
}
|
||||
12
src/pagesAddress/switch-label/switch-label.scss
Normal file
12
src/pagesAddress/switch-label/switch-label.scss
Normal file
@@ -0,0 +1,12 @@
|
||||
@import '@/assets/bundle.scss';
|
||||
|
||||
.switch-label {
|
||||
@extend %flex-left;
|
||||
height: 100rpx;
|
||||
.label {
|
||||
width: 240rpx;
|
||||
flex: none;
|
||||
font-size: 30rpx;
|
||||
color: $text1;
|
||||
}
|
||||
}
|
||||
53
src/pagesAddress/switch-label/switch-label.vue
Normal file
53
src/pagesAddress/switch-label/switch-label.vue
Normal file
@@ -0,0 +1,53 @@
|
||||
<template>
|
||||
<div class="switch-label">
|
||||
<div class="label">{{label}}</div>
|
||||
<y-switch
|
||||
v-model:value="currentValue"
|
||||
@on-change="onChange"
|
||||
:size="size"
|
||||
></y-switch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import YSwitch from '../Switch/switch'
|
||||
export default {
|
||||
components: {
|
||||
YSwitch
|
||||
},
|
||||
props: {
|
||||
label: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
value: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: '50'
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
currentValue: this.value
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
value (val) {
|
||||
this.currentValue = val
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onChange (val) {
|
||||
this.currentValue = val
|
||||
this.$emit('update:value',val)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import "./switch-label.scss";
|
||||
</style>
|
||||
Reference in New Issue
Block a user