Zlpt_Portal_h5/src/pages/cart/index.vue

753 lines
24 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<!-- 预约车 -->
<keep-alive>
<view class="h5-container cart-container">
<view class="nav-header">
<view style="display: flex; align-items: center">
<van-icon name="arrow-left" @click="onClickLeft()" />
<van-image height="1rem" width="3rem" :src="cartImg" />
<text> ({{ amountNum }}) </text>
</view>
<van-button
style="padding: 10px 20px"
type="primary"
size="mini"
class="primary-lease"
@click="onClickManage"
>
{{ isCartManage ? '退出管理' : '管理' }}
</van-button>
</view>
<scroll-view scroll-y :style="{ paddingBottom: actionBarHeight + 'px' }">
<view class="order-set" v-for="(item, index) in cartList" :key="index">
<van-row>
<van-col span="2">
<van-checkbox
v-model="item.isChecked"
icon-size="16px"
@change="onChangeAllCheckbox($event, index)"
/>
</van-col>
<van-col span="12">
<view class="company-box">
<van-image
fit="cover"
width="1.5rem"
height="1.2rem"
:src="companyImg"
/>
<view class="company-name">
<view> {{ item.companyPersonPhoneKey.companyName }} </view>
<van-image fit="cover" height="0.5rem" :src="companyBg" />
</view>
</view>
</van-col>
<van-col span="10" class="contacts">
<view> 联系人: {{ item.companyPersonPhoneKey.person }} </view>
<view>
{{ item.companyPersonPhoneKey.personPhone }}
</view>
</van-col>
</van-row>
<view v-for="(goods, i) in item.devInfoVoList" :key="i">
<van-row>
<van-col span="2">
<van-checkbox
v-model="goods.isChecked"
icon-size="16px"
@click="onChangeCheckbox($event, index)"
/>
</van-col>
<van-col span="22">
<view class="items-info">
<van-image
fit="cover"
height="4rem"
width="4rem"
:src="goods.picUrl"
/>
<view class="info">
<view style="color: #000">{{ goods.deviceName }}</view>
<view>装备编号:{{ goods.code }}</view>
<view>装备型号:{{ goods.typeName }}</view>
<view
style="
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
"
>
<text style="color: var(--van-submit-bar-price-color)">
租赁金额:¥{{ goods.dayLeasePrice }}/天
</text>
<van-stepper
button-size="16"
:min="goods.num"
:max="goods.deviceCount"
v-model="goods.num"
v-if="!isCartManage"
/>
<van-icon
v-else
name="delete"
size="18"
@click="onDeleteCartGoods(goods.id)"
color="var(--van-submit-bar-price-color)"
/>
</view>
<view class="items-info">
{{
goods.rentBeginTime
? goods.rentBeginTime
: '开始日期'
}}
<van-image
width="1rem"
height="1rem"
:src="dateIcon"
style="margin: 0 6px"
@click="onSelectTime(1, index, i)"
/>
{{ goods.rentEndTime ? goods.rentEndTime : '结束日期' }}
<van-image
width="1rem"
height="1rem"
:src="dateIcon"
style="margin: 0 6px"
@click="onSelectTime(2, index, i)"
/>
</view>
<view>
租赁天数:
{{ goods.days }}
</view>
</view>
</view>
</van-col>
</van-row>
<view
style="
margin-top: 14px;
display: flex;
justify-content: flex-end;
height: 30px;
line-height: 30px;
"
>
<text
style="font-weight: bold; color: var(--van-submit-bar-price-color)"
>
{{ goods.num * goods.dayLeasePrice * goods.days }}
</text>
</view>
</view>
<van-row style="padding: 10px 0; margin-top: 10px; border-top: 1px solid #ccc">
<van-checkbox v-model="item.protocolChecked" icon-size="16px">
我已阅读并同意
<text class="protocol" @click.stop="onViewProtocol(item, index)">
《{{ item.companyPersonPhoneKey.companyName }}公司协议》
</text>
</van-checkbox>
</van-row>
</view>
</scroll-view>
<van-popup v-model:show="showBottom" position="bottom" :destroy-on-close="true">
<van-date-picker
v-model="leaseTime"
@confirm="onConfirm"
@cancel="onCancel"
:min-date="minDate"
:max-date="maxDate"
title="选择日期"
/>
</van-popup>
<van-popup
v-model:show="showBottomAddress"
position="bottom"
:style="{ height: '50%' }"
>
<van-address-list
v-model="chosenAddressId"
:list="addressList"
@click-item="onClickAddress"
@add="onAddAddress"
class="primary-lease"
/>
</van-popup>
<van-submit-bar
button-color="#00377a"
button-text="提交"
:price="totalPrice"
@submit="onSubmitOrder"
v-if="!isCartManage"
>
<template #default>
<view class="amount"> 共计 {{ amountDevice }} 件装备 </view>
</template>
<template #tip>
<text @click="onClickLink">
{{ address.length === 0 ? '请选择收货地址' : `收货地址:${address}` }}
</text>
</template>
</van-submit-bar>
<van-submit-bar
button-color="#00377a"
button-text="删除"
@submit="onDeleteCart"
v-if="isCartManage"
>
<template #default>
<van-checkbox v-model="checkedAll" @change="onChangeDelete">全选</van-checkbox>
</template>
</van-submit-bar>
</view>
</keep-alive>
</template>
<script setup>
import companyImg from '@/static/goods/company-img.png'
import companyBg from '@/static/goods/company-bg.png'
import cartImg from '@/static/cart/cart.png'
import dateIcon from '@/static/goods/date-icon.png'
import { computed, nextTick, ref } from 'vue'
import { onHide, onLoad, onShow } from '@dcloudio/uni-app'
import {
submitBookCarAPI,
deleteBookCarAPI,
getAddressListAPI,
getBookCarDetailsAPI,
deleteBookCarByIdsAPI,
getBookCarAgreementAPI,
} from '@/services/cart/index.js'
import { useMemberStore } from '@/stores/index.js'
import moment from 'moment'
const cartList = ref([])
const showBottom = ref(false)
const showBottomAddress = ref(false)
const minDate = new Date(moment().format('YYYY'), moment().format('MM') - 1, moment().format('DD'))
const maxDate = new Date(moment().format('YYYY') * 1 + 100, 12, 31)
const timeType = ref(0)
const activeIndex = ref(0)
const goodsIndex = ref(0)
const leaseTime = ref()
const address = ref('')
const actionBarHeight = ref()
const chosenAddressId = ref()
const addressList = ref([])
const isCartManage = ref(false)
const checkedAll = ref(false)
const memberStore = useMemberStore()
const onClickLeft = () => {
uni.removeStorageSync('myCartList')
uni.showTabBar()
uni.switchTab({
url: '/pages/index/index',
})
}
const onSubmitOrder = async () => {
if (amountDevice.value < 1) {
showFailToast('请选择装备')
return
}
let isDays = false
try {
amountDeviceList.value.forEach((e) => {
if (e.days < 1) {
showFailToast('有装备租期未选择或租期为0请重新选择后再提交')
isDays = true
throw new Error()
}
})
} catch (error) {}
if (isDays) return
let isRead = false
try {
cartList.value.forEach((e) => {
const isSelect = e.devInfoVoList.some((j) => j.isChecked === true)
if (isSelect && !e.protocolChecked) {
showFailToast('请阅读公司合同')
isRead = true
throw new Error()
}
})
} catch (error) {}
if (isRead) return
if (address.value.length == 0) {
showFailToast('请选择收货地址')
return
}
// 组装参数
const detailsList = amountDeviceList.value.map((e) => {
return {
maId: e.maId,
id: e.id,
rentBeginTime: e.rentBeginTime + ' ' + '00:00:00',
rentEndTime: e.rentEndTime + ' ' + '00:00:00',
manageType: e.manageType,
days: e.days,
num: e.num,
costs: e.num * e.days * e.dayLeasePrice,
}
})
const paramsList = []
cartList.value.forEach((j, index) => {
let itemsArray = []
j.devInfoVoList.forEach((e) => {
if (e.isChecked) {
itemsArray.push({
maId: e.maId,
id: e.id,
rentBeginTime: e.rentBeginTime + ' ' + '00:00:00',
rentEndTime: e.rentEndTime + ' ' + '23:59:59',
manageType: e.manageType,
days: e.days,
num: e.num,
costs: e.num * e.days * e.dayLeasePrice,
})
}
})
if (itemsArray.length > 0) {
paramsList[index] = {
cost: 0,
detailsList: itemsArray,
address: address.value,
}
}
})
paramsList.forEach((e) => {
e.cost = e.detailsList.reduce((accumulator, currentValue) => {
return accumulator + currentValue.costs
}, 0)
})
const res = await submitBookCarAPI(paramsList)
if (res.code === 200) {
showSuccessToast('提交成功')
uni.removeStorageSync('myCartList')
setTimeout(() => {
uni.navigateTo({ url: `/pages/order-list/index?type=2` })
}, 500)
// getDeviceDetailsData()
}
}
const onViewProtocol = async (item, index) => {
if (amountDevice.value < 1) {
showFailToast('请选择装备')
return
}
let isDays = false
try {
amountDeviceList.value.forEach((e) => {
if (e.days < 1) {
showFailToast('有装备租期未选择或租期为0请选择租期')
isDays = true
throw new Error()
}
})
} catch (error) {}
if (isDays) return
// 组装参数 获取协议
let detailsList = []
let cost = 0
const { companyName, companyId, personPhone } = item.companyPersonPhoneKey
cartList.value[index].devInfoVoList.map((e) => {
if (e.isChecked) {
detailsList.push({
rentBeginTime: e.rentBeginTime + ' ' + '00:00:00',
rentEndTime: e.rentEndTime + ' ' + '23:59:59',
manageType: e.manageType,
days: e.days,
num: e.num,
costs: e.num * e.days * e.dayLeasePrice,
deviceName: e.deviceName,
dayLeasePrice: e.dayLeasePrice,
})
cost = cost + e.num * e.days * e.dayLeasePrice
}
})
const queryParams = {
companyName: memberStore.userCompanyName,
czcompanyName: companyName,
companyId,
cost,
detailsList,
personPhone,
}
const { data: res } = await getBookCarAgreementAPI(queryParams)
uni.setStorageSync('myCartList', { cartList: cartList.value })
uni.navigateTo({
url: `/pages/agreement/index?url=${res.url}&type=1`,
})
}
const onSelectTime = (type, index, goodsI) => {
timeType.value = type
activeIndex.value = index
goodsIndex.value = goodsI
showBottom.value = true
}
const onConfirm = () => {
if (timeType.value === 1) {
// 清除结束日期
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentEndTime = ''
// 清除天数
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].days = 0
// 清除费用
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].costs = 0
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentBeginTime =
leaseTime.value.join('-')
} else {
console.log("xxxxxxxxxxxxx",cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentBeginTime)
if(cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentBeginTime==''){
showFailToast('请先选择租赁开始日期')
return
}
if (
moment(leaseTime.value.join('-')).isBefore(
moment(
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentBeginTime,
),
)
) {
showFailToast('租赁结束日期不能早于租赁开始日期')
return
} else {
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentEndTime =
leaseTime.value.join('-')
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].days =
moment(leaseTime.value.join('-')).diff(
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentBeginTime,
'day',
) + 1
}
}
showBottom.value = false
leaseTime.value = []
}
const onClickManage = () => {
isCartManage.value = !isCartManage.value
}
const onCancel = () => {
showBottom.value = false
}
// 获取预约车列表
const getDeviceDetailsData = async () => {
const { data: res } = await getBookCarDetailsAPI()
cartList.value = res
cartList.value.forEach((e) => {
e.isChecked = false
e.protocolChecked = false
e.devInfoVoList.forEach((j) => {
e.isChecked = false
j.days = 0
j.num = j.deviceCount ? j.deviceCount: 1
j.costs = 0
j.rentBeginTime = ''
j.rentEndTime = ''
j.lease_date = null
})
})
}
// 获取地址
const getAddressListData = async () => {
const { rows: res } = await getAddressListAPI()
addressList.value = res.map((e, index) => {
return {
id: index,
name: '',
tel: '',
address: `${e.provinceName}${e.cityName}${e.areaName}${e.address}`,
isDefault: false,
}
})
}
const totalPrice = computed(() => {
let orderAmountPice = 0
cartList.value.forEach((e) => {
e.devInfoVoList.forEach((g) => {
if (g.isChecked) {
orderAmountPice = g.num * g.dayLeasePrice * g.days + orderAmountPice
}
})
})
return orderAmountPice * 100
})
// 计算所有装备
const amountNum = computed(() => {
let amountNum = 0
cartList.value.forEach((e) => {
amountNum = e.devInfoVoList.length + amountNum
})
return amountNum
})
// 已勾选的装备列表
const amountDeviceList = computed(() => {
let selectList = []
cartList.value.forEach((e) => {
e.devInfoVoList.forEach((g) => {
if (g.isChecked) {
selectList.push(g)
}
})
})
return selectList
})
const amountDevice = computed(() => {
let amountNum = 0
cartList.value.forEach((e) => {
e.devInfoVoList.forEach((g) => {
if (g.isChecked) {
amountNum++
}
})
})
return amountNum
})
const onChangeAllCheckbox = (e, index) => {
cartList.value[index].devInfoVoList.forEach((j) => {
j.isChecked = e
})
checkedAll.value = cartList.value.every((i) => i.isChecked === true)
}
const onChangeCheckbox = (e, index) => {
const isCheckAll = cartList.value[index].devInfoVoList.every((j) => j.isChecked === true)
if (isCheckAll) {
cartList.value[index].isChecked = true
} else {
cartList.value[index].isChecked = false
}
checkedAll.value = cartList.value.every((i) => i.isChecked === true)
}
// 获取底部操作栏高度 适配底部内容
const getActionBarHeight = () => {
const query = uni.createSelectorQuery().in(this)
query
.select('.van-safe-area-bottom')
.boundingClientRect((data) => {
if (data) {
actionBarHeight.value = data.height
}
})
.exec()
}
const onChangeDelete = (val) => {
cartList.value.forEach((e) => {
e.isChecked = val
})
}
// 选择地址
const onClickLink = () => {
showBottomAddress.value = true
}
const onClickAddress = (res) => {
address.value = res.address
showBottomAddress.value = false
}
// 删除 底部操作
const onDeleteCart = () => {
showConfirmDialog({
title: '温馨提示',
message: '是否确定删除这条预约车记录',
})
.then(async () => {
let ids = []
cartList.value.forEach((e) => {
e.devInfoVoList.forEach((j) => {
if (j.isChecked) {
ids.push(j.id)
}
})
})
const res = await deleteBookCarByIdsAPI({ ids })
if (res.code === 200) {
showSuccessToast('删除成功')
getDeviceDetailsData()
}
})
.catch(() => {})
}
const onDeleteCartGoods = (id) => {
showConfirmDialog({
title: '温馨提示',
message: '是否确定删除这条预约车记录',
})
.then(async () => {
const res = await deleteBookCarAPI({ id })
if (res.code === 200) {
showSuccessToast('删除成功')
getDeviceDetailsData()
}
})
.catch(() => {})
}
const onAddAddress = () => {
// console.log('新增地址')
uni.navigateTo({ url: '/pages/add-address/index' })
}
onLoad(() => {
nextTick(() => {
getActionBarHeight()
})
})
onShow(() => {
const myCartList = uni.getStorageSync('myCartList')
if (myCartList.cartList) {
cartList.value = myCartList.cartList
} else {
getDeviceDetailsData()
}
getAddressListData()
uni.hideTabBar()
})
onHide(() => {
cartList.value = []
address.value = ''
})
</script>
<style lang="scss" scoped>
.cart-container {
padding: 10px;
box-sizing: border-box;
background: linear-gradient(to bottom, #b0c7e3, #cfd9e5, #f9f9f9);
}
.order-set {
background-color: #fff;
padding: 10px;
box-sizing: border-box;
border-radius: 6px;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
.van-row {
padding: 2px 0;
display: flex;
align-items: center;
}
}
.nav-header {
height: 40px;
padding: 0 10px;
display: flex;
align-items: center;
justify-content: space-between;
background-color: $uni-navbar-bg-color;
text:nth-child(2) {
margin-left: 8px;
color: #00377a;
font-size: 16px;
font-weight: bold;
font-style: italic;
}
}
.amount {
font-size: 13px;
color: #ccc;
}
.company-box {
display: flex;
align-items: center;
width: 100%;
.company-name {
width: 100%;
display: flex;
flex-direction: column;
view {
padding-left: 6px;
font-size: 13px;
font-weight: bold;
margin-bottom: -6px;
}
.van-image {
width: 100%;
}
}
}
.contacts {
font-size: 13px;
text-align: right;
}
.items-info {
display: flex;
align-items: center;
.info {
font-size: 12px;
flex: 1;
view {
padding: 1px 0 1px 10px;
font-size: 12px;
color: #6f6f6f;
.van-image {
margin: 0 4px;
}
}
& view:first-child {
font-size: 14px;
font-weight: bold;
}
}
}
.protocol {
font-size: 13px;
color: #1989fa;
}
:deep(.van-address-item__edit) {
display: none;
}
:deep(.van-submit-bar__bar) {
justify-content: space-between;
}
:deep(.van-address-item__name) {
margin-bottom: 0;
}
</style>