Zlpt_Portal_h5/src/pages/cart/index.vue

746 lines
24 KiB
Vue
Raw Normal View History

2024-12-13 15:30:11 +08:00
<template>
<!-- 预约车 -->
2025-01-02 18:02:58 +08:00
<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>
2024-12-20 14:23:43 +08:00
</view>
2025-01-02 18:02:58 +08:00
<scroll-view scroll-y :style="{ paddingBottom: actionBarHeight + 'px' }">
<view class="order-set" v-for="(item, index) in cartList" :key="index">
2024-12-20 14:23:43 +08:00
<van-row>
<van-col span="2">
2024-12-26 18:17:45 +08:00
<van-checkbox
2025-01-02 18:02:58 +08:00
v-model="item.isChecked"
2024-12-20 14:23:43 +08:00
icon-size="16px"
2025-01-02 18:02:58 +08:00
@change="onChangeAllCheckbox($event, index)"
2024-12-26 18:17:45 +08:00
/>
2024-12-20 14:23:43 +08:00
</van-col>
2025-01-02 18:02:58 +08:00
<van-col span="12">
<view class="company-box">
2024-12-20 14:23:43 +08:00
<van-image
fit="cover"
2025-01-02 18:02:58 +08:00
width="1.5rem"
height="1.2rem"
:src="companyImg"
2024-12-20 14:23:43 +08:00
/>
2025-01-02 18:02:58 +08:00
<view class="company-name">
<view> {{ item.companyPersonPhoneKey.companyName }} </view>
<van-image fit="cover" height="0.5rem" :src="companyBg" />
2024-12-20 14:23:43 +08:00
</view>
</view>
</van-col>
2025-01-02 18:02:58 +08:00
<van-col span="10" class="contacts">
<view> 联系人 {{ item.companyPersonPhoneKey.person }} </view>
<view>
{{ item.companyPersonPhoneKey.personPhone }}
</view>
</van-col>
2024-12-20 14:23:43 +08:00
</van-row>
2025-01-02 18:02:58 +08:00
<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"
: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>
2024-12-26 18:17:45 +08:00
</view>
2025-01-02 18:02:58 +08:00
<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>
2024-12-20 14:23:43 +08:00
</view>
2025-01-02 18:02:58 +08:00
</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"
/>
</van-popup>
<van-submit-bar
button-color="#579d92"
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="#579d92"
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>
2024-12-13 15:30:11 +08:00
</template>
<script setup>
2024-12-20 14:23:43 +08:00
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'
2024-12-26 18:17:45 +08:00
import {
submitBookCarAPI,
deleteBookCarAPI,
2024-12-30 15:02:18 +08:00
getAddressListAPI,
getBookCarDetailsAPI,
2024-12-26 18:17:45 +08:00
deleteBookCarByIdsAPI,
2024-12-30 15:02:18 +08:00
getBookCarAgreementAPI,
2024-12-26 18:17:45 +08:00
} from '@/services/cart/index.js'
2024-12-30 15:02:18 +08:00
import { useMemberStore } from '@/stores/index.js'
2024-12-20 14:23:43 +08:00
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([])
2024-12-26 18:17:45 +08:00
const isCartManage = ref(false)
const checkedAll = ref(false)
2024-12-30 15:02:18 +08:00
const memberStore = useMemberStore()
2024-12-20 14:23:43 +08:00
const onClickLeft = () => {
2025-01-02 18:02:58 +08:00
uni.removeStorageSync('myCartList')
2024-12-20 14:23:43 +08:00
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) => {
2024-12-26 18:17:45 +08:00
const isSelect = e.devInfoVoList.some((j) => j.isChecked === true)
if (isSelect && !e.protocolChecked) {
2024-12-20 14:23:43 +08:00
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) => {
2024-12-26 18:17:45 +08:00
if (e.isChecked) {
2024-12-20 14:23:43 +08:00
itemsArray.push({
maId: e.maId,
id: e.id,
2024-12-26 18:17:45 +08:00
rentBeginTime: e.rentBeginTime + ' ' + '00:00:00',
rentEndTime: e.rentEndTime + ' ' + '23:59:59',
2024-12-20 14:23:43 +08:00
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('提交成功')
2025-01-02 18:02:58 +08:00
uni.removeStorageSync('myCartList')
2024-12-26 18:17:45 +08:00
setTimeout(() => {
2024-12-27 18:04:48 +08:00
uni.navigateTo({ url: `/pages/order-list/index?type=2` })
2024-12-26 18:17:45 +08:00
}, 500)
// getDeviceDetailsData()
2024-12-20 14:23:43 +08:00
}
}
2024-12-30 15:02:18 +08:00
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)
2025-01-02 18:02:58 +08:00
uni.setStorageSync('myCartList', { cartList: cartList.value })
2024-12-27 18:04:48 +08:00
uni.navigateTo({
2024-12-30 15:02:18 +08:00
url: `/pages/agreement/index?url=${res.url}&type=1`,
2024-12-27 18:04:48 +08:00
})
}
2024-12-20 14:23:43 +08:00
const onSelectTime = (type, index, goodsI) => {
timeType.value = type
activeIndex.value = index
goodsIndex.value = goodsI
showBottom.value = true
}
const onConfirm = () => {
if (timeType.value === 1) {
2025-02-08 17:01:40 +08:00
// 清除结束日期
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
2024-12-20 14:23:43 +08:00
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentBeginTime =
leaseTime.value.join('-')
} else {
if (
moment(leaseTime.value.join('-')).isBefore(
moment(
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentBeginTime,
),
)
) {
2025-02-08 17:01:40 +08:00
showFailToast('租赁结束日期不能早于租赁开始日期')
2025-01-21 16:11:20 +08:00
return
2024-12-20 14:23:43 +08:00
} else {
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentEndTime =
leaseTime.value.join('-')
2025-01-21 16:11:20 +08:00
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].days =
moment(leaseTime.value.join('-')).diff(
cartList.value[activeIndex.value].devInfoVoList[goodsIndex.value].rentBeginTime,
'day',
) + 1
2024-12-20 14:23:43 +08:00
}
}
showBottom.value = false
leaseTime.value = []
}
2024-12-26 18:17:45 +08:00
const onClickManage = () => {
isCartManage.value = !isCartManage.value
}
2024-12-20 14:23:43 +08:00
const onCancel = () => {
showBottom.value = false
}
// 获取预约车列表
const getDeviceDetailsData = async () => {
const { data: res } = await getBookCarDetailsAPI()
cartList.value = res
cartList.value.forEach((e) => {
2024-12-26 18:17:45 +08:00
e.isChecked = false
e.protocolChecked = false
2024-12-20 14:23:43 +08:00
e.devInfoVoList.forEach((j) => {
2024-12-26 18:17:45 +08:00
e.isChecked = false
2024-12-20 14:23:43 +08:00
j.days = 0
j.num = 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) => {
2024-12-26 18:17:45 +08:00
if (g.isChecked) {
2024-12-20 14:23:43 +08:00
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) => {
2024-12-26 18:17:45 +08:00
if (g.isChecked) {
2024-12-20 14:23:43 +08:00
selectList.push(g)
}
})
})
return selectList
})
const amountDevice = computed(() => {
let amountNum = 0
cartList.value.forEach((e) => {
e.devInfoVoList.forEach((g) => {
2024-12-26 18:17:45 +08:00
if (g.isChecked) {
2024-12-20 14:23:43 +08:00
amountNum++
}
})
})
return amountNum
})
2024-12-26 18:17:45 +08:00
const onChangeAllCheckbox = (e, index) => {
2024-12-20 14:23:43 +08:00
cartList.value[index].devInfoVoList.forEach((j) => {
2024-12-26 18:17:45 +08:00
j.isChecked = e
2024-12-20 14:23:43 +08:00
})
2024-12-26 18:17:45 +08:00
checkedAll.value = cartList.value.every((i) => i.isChecked === true)
2024-12-20 14:23:43 +08:00
}
2024-12-26 18:17:45 +08:00
const onChangeCheckbox = (e, index) => {
const isCheckAll = cartList.value[index].devInfoVoList.every((j) => j.isChecked === true)
2024-12-20 14:23:43 +08:00
if (isCheckAll) {
2024-12-26 18:17:45 +08:00
cartList.value[index].isChecked = true
2024-12-20 14:23:43 +08:00
} else {
2024-12-26 18:17:45 +08:00
cartList.value[index].isChecked = false
2024-12-20 14:23:43 +08:00
}
2024-12-26 18:17:45 +08:00
checkedAll.value = cartList.value.every((i) => i.isChecked === true)
2024-12-20 14:23:43 +08:00
}
// 获取底部操作栏高度 适配底部内容
const getActionBarHeight = () => {
const query = uni.createSelectorQuery().in(this)
query
.select('.van-safe-area-bottom')
.boundingClientRect((data) => {
if (data) {
actionBarHeight.value = data.height
}
})
.exec()
}
2024-12-26 18:17:45 +08:00
const onChangeDelete = (val) => {
cartList.value.forEach((e) => {
e.isChecked = val
})
}
2024-12-20 14:23:43 +08:00
// 选择地址
const onClickLink = () => {
showBottomAddress.value = true
}
const onClickAddress = (res) => {
address.value = res.address
showBottomAddress.value = false
}
2024-12-26 18:17:45 +08:00
// 删除 底部操作
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(() => {})
}
2024-12-27 18:04:48 +08:00
const onAddAddress = () => {
// console.log('新增地址')
uni.navigateTo({ url: '/pages/add-address/index' })
}
2024-12-20 14:23:43 +08:00
onLoad(() => {
nextTick(() => {
getActionBarHeight()
})
})
onShow(() => {
2025-01-02 18:02:58 +08:00
const myCartList = uni.getStorageSync('myCartList')
if (myCartList.cartList) {
cartList.value = myCartList.cartList
} else {
getDeviceDetailsData()
}
2024-12-20 14:23:43 +08:00
getAddressListData()
uni.hideTabBar()
})
onHide(() => {
cartList.value = []
address.value = ''
})
2024-12-13 15:30:11 +08:00
</script>
2024-12-20 14:23:43 +08:00
<style lang="scss" scoped>
.cart-container {
padding: 10px;
box-sizing: border-box;
background: linear-gradient(to bottom, #bfdfdb, #f9f9f9, #fff);
}
.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: #0292f9;
font-size: 16px;
font-weight: bold;
font-style: italic;
}
}
.amount {
font-size: 13px;
color: #ccc;
}
.company-box {
display: flex;
align-items: center;
2024-12-13 15:30:11 +08:00
width: 100%;
2024-12-20 14:23:43 +08:00
.company-name {
width: 100%;
display: flex;
flex-direction: column;
view {
padding-left: 6px;
font-size: 13px;
font-weight: bold;
2024-12-27 18:04:48 +08:00
margin-bottom: -6px;
2024-12-20 14:23:43 +08:00
}
.van-image {
width: 100%;
}
}
}
.contacts {
2024-12-27 18:04:48 +08:00
font-size: 13px;
text-align: right;
2024-12-20 14:23:43 +08:00
}
.items-info {
display: flex;
2024-12-26 18:17:45 +08:00
2024-12-20 14:23:43 +08:00
align-items: center;
.info {
font-size: 12px;
2024-12-26 18:17:45 +08:00
flex: 1;
2024-12-20 14:23:43 +08:00
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;
2024-12-13 15:30:11 +08:00
}
2024-12-26 18:17:45 +08:00
:deep(.van-submit-bar__bar) {
justify-content: space-between;
}
2024-12-27 18:04:48 +08:00
:deep(.van-address-item__name) {
margin-bottom: 0;
}
2024-12-13 15:30:11 +08:00
</style>