master
王文杰 8 months ago
parent d0d49a26e1
commit 6b5422fc98

@ -12,6 +12,12 @@
} }
}, },
"pages": [ "pages": [
{
"path": "pages/booking/booking",
"style": {
"navigationBarTitleText": "一键预约"
}
},
{ {
"path": "pages/login/login", "path": "pages/login/login",
"style": { "style": {
@ -32,12 +38,7 @@
"navigationBarTitleText": "我的" "navigationBarTitleText": "我的"
} }
}, },
{
"path": "pages/booking/booking",
"style": {
"navigationBarTitleText": "一键预约"
}
},
{ {
"path": "pages/booking/booking-success", "path": "pages/booking/booking-success",
"style": { "style": {

@ -5,7 +5,9 @@ import TimePopup from './components/timePopup.vue'
import AddressPopup from './components/addressPopup.vue' import AddressPopup from './components/addressPopup.vue'
import SitePopup from './components/sitePopup.vue' import SitePopup from './components/sitePopup.vue'
import { postBookingAPI } from '@/services/booking' import { postBookingAPI } from '@/services/booking'
import AddressPanel from './components/AddressPanel.vue'
import TimePanel from './components/TimePanel.vue'
import SitePanel from './components/SitePanel.vue'
const activeMenuKey = ref(0) const activeMenuKey = ref(0)
const activeWeightKey = ref(0) const activeWeightKey = ref(0)
@ -18,9 +20,9 @@ const isShowAddressPop = ref(false)
const isShowSitePop = ref(false) const isShowSitePop = ref(false)
// //
const recycleAddress = ref('') const recycleAddress = ref('请选择回收地址')
const appointmentTime = ref('') const appointmentTime = ref('请选择回收时间')
const siteLabel = ref('') const siteLabel = ref('请选择回收站点')
const recycleStationId = ref('521632060801030597') const recycleStationId = ref('521632060801030597')
// //
@ -196,17 +198,37 @@ const handleBooking = async () => {
} }
} }
// uni-ui ref
const popup = ref<{
open: (type?: UniHelper.UniPopupType) => void
close: () => void
}>()
//
const popupName = ref<'address' | 'time' | 'site'>()
const openPopup = (name: typeof popupName.value) => {
//
popupName.value = name
popup.value?.open()
}
const handlePopClose = (item) => {
if (popupName.value == 'time') {
appointmentTime.value = item
}
if (popupName.value == 'address') {
recycleAddress.value = item.location
}
if (popupName.value == 'site') {
recycleAddress.value = item.name
}
popup.value?.close()
}
</script> </script>
<template> <template>
<view class="booking"> <view class="booking">
<view class="module section-map"> <view class="module section-map">
<map <map id="map" class="map" show-location :latitude="latitude" :longitude="longitude"></map>
id="map"
class="map"
show-location
:latitude="latitude"
:longitude="longitude"
></map>
</view> </view>
<!-- <view class="module lei"> <!-- <view class="module lei">
<view class="module-title">回收品类</view> <view class="module-title">回收品类</view>
@ -223,11 +245,22 @@ const handleBooking = async () => {
</view> --> </view> -->
<view class="module info"> <view class="module info">
<view class="module-title">取件信息</view> <view class="module-title">取件信息</view>
<view class="list"> <!-- 操作面板 -->
<button hover-class="none" class="item arrow" @click="openTimePop"> {{appointmentTime}}</button> <view class="action">
<button hover-class="none" class="item arrow" @click="openAddressPop">{{recycleAddress}}</button> <view @tap="openPopup('time')" class="item arrow">
<button hover-class="none" class="item arrow" @click="openSitePop">{{siteLabel}}</button> <text class="label">时间</text>
<text class="text ellipsis"> {{ appointmentTime }} </text>
</view>
<view @tap="openPopup('address')" class="item arrow">
<text class="label">地址</text>
<text class="text ellipsis"> {{ recycleAddress }} </text>
</view>
<view @tap="openPopup('site')" class="item arrow">
<text class="label">站点</text>
<text class="text ellipsis">{{ siteLabel }}</text>
</view>
</view> </view>
<!-- <view class="weight"> <!-- <view class="weight">
<view class="weight-title" <view class="weight-title"
>请选择预估重量<span class="desc">预估仅供参考以实际重量为准</span></view >请选择预估重量<span class="desc">预估仅供参考以实际重量为准</span></view
@ -244,9 +277,13 @@ const handleBooking = async () => {
</view> </view>
</view> --> </view> -->
</view> </view>
<time-popup :props-time="appointmentTime" v-if="isShowTimePop" @change="handleTimePopChange" />
<address-popup v-if="isShowAddressPop" @change="handleAddressPopChange" /> <!-- uni-ui 弹出层 -->
<site-popup v-if="isShowSitePop" @change="handleSitePopChange" /> <uni-popup ref="popup" type="bottom" background-color="#fff">
<AddressPanel v-if="popupName === 'address'" @close="handlePopClose" />
<TimePanel v-if="popupName === 'time'" @close="handlePopClose" />
<SitePanel v-if="popupName === 'site'" @close="handlePopClose" />
</uni-popup>
<view :class="[!isBooking ? 'disabled' : '', 'submit']" @click="handleBooking"></view> <view :class="[!isBooking ? 'disabled' : '', 'submit']" @click="handleBooking"></view>
<!-- 底部占位空盒子 --> <!-- 底部占位空盒子 -->
@ -375,6 +412,44 @@ page {
} }
} }
} }
.action {
padding-left: 20rpx;
.item {
height: 90rpx;
padding-right: 60rpx;
border-bottom: 1rpx solid #eaeaea;
font-size: 26rpx;
color: #333;
position: relative;
display: flex;
align-items: center;
&:last-child {
border-bottom: 0 none;
}
}
.label {
width: 100rpx;
color: #898b94;
margin: 0 16rpx 0 10rpx;
}
.text {
flex: 1;
-webkit-line-clamp: 1;
}
.arrow {
&::after {
position: absolute;
top: 50%;
right: 30rpx;
content: '\e6c2';
color: #ccc;
font-family: 'erabbit' !important;
font-size: 32rpx;
transform: translateY(-50%);
}
}
}
.submit { .submit {
display: flex; display: flex;
flex-direction: column; flex-direction: column;

@ -0,0 +1,170 @@
<script setup lang="ts">
import { ref, reactive, toRaw } from 'vue'
import { onReady } from '@dcloudio/uni-app'
//
const emit = defineEmits<{
(event: 'close'): void
}>()
const handleClose = () => {
const item = addressList.value[activeIndex.value]
emit('close', toRaw(item))
}
//
const addressList = ref<any[]>([])
const activeIndex = ref(0)
const handleChange = (e) => {
activeIndex.value = e.currentTarget.dataset.val
}
const getMemberAddressData = async () => {
const res = await new Promise((resolve, reject) => {
setTimeout(() => {
const dataList = [
{
id: '1',
name: '李明 13824686868',
location: '北京市顺义区后沙峪地区安平北街6号院1',
},
{
id: '2',
name: '李明2 13824686868',
location: '北京市顺义区后沙峪地区安平北街6号院2',
},
{
id: '3',
name: '李明3 13824686868',
location: '北京市顺义区后沙峪地区安平北街6号院3',
},
]
resolve(dataList)
}, 0);
})
addressList.value = res
}
//
onReady(async () => {
getMemberAddressData()
})
</script>
<template>
<view class="address-panel">
<!-- 关闭按钮 -->
<text class="close icon-close" @click="handleClose"></text>
<!-- 标题 -->
<view class="title">配送至</view>
<!-- 内容 -->
<view class="content">
<view
class="item"
v-for="(item, index) in addressList"
:key="item.id"
:data-val="index"
@click="handleChange"
>
<view class="user">{{ item.name }}</view>
<view class="address">{{ item.location }}</view>
<text :class="[activeIndex == index ? 'icon-checked' : 'icon-ring', 'icon']"></text>
</view>
</view>
<view class="footer">
<view class="button primary">
<navigator hover-class="none" url="/pagesMember/address-form/address-form">
新建地址
</navigator>
</view>
<view v-if="false" class="button primary"></view>
</view>
</view>
</template>
<style lang="scss">
.address-panel {
padding: 0 30rpx;
border-radius: 10rpx 10rpx 0 0;
position: relative;
background-color: #fff;
}
.title {
line-height: 1;
padding: 40rpx 0;
text-align: center;
font-size: 32rpx;
font-weight: normal;
border-bottom: 1rpx solid #ddd;
color: #444;
}
.close {
position: absolute;
right: 24rpx;
top: 24rpx;
}
.content {
min-height: 300rpx;
max-height: 540rpx;
overflow: auto;
padding: 20rpx;
.item {
padding: 30rpx 50rpx 30rpx 60rpx;
background-size: 40rpx;
background-repeat: no-repeat;
background-position: 0 center;
background-image: url(/static/images/location.png);
position: relative;
}
.icon {
color: #999;
font-size: 40rpx;
transform: translateY(-50%);
position: absolute;
top: 50%;
right: 0;
}
.icon-checked {
color: #3775F6;
}
.icon-ring {
color: #444;
}
.user {
font-size: 28rpx;
color: #444;
font-weight: 500;
}
.address {
font-size: 26rpx;
color: #666;
}
}
.footer {
display: flex;
justify-content: space-between;
padding: 20rpx 0 40rpx;
font-size: 28rpx;
color: #444;
.button {
flex: 1;
height: 72rpx;
text-align: center;
line-height: 72rpx;
margin: 0 20rpx;
color: #fff;
border-radius: 72rpx;
}
.primary {
color: #fff;
background-color: #3775F6;
}
.secondary {
background-color: #ffa868;
}
}
</style>

@ -22,8 +22,14 @@ const dataList = ref<any[]>([])
const isLoading = ref(false) const isLoading = ref(false)
// //
const isFinish = ref(false) const isFinish = ref(false)
// //
const emit = defineEmits(['change']) const emit = defineEmits<{
(event: 'close'): void
}>()
const handleClose = () => {
emit('close', siteSelected.value)
}
const getDataList = async () => { const getDataList = async () => {
// 退 // 退
@ -49,13 +55,6 @@ const getDataList = async () => {
isFinish.value = true isFinish.value = true
} }
} }
const show = async ()=> {
await getDataList()
sitePopup.value?.open?.()
}
const hide = ()=> {
emit('change', siteSelected.value)
}
const isTriggered = ref(false) const isTriggered = ref(false)
// //
@ -74,21 +73,19 @@ const onRefresherrefresh = async () => {
const handleSelected = (e) => { const handleSelected = (e) => {
const item = e.target.dataset.val const item = e.target.dataset.val
siteSelected.value = item siteSelected.value = item
hide()
} }
// //
onReady(async () => { onReady(async () => {
show()
}) })
</script> </script>
<template> <template>
<uni-popup class="time-popup" :is-mask-click="false" ref="sitePopup" type="bottom" background-color="#fff"> <view class="time-popup" :is-mask-click="false">
<view class="popup-root"> <view class="popup-root">
<view class="title"> <view class="title">
<view class="text">回收站点</view> <view class="text">回收站点</view>
<view class="close" @click="hide">X</view> <view class="close" @click="handleClose">X</view>
</view> </view>
<!-- 地址列表 --> <!-- 地址列表 -->
<scroll-view <scroll-view
@ -98,12 +95,12 @@ onReady(async () => {
:refresher-triggered="isTriggered" :refresher-triggered="isTriggered"
@refresherrefresh="onRefresherrefresh" @refresherrefresh="onRefresherrefresh"
@scrolltolower="getDataList" @scrolltolower="getDataList"
@click="handleSelected" @click="handleSelected"
> >
<siteItem class="item" :site-val="item" :data-val="item" v-for="item in dataList" :key="item.id" /> <siteItem class="item" :site-val="item" :data-val="item" v-for="item in dataList" :key="item.id" />
</scroll-view> </scroll-view>
</view> </view>
</uni-popup> </view>
</template> </template>
<style lang="scss"> <style lang="scss">
@ -155,6 +152,8 @@ onReady(async () => {
.scroll-view { .scroll-view {
padding-top: 20rpx; padding-top: 20rpx;
max-height: 600rpx;
overflow-y: auto;
} }
} }

@ -3,12 +3,15 @@ import { ref, reactive } from 'vue'
import { onReady } from '@dcloudio/uni-app' import { onReady } from '@dcloudio/uni-app'
const popup = ref<UniHelper.UniPopupInstance>() const popup = ref<UniHelper.UniPopupInstance>()
// //
const emit = defineEmits(['change'])
const props = defineProps<{ //
propsTime: string const emit = defineEmits<{
(event: 'close'): void
}>() }>()
const handleClose = () => {
emit('close', sendTime.value)
}
const jmhDay = ref('') const jmhDay = ref('')
const sendTime = ref('') const sendTime = ref('')
@ -65,18 +68,18 @@ const getWeekDate = (day) => {
return week; return week;
} }
const selectRDate = (item) => { const selectRDate = (item) => {
if(item.disabled){ if (item.disabled) {
return; return
} }
sRightDate.value = item.time; sRightDate.value = item.time
sendTime.value = sLDate.value +' ' +item.time; sendTime.value = sLDate.value + ' ' + item.time
popup.value?.close?.() popup.value?.close?.()
emit('change', sendTime.value) emit('close', sendTime.value)
} }
const selectLDate = (val) => { const selectLDate = (val) => {
console.log(val); console.log(val);
if(val!=1){ if (val != 1) {
sLDate.value = val.formatDate; sLDate.value = val.formatDate
} }
let t = [ let t = [
{ disabled: false, time: '11:00-13:00', id: 1 }, { disabled: false, time: '11:00-13:00', id: 1 },
@ -87,7 +90,7 @@ const selectLDate = (val) => {
{ disabled: false, time: '21:00-23:00', id: 6 }, { disabled: false, time: '21:00-23:00', id: 6 },
] ]
if(val.desc=='今天' || val==1) { if (val.desc == '今天' || val == 1) {
const nowH = new Date().getHours() const nowH = new Date().getHours()
console.log(nowH) console.log(nowH)
if (nowH <= 10) { if (nowH <= 10) {
@ -117,7 +120,16 @@ const selectLDate = (val) => {
t[3].disabled = true t[3].disabled = true
t[4].disabled = true t[4].disabled = true
timeList = t timeList = t
} else if (nowH <= 21) {
t[0].disabled = true
t[1].disabled = true
t[2].disabled = true
t[3].disabled = true
t[4].disabled = true
t[5].disabled = true
timeList = t
} }
console.log('最终的时间列表', timeList) console.log('最终的时间列表', timeList)
} else { } else {
timeList = t timeList = t
@ -131,43 +143,37 @@ onReady(async () => {
popup.value?.open?.() popup.value?.open?.()
}) })
const hide = () => {
popup.value?.close?.()
}
</script> </script>
<template> <template>
<uni-popup ref="popup" type="bottom"> <view class="pBoxUp">
<view class="pBoxUp"> <view class="textCenter f32 psTitle border-bottom">请选择取件时间</view>
<view class="textCenter f32 psTitle border-bottom">请选择取件时间</view> <view class="shopPopup bgff justify-between default-flex">
<view class="shopPopup bgff justify-between default-flex"> <view class="f30 t666 lBox">
<view class="f30 t666 lBox"> <view
<view v-for="(item, index) in jmhDay"
v-for="(item, index) in jmhDay" @click="selectLDate(item)"
@click="selectLDate(item)" :class="sLDate == item.formatDate ? 'ed' : ''"
:class="sLDate == item.formatDate ? 'ed' : ''" class="boxLDate"
class="boxLDate" :key="index"
:key="index" >{{ item.desc }}({{ item.name }})
>{{ item.desc }}({{ item.name }}) </view>
</view> </view>
<view>
<view
v-for="(item, index) in timeList"
@click="selectRDate(item)"
:class="[sRightDate == item.time ? 'ed' : '', item.disabled ? 'disabled' : '']"
:key="index"
class="rBox">
{{ item.time }}{{ item.disabled ? ' (超出回收时间)' : '' }}
</view> </view>
<view> <view v-if="!timeList.length" class="empty f28 text-center" style="color: #999; margin-top: 40rpx">
<view 今天没有时间了,看看明天吧
v-for="(item, index) in timeList"
@click="selectRDate(item)"
:class="[sRightDate == item.time ? 'ed' : '', item.disabled ? 'disabled' : '']"
:key="index"
class="rBox"
>
{{ item.time }}{{ item.disabled ? ' (超出回收时间)' : '' }}
</view>
<view v-if="!timeList.length" class="empty f28 text-center" style="color: #999; margin-top: 40rpx">
今天没有时间了,看看明天吧
</view>
</view> </view>
</view> </view>
<view class="cancelButton" @click="hide()"></view>
</view> </view>
</uni-popup> <view class="cancelButton" @click="handleClose"></view>
</view>
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.pBoxUp { .pBoxUp {

@ -1,231 +0,0 @@
<script setup lang="ts">
import { ref, reactive } from 'vue'
import { onReady } from '@dcloudio/uni-app'
const addressPopup = ref<UniHelper.UniPopupInstance>()
//
const addressList = ref<any[]>([])
//
const emit = defineEmits(['change'])
const getMemberAddressData = async () => {
const res = await new Promise((resolve, reject) => {
setTimeout(() => {
const dataList = [
{
'id': '1764537730823360514',
'receiver': '656',
'contact': '1',
'provinceCode': '120000',
'cityCode': '120100',
'countyCode': '120101',
'address': '22',
'isDefault': 1,
'fullLocation': '天津市 天津市 和平区',
'postalCode': null,
'addressTags': null
},
]
resolve(dataList)
}, 0);
})
addressList.value = res
}
const show = ()=> {
addressPopup.value?.open?.()
getMemberAddressData()
}
const hide = ()=> {
addressPopup.value?.close?.()
const str = addressList.value[0].fullLocation
emit('change', str)
}
//
onReady(async () => {
show()
})
</script>
<template>
<uni-popup class="time-popup" :is-mask-click="false" ref="addressPopup" type="bottom" background-color="#fff">
<view class="popup-root">
<view class="title">
<view class="text">取件地址</view>
<view class="close" @click="hide">X</view>
</view>
<!-- 地址列表 -->
<scroll-view enable-back-to-top class="scroll-view" scroll-y>
<view v-if="addressList.length" class="address">
<uni-swipe-action class="address-list">
<!-- 收货地址项 -->
<uni-swipe-action-item class="item" v-for="item in addressList" :key="item.id">
<view class="item-content" @tap="onChangeAddress(item)">
<view class="user">
{{ item.receiver }}
<text class="contact">{{ item.contact }}</text>
<text v-if="item.isDefault" class="badge"></text>
</view>
<view class="locate">{{ item.fullLocation }} {{ item.address }}</view>
<!-- H5 端需添加 .prevent 阻止链接的默认行为 -->
<navigator
class="edit"
hover-class="none"
:url="`/pagesMember/address-form/address-form?id=${item.id}`"
@tap.stop="() => {}"
@tap.prevent="() => {}"
>
修改
</navigator>
</view>
<!-- 右侧插槽 -->
<template #right>
<button @tap="onDeleteAddress(item.id)" class="delete-button">删除</button>
</template>
</uni-swipe-action-item>
</uni-swipe-action>
</view>
<view v-else class="blank">暂无收货地址</view>
</scroll-view>
<!-- 添加按钮 -->
<view class="add-btn">
<navigator hover-class="none" url="/pagesMember/address-form/address-form">
新建地址
</navigator>
</view>
</view>
</uni-popup>
</template>
<style lang="scss">
.time-popup {
padding: 0 30rpx;
border-radius: 10rpx 10rpx 0 0;
position: relative;
background-color: #fff;
.title {
line-height: 1;
padding: 40rpx;
font-size: 32rpx;
font-weight: normal;
border-bottom: 1rpx solid #ddd;
color: #444;
.close {
position: absolute;
right: 24rpx;
top: 40rpx;
height: 60rpx;
width: 60rpx;
text-align: center;
}
}
page {
height: 100%;
overflow: hidden;
}
/* 删除按钮 */
.delete-button {
display: flex;
justify-content: center;
align-items: center;
width: 50px;
height: 100%;
font-size: 28rpx;
color: #fff;
border-radius: 0;
padding: 0;
background-color: #cf4444;
}
.viewport {
display: flex;
flex-direction: column;
height: 100%;
background-color: #f4f4f4;
.scroll-view {
padding-top: 20rpx;
}
}
.address {
padding: 0 20rpx;
margin: 0 20rpx;
border-radius: 10rpx;
background-color: #fff;
.item-content {
line-height: 1;
padding: 40rpx 10rpx 38rpx;
border-bottom: 1rpx solid #ddd;
position: relative;
.edit {
position: absolute;
top: 36rpx;
right: 30rpx;
padding: 2rpx 0 2rpx 20rpx;
border-left: 1rpx solid #666;
font-size: 26rpx;
color: #666;
line-height: 1;
}
}
.item:last-child .item-content {
border: none;
}
.user {
font-size: 28rpx;
margin-bottom: 20rpx;
color: #333;
.contact {
color: #666;
}
.badge {
display: inline-block;
padding: 4rpx 10rpx 2rpx 14rpx;
margin: 2rpx 0 0 10rpx;
font-size: 26rpx;
color: #3775F6;
border-radius: 6rpx;
border: 1rpx solid #3775F6;
}
}
.locate {
line-height: 1.6;
font-size: 26rpx;
color: #333;
}
}
.blank {
margin-top: 300rpx;
text-align: center;
font-size: 32rpx;
color: #888;
}
.add-btn {
height: 80rpx;
text-align: center;
line-height: 80rpx;
margin: 30rpx 20rpx;
color: #fff;
border-radius: 80rpx;
font-size: 30rpx;
background-color: #3775F6;
}
}
</style>

@ -24,12 +24,6 @@ const bannerList = ref<BannerItem[]>([
hrefUrl: '1019000', hrefUrl: '1019000',
type: '1', type: '1',
}, },
{
hrefUrl: '1005000',
id: '3',
imgUrl: '/static/images/banner3.jpg',
type: '1',
},
]) ])
// //
const categoryList = ref<CategoryItem[]>([ const categoryList = ref<CategoryItem[]>([

@ -15,12 +15,6 @@ const bannerList = [
hrefUrl: '1019000', hrefUrl: '1019000',
type: '1', type: '1',
}, },
{
hrefUrl: '1005000',
id: '3',
imgUrl: '/static/images/banner3.jpg',
type: '1',
},
] ]
const leiList = [ const leiList = [
{ {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 467 KiB

@ -11,8 +11,8 @@
* 4. token * 4. token
*/ */
import { useMemberStore } from '@/stores' import { useMemberStore } from '@/stores'
const baseURL = 'http://192.168.0.166:8808/api' // const baseURL = 'http://192.168.0.166:8808/api'
// const baseURL = 'http://222.71.165.188:8808/api' const baseURL = 'http://222.71.165.188:8808/api'
// 添加拦截器 // 添加拦截器
const httpInterceptor = { const httpInterceptor = {
// 拦截前触发 // 拦截前触发

Loading…
Cancel
Save