Commit b1172282 authored by 贺世双's avatar 贺世双

新增运单

parent 8e475743
......@@ -50,7 +50,7 @@ export function downloadImg(data) {
//获取基础订单信息--订舱委托
export function getOrderBaseList(data) {
return Request(`/api/entry/{mini}/m-action/getBookingOrder`, data);
return Request(`/api/entry/{mini}/m-action/getBookingOrder`, data);
}
// 查询订舱委托订单明细
......@@ -65,20 +65,54 @@ export function getOrderBaseEvent(data) {
}
// 查询所有船公司信息
export function queryShipownerAll(data) {
return Request(`/api/entry/{mini}/m-action/getShipownerAll`, data);
}
// 订舱确认操作
export function updateTmBlEvent(data) {
return Request(`/api/entry/{mini}/m-action/updateTmBlEvent`, data);
}
// 修改船期操作
export function changeShippingDateSubmit(data) {
return Request(`/api/entry/{mini}/m-action/changeShippingDateSubmit`, data);
}
// 提货单上传操作
export function getLadingUpload(data) {
return Request(`/api/entry/{mini}/m-action/getLadingUpload`, data);
}
//查询运单列表
export function findShipmentOrders(data) {
return Request(
`/api/entry/{mini}/m-action/biz.tm.Shipment.tm_shipment_m_carrier.paging`,
data
);
export function getShipmentOrders(data) {
return Request( `/api/entry/{mini}/m-action/getShipmentOrders`, data);
}
//查询运单详情
export function findShipmentDetail(data) {
return Request(
`/api/entry/{mini}/m-action/biz.tm.Shipment.tm_shipment_m_carrier_page.get`,
data
);
// 查询运单的所有节点信息
export function getShipmentEvent(data) {
return Request(`/api/entry/{mini}/m-action/getShipmentEvent`, data);
}
//查询司机列表
export function searchDriverList(data) {
return Request(`/api/entry/{mini}/m-action/getDriverAll`,data);
}
//查询车辆列表
export function searchTruckList(data) {
return Request(`/api/entry/{mini}/m-action/getVehicleAll`, data);
}
//派车确认
export function getMassShipmentTruckList(data) {
return Request(`/api/entry/{mini}/m-action/getMassShipmentTruckList`, data );
}
//查询运单途径站点
export function findShipmentStops(data) {
return Request(
......@@ -123,20 +157,7 @@ export function queryTruckType(data) {
);
}
//查询司机列表
export function searchDriverList(data) {
return Request(
`/api/entry/{mini}/m-action/biz.md.Driver.md_driver_m_search.paging`,
data
);
}
//查询车辆列表
export function searchTruckList(data) {
return Request(
`/api/entry/{mini}/m-action/biz.md.Truck.md_truck_m_search.paging`,
data
);
}
//查询道口
export function searchDockList(data) {
return Request(
......@@ -249,13 +270,7 @@ export function UpdateTruckInfo(data) {
//获取大宗订单已分配车辆
export function getMassOrderTruckList(data) {
return Request(
`/api/entry/{mini}/m-action/biz.tm.MassOrderTruck.tm_massordertruck_m_search.paging`,
data
);
}
//大宗订单车辆分配 assignType: 分配单辆车:assignTruck 分配多量车:assignTrucks
export function massAssignTruck(data, assignType) {
......
......@@ -4,6 +4,9 @@
<view class="consumer_code flex_center">
<text selectable> 基础订单号:{{propData['order_base_no'] || ''}}</text>
</view>
<view :class="propData.execute_bu == null ? 'shipment-state' : 'shipment-state shipmenting'">
{{propData.execute_bu}}
</view>
</view>
<u-line color="#E5E5E5" margin="20rpx 0" />
<view style="padding: 0 24rpx 32rpx;" @click="toOrderDetail">
......@@ -12,7 +15,7 @@
<bs-customCell label="起运港 :" :value="propData.port_of_source_location_name" labelCol="4" wrapCol="6" />
</view>
<view style="width: 50%;float: left;">
<bs-customCell label="目的港 :" :value="propData.port_of_dest_location_name" labelCol="4" wrapCol="6" />
<bs-customCell label="目的港 :" :value="propData.port_of_dest_location_name" labelCol="4" wrapCol="8" />
</view>
</view>
<view class=" flex_sb">
......@@ -34,10 +37,10 @@
<bs-customCell label="承运商 :" :value="propData.carrier" labelCol="2" wrapCol="6" />
</view>
<view class="flex_cen flex_center orderItemButtonGroup">
<button class="flex_cen flex_center" @click="onAllotCar('unMulti')">订舱确认</button>
<button class="flex_cen flex_center" @click="onAllotCar('multi')">提单上传</button>
<button class="flex_cen flex_center" style="margin-top: 24rpx;" @click="onAllotCar('record')">修改船期</button>
<button class="flex_cen flex_center" @click="onAllotCar('multi')">异常上报</button>
<button class="flex_cen flex_center" @click="onBookingConfirm()">订舱确认</button>
<button class="flex_cen flex_center" @click="onLadingUpload()">提单上传</button>
<button class="flex_cen flex_center" style="margin-top: 24rpx;" @click="onChangeShippingDate()">修改船期</button>
<button class="flex_cen flex_center" @click="onAbnormalEvent()">异常上报</button>
</view>
</view>
......@@ -62,11 +65,32 @@
url: `/subpkg/orderDetail/orderDetail`,
})
},
onAllotCar(allotType) {
const orderNo = this.propData['massOrder.orderNo']
const orderId = this.propData['id']
//跳转订舱确认界面
onBookingConfirm() {
getApp().globalData.bookingConfirm = this.propData
uni.navigateTo({
url: `/subpkg/bookingConfirm/bookingConfirm`,
})
},
//跳转修改船期界面
onChangeShippingDate() {
getApp().globalData.changeShippingDate = this.propData
uni.navigateTo({
url: `/subpkg/changeShippingDate/changeShippingDate`,
})
},
//跳转提单上传界面
onLadingUpload() {
getApp().globalData.ladingUpload = this.propData
uni.navigateTo({
url: `/subpkg/ladingUpload/ladingUpload`,
})
},
//跳转异常反馈界面
onAbnormalEvent() {
getApp().globalData.abnormalEvent = this.propData
uni.navigateTo({
url: `/subpkg/allotCars/allotCars?orderId=${orderId}&orderNo=${orderNo}&allotType=${allotType}`,
url: `/subpkg/abnormalEvent/abnormalEvent`,
})
},
},
......
<template>
<view class="shipmentItem box_shadow_card" @click="navToShipmentDetail">
<view class="shipment-header flex_sb" style="padding: 28rpx 24rpx 0;">
<u-checkbox iconSize="20rpx" shape="circle" size="20px" :name="propData" :checked="propData.checked">
</u-checkbox>
<view class="consumer_code flex_center">
<text selectable> 运单号:{{propData.shipmentNo}}</text>
<text selectable> 运单号:{{propData.shipment_no}}</text>
</view>
<view :class="propData.shipmentStatus ==='Approved' ? 'shipment-state' : 'shipment-state shipmenting'">
{{propData.shipmentStatusLabel}}
<view :class="propData.execute_bu == null ? 'shipment-state' : 'shipment-state shipmenting'">
{{propData.execute_bu}}
</view>
</view>
<u-line color="#E5E5E5" margin="20rpx 0" />
<view style="padding: 0 24rpx 32rpx;">
<view class="stations">
<view class="stations">
<view class="start-station flex_center">
<view class="t-icon-start-sddress t-icon" style="margin-right: 8rpx;"></view>
{{propData['original.name'] || ''}}
{{propData['source_location_name'] || ''}}
</view>
<view class="end-station flex_center">
<view class="t-icon-end-sddress t-icon" style="margin-right: 8rpx;"></view>
{{propData['destination.name'] || ''}}
{{propData['dest_location_name'] || ''}}
</view>
</view>
<bs-customCell label="要求提货日期 :" :value="propData.early_pickup_date" labelCol="3.5" wrapCol="6" />
<view class=" flex_sb">
<view style="width: 50%;float: left;">
<bs-customCell label="车牌号 :" :value="propData.truck_no" labelCol="4" wrapCol="6" />
</view>
<view style="width: 50%;float: left;">
<bs-customCell label="司机 :" :value="propData.driver_name" labelCol="3" wrapCol="8" />
</view>
</view>
<view class=" flex_sb">
<view style="width: 50%;float: left;">
<bs-customCell label="承运商 :" :value="propData.carrier" labelCol="4" wrapCol="6" />
</view>
<view style="width: 50%;float: left;">
<bs-customCell label="司机电话 :" :value="propData.driver_tel" labelCol="5" wrapCol="8" />
</view>
</view>
<bs-customCell label="发运日期 :" :value="propData.shipmentDate" labelCol="3" wrapCol="6" />
<!-- <customCell label="运输时效" :value="propData.shipTime || '0天'" labelCol="4" wrapCol="6" /> -->
<template v-if="0">
<bs-customCell label="司机名" :value="propData['driver1.tel']" labelCol="2" wrapCol="10" />
<bs-customCell label="车牌号" :value="propData['truck.name']" labelCol="2" wrapCol="10" />
</template>
<bs-customCell label="货量 :" labelCol="2" wrapCol="10" :value="`${propData.shipOrders}单 / ${propData.shipQty}件 / ${propData.shipWeight}千克 / ${propData.shipVolume}方`" />
<template v-if="propData.shipmentStatus ==='Approving'">
<view class="operationBtn flex_center flex_cen" @click.stop="onClick(propData.id, 'approve')">确认</view>
</template>
<template v-if="propData.shipmentStatus ==='Approved'">
<view class="operationBtn flex_center flex_cen" @click.stop="onClick(propData.id, 'approveCancel')">取消确认</view>
</template>
<!-- <bs-customCell label="货量 :" labelCol="2" wrapCol="10" :value="`${propData.shipOrders}单 / ${propData.shipQty}件 / ${propData.shipWeight}千克 / ${propData.shipVolume}方`" /> -->
</view>
</view>
</template>
<script>
......@@ -42,18 +51,13 @@
export default {
name: 'shipmentItem',
options: { styleIsolation: 'shared' },
props: {
propData: {
type: Object,
default: {}
},
},
props: ['propData'],
methods: {
navToShipmentDetail() {
this.onSetGlobalData()
const shipmentId = this.propData.id
//路由跳转==预约单详情界面
navToShipmentDetail() {
getApp().globalData.shipmentDetail = this.propData
wx.navigateTo({
url: `/subpkg/shipmentDetail/shipmentDetail?id=${shipmentId}`,
url: `/subpkg/shipmentDetail/shipmentDetail`,
})
},
//设置全局变量
......@@ -93,16 +97,19 @@
position: relative;
margin: 24rpx 24rpx 0;
padding: 0;
padding-bottom: 32rpx;
&/deep/.custom-cell-row {
margin-top: 20rpx;
}
.consumer_code {
line-height: 40rpx;
text-shadow: 1rpx 3rpx 12rpx rgba(0, 0, 0, 0.04);
}
margin-right: 85px;
}
.shipment-state {
font-size: 24rpx;
color: #F7A64A;
......@@ -112,18 +119,18 @@
background: rgba(247, 166, 74, .1);
text-shadow: 1rpx 3rpx 12rpx rgba(0, 0, 0, 0.04);
}
.shipmenting {
color: #66CCCC;
background: rgba(61, 204, 185, .1);
}
.start-station,
.end-station {
margin: 20rpx 0;
font-size: 30rpx;
font-weight: bolder;
.start-icon,
.end-icon {
width: 40rpx;
......@@ -135,20 +142,28 @@
background-color: #2E75E6;
margin-right: 20rpx;
}
.end-icon {
background-color: #F7A64A;
}
}
.operationBtn {
color: #FFFFFF;
padding: 20rpx;
margin-top: 32rpx;
border-radius: 44rpx;
box-shadow: 1rpx 3rpx 12rpx 0px rgba(0, 0, 0, 0.04);
background: linear-gradient(90deg, #2E75E6 0%, #5E58EE 100%);
width: 100%;
.orderItemButtonGroup {
justify-content: space-between;
padding: 0 24rpx;
flex-wrap: wrap;
button {
font-size: 32rpx;
font-weight: 500;
color: #FFFFFF;
width: 315rpx;
height: 80rpx;
margin: 0;
border-radius: 44rpx;
background: linear-gradient(90deg, #2E75E6 0%, #5E58EE 100%);
box-shadow: 1rpx 3rpx 12rpx 0rpx rgba(0, 0, 0, 0.04);
}
}
}
</style>
......@@ -95,9 +95,9 @@
"enablePullDownRefresh": false
}
}, {
"path": "reserveDockTime/reserveDockTime",
"path": "abnormalEvent/abnormalEvent",
"style": {
"navigationBarTitleText": "预约到站时间",
"navigationBarTitleText": "异常反馈",
"enablePullDownRefresh": false
}
}, {
......@@ -126,28 +126,28 @@
"disableScroll": false
}
}, {
"path": "checkTruck/checkTruck",
"path": "changeShippingDate/changeShippingDate",
"style": {
"navigationBarTitleText": "",
"navigationBarTitleText": "修改船期",
"enablePullDownRefresh": false
}
}, {
"path": "allotCars/allotCars",
"path": "bookingConfirm/bookingConfirm",
"style": {
"navigationBarTitleText": "配车确认",
"navigationBarTitleText": "订舱确认",
"enablePullDownRefresh": false
}
}, {
"path": "choiceTruck/choiceTruck",
"path": "ladingUpload/ladingUpload",
"style": {
"navigationBarTitleText": "",
"navigationBarTitleText": "提单上传",
"enablePullDownRefresh": false
}
}, {
"path": "shipmentLbs/shipmentLbs",
"path": "shipmentDispatch/shipmentDispatch",
"style": {
"navigationBarTitleText": "运单轨迹",
"navigationBarTitleText": "派车",
"enablePullDownRefresh": false,
"disableScroll": true
}
......
<template>
<view class="shipment-order-list content_box">
<shipmentItem v-for="item in shipmentOrders" :key="item.id" :propData="item" @onReload="onReload"/>
<view class="search-input flex_center">
<u-search searchIconSize="50" searchIconColor="#FFFFFF" placeholderColor='#FFFFFF' color="#FFFFFF"
:showAction="false" :placeholder="'请输入运单号'" v-model="searchValue"
@clickIcon="onSearch" @search="onSearch" @clear="onSearch" />
</view>
<u-checkbox-group @change="change" placement="column">
<shipmentItem v-for="item in shipmentOrders" :key="item.id" :propData="item" @onReload="onReload"/>
</u-checkbox-group>
<!-- 空状态 -->
<view class="emptyImg flex_col" v-if="!shipmentOrders.length">
<image mode="aspectFit" src="../../static/img/empty/shipmentEmpty.png" />
<text class="empty-text">暂时没有运单</text>
</view>
<view class="box_8">
<view class="section_8">
<u-button @click="onDispatchCar()" shape="circle" color="#2E75E6" text="派车"></u-button>
<u-button @click="onEmptyBox()" shape="circle" color="#2E75E6" customStyle="margin-left: 20rpx;" text="已提空箱"></u-button>
<u-button @click="deliveryArrival()" shape="circle" color="#2E75E6" customStyle="margin-left: 20rpx;" text="已到厂"></u-button>
</view>
<view class="section_9">
<u-button @click="warehouseShipment()" shape="circle" color="#2E75E6" text="仓库已发货"></u-button>
<u-button @click="arrivalPort()" shape="circle" color="#2E75E6" text="进港(到目的地)" customStyle="margin-left: 20rpx;"></u-button>
<u-button @click="onVisibleDate()" shape="circle" color="#2E75E6" customStyle="margin-left: 20rpx;" text="异常上报"></u-button>
</view>
</view>
<!-- <view class="box_4">
<view class="group_6">
<view class="image-text_1">
<u-checkbox-group>
<u-checkbox iconSize="30rpx" shape="circle" size="20px" :checked="isAllChecked "
@change="allChaneg" label="全选" labelSize="25rpx"></u-checkbox>
</u-checkbox-group>
</view>
<text lines="1" class="text_23">已选运单数:</text>
<text lines="1" class="text_24"> {{sum}}</text>
</view>
</view> -->
<!--实际到厂弹出框 -->
<u-popup :show="visible" @close="closeProcess" @open="open" mode="center" :round="10" :safeAreaInsetBottom="0">
<view class="model_box">
<u--form :model="formData" :rules="rules" ref="myForm" errorType='none'>
<view class="basic-info">
<u-form-item prop="actual_arrival_factory_time" required label="实际到厂时间" labelWidth="30%" borderBottom>
<view @click="onVisibleDate('actual_arrival_factory_time')">
<u-input :disabledColor="'#ffffff'" disabled border="none" readonly placeholder="请选择实际到厂时间"
:value="formatDate(formData.actual_arrival_factory_time)" />
</view>
</u-form-item>
</view>
</u--form>
</view>
<view class="operation-btn flex_sb">
<button class="backBtn common_btn" @click="closeProcess">取消</button>
<button class="submitBtn common_btn" @click="onSubmitForm('truck_arrive')">确认</button>
</view>
</u-popup>
<!--实际发货弹出框 -->
<u-popup :show="visible1" @close="closeProcess1" @open="open" mode="center" :round="10" :safeAreaInsetBottom="0">
<view class="model_box">
<u--form :model="formData" :rules="rules" ref="myForm" errorType='none'>
<view class="basic-info">
<u-form-item prop="local_atd" required label="实际发货时间" labelWidth="30%" borderBottom>
<view @click="onVisibleDate('local_atd')">
<u-input :disabledColor="'#ffffff'" disabled border="none" readonly placeholder="请选择实际发货时间"
:value="formatDate(formData.local_atd)" />
</view>
</u-form-item>
</view>
</u--form>
</view>
<view class="operation-btn flex_sb">
<button class="backBtn common_btn" @click="closeProcess1">取消</button>
<button class="submitBtn common_btn" @click="onSubmitForm('truck_departure')">确认</button>
</view>
</u-popup>
<!--实际进港弹出框 -->
<u-popup :show="visible2" @close="closeProcess2" @open="open" mode="center" :round="10" :safeAreaInsetBottom="0">
<view class="model_box">
<u--form :model="formData" :rules="rules" ref="myForm" errorType='none'>
<view class="basic-info">
<u-form-item prop="local_ata" required label="实际进港时间" labelWidth="30%" borderBottom>
<view @click="onVisibleDate('local_ata')">
<u-input :disabledColor="'#ffffff'" disabled border="none" readonly placeholder="请选择实际进港时间"
:value="formatDate(formData.local_ata)" />
</view>
</u-form-item>
</view>
</u--form>
</view>
<view class="operation-btn flex_sb">
<button class="backBtn common_btn" @click="closeProcess2">取消</button>
<button class="submitBtn common_btn" @click="onSubmitForm('truck_entry')">确认</button>
</view>
</u-popup>
<!-- 时间选择 -->
<bs-datetimePicker ref="myTimePicker" :visible="showPopup" @onVisible="onVisibleDate" dateType="datetime"
@onSelsectDate="onSelsectDate" />
</view>
</template>
<script>
import { findShipmentOrders } from '@/api/apiList.js'
import { getShipmentOrders, getMassShipmentTruckList} from '@/api/apiList.js'
import { formatGMT } from '@/utils/util.js'
import { TokenPrefix } from '../../publicConfig/config.js'
const getUserLocation = require('../../mixins/getUserLocation')
......@@ -22,9 +121,22 @@
pageNum: 1, //页码
pageSize: 10, //每页条数
loadMore: true, //加载更多
searchValue: "", //搜索值
message: [],
sum: 0,
isAllChecked: false,
visible:false,//到厂
visible1:false,//仓库发货
visible2:false,//进港
showPopup: false, //时间选择
formData: {
actual_arrival_factory_time: "", //实际到达时间
local_atd:"",//实际发货时间
local_ata:"",//实际进港时间
},
}
},
onLoad(options) {
/*onLoad(options) {
const time = setInterval(() => {
let XSRFToken = uni.getStorageSync(`${TokenPrefix}_XSRFToken`)
if (XSRFToken) {
......@@ -33,6 +145,11 @@
clearInterval(time)
}
}, 1000);
},*/
onShow() {
this.pageNum = 1
this.shipmentOrders = []
this.initData()
},
//下拉刷新
onPullDownRefresh() {
......@@ -46,19 +163,32 @@
}
},
methods: {
open() { },
change(e) {
this.sum = e.length
this.message = e
this.message.length=e.length
},
//初始化数据
initData() {
const { pageNum, pageSize } = this
let data = {
let reqData = {
"args": { pageNum, pageSize }
}
findShipmentOrders(data).then(res => {
if(this.searchValue){
reqData.args.restrictions = [{
"field": 'shipment_no',
"type": "like", //EQ精准匹配,LK模糊匹配
"value": this.searchValue
}]
}
getShipmentOrders(reqData).then(res => {
uni.stopPullDownRefresh()
const data = res.data.data.datas
if (data.length > 0) {
data.map(item => { //格式化时间
if (item.shipmentDate) {
item.shipmentDate = formatGMT(item.shipmentDate, 'D')
if (item.early_pickup_date) {
item.early_pickup_date = formatGMT(item.early_pickup_date, 'D')
}
})
this.shipmentOrders = this.shipmentOrders.concat(data)
......@@ -67,20 +197,261 @@
}
})
},
//调度派车
onDispatchCar(){
this.choose = []
if (this.message.length >0) {
this.choose = this.message
getApp().globalData.choose = this.choose
uni.navigateTo({
url: `/subpkg/shipmentDispatch/shipmentDispatch`,
})
} else {
uni.showToast({
title: "请选择运单",
duration: 3000,
icon: 'error'
})
}
},
//提空箱操作-支架
onDispatchCar(){
this.choose = []
if (this.message.length >0) {
this.choose = this.message
getApp().globalData.choose = this.choose
uni.navigateTo({
url: `/subpkg/shipmentDispatch/shipmentDispatch`,
})
} else {
uni.showToast({
title: "请选择运单",
duration: 3000,
icon: 'error'
})
}
},
//到厂、仓库到货、进港提交表单数据
onSubmitForm(type) {
const rows = this.choose;
this.formData.rows= rows;
this.formData.ship_event_code=type;//进度更新类型
//已到厂时间
if(!this.formData.actual_arrival_factory_time && type=="truck_arrive"){
this.formData.local_ata="";
this.formData.local_atd="";
this.formData.actual_arrival_factory_time= this.formatDate(this.formData.time)
}
//仓库到货时间
if(!this.formData.local_atd && type=="truck_departure"){
this.formData.local_ata="";
this.formData.actual_arrival_factory_time="";
this.formData.local_atd= this.formatDate(this.formData.time)
}
//进港时间
if(!this.formData.local_ata && type=="truck_entry"){
this.formData.actual_arrival_factory_time="";
this.formData.local_atd="";
this.formData.local_ata= this.formatDate(this.formData.time)
}
var baseData = {
"aux": {
"rows":rows,
"aux":this.formData,
},
}
console.log('进度更新确认===========')
//进度更新操作
getMassShipmentTruckList(baseData).then(res => {
if (res.data.data.messageType === 'success') {
uni.showToast({
title: '操作成功!',
duration: 1000
})
if(type=="truck_arrive"){
this.closeProcess();
}else if(type=="truck_departure"){
this.closeProcess1();
}else if(type=="truck_entry"){
this.closeProcess2();
}
setTimeout(() => {
that.$emit('onReload')
}, 1000)
}
})
},
//已到厂显示弹出框
deliveryArrival() {
this.choose = []
if (this.message.length >0) {
this.visible = true;
this.choose = this.message
} else {
uni.showToast({
title: "请选择运单",
duration: 3000,
icon: 'error'
})
}
},
//仓库发货显示弹出框
warehouseShipment(){
this.choose = []
if (this.message.length >0) {
this.choose = this.message
this.visible1 = true;
} else {
uni.showToast({
title: "请选择运单",
duration: 3000,
icon: 'error'
})
}
},
//进港显示弹出框
arrivalPort(){
this.choose = []
if (this.message.length >0) {
this.choose = this.message
this.visible2 = true;
} else {
uni.showToast({
title: "请选择运单",
duration: 3000,
icon: 'error'
})
}
},
//确认选择
onConfirmPicker(value) {
this.setFormData(value)
this.visible = false
this.visible1 = false
this.visible2 = false
},
//到厂关闭弹出框
closeProcess() {
this.visible = false
},
//仓库发货关闭弹出框
closeProcess1() {
this.visible1 = false
},
//进港关闭弹出框
closeProcess2() {
this.visible2 = false
},
//关闭时间选择框
onVisibleDate(type) {
if (type) {
this.visibleKey = type
}
this.showPopup = !this.showPopup
},
//全选
allChaneg() {
this.isAllChecked = !this.isAllChecked;
this.shipmentOrders.map(item => item.checked = this.isAllChecked)
if (this.isAllChecked) {
this.change(this.shipmentOrders)
} else {
this.change(this.shipmentOrders)
this.sum = 0
}
},
// 搜索功能
onSearch() {
this.pageNum = 1
this.shipmentOrders = []
this.initData()
},
// 刷新页面
onReload() {
this.pageNum = 1
this.shipmentOrders = []
this.initData()
},
// 时间选择
onSelsectDate(dateInfo) {
const {
timestamp
} = dateInfo
this.setFormData(timestamp)
this.showPopup = false
},
//页面展示时间戳转换为日期
convertTime(timestamp) {
if (!timestamp) return
const nowDate = new Date(timestamp);
var year = nowDate.getFullYear();
var month = nowDate.getMonth() < 10 ? '0' + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1;
var date = nowDate.getDate();
return `${year}-${ month}-${date}`
},
//设置formData
setFormData(value) {
const key = this.visibleKey
if (key.includes('.')) { //对象特殊处理
const keys = key.split('.')
this.formData[keys[0]][keys[1]] = value
} else {
this.formData[key] = value
}
},
//时间戳转换
formatDate(timestamp) {
var data ="";
this.formData.time="";
if(!timestamp){
data=new Date();
//赋值参数
this.formData.time=data.getTime();
} else{
data=new Date(timestamp);
}
//if (!timestamp) return
const nowDate = data
var year = nowDate.getFullYear();
var month = nowDate.getMonth() < 10 ? '0' + (nowDate.getMonth() + 1) : nowDate.getMonth() + 1;
var date = nowDate.getDate();
const hour = nowDate.getHours();
const minute = nowDate.getMinutes()< 10 ? '0'+ nowDate.getMinutes() : nowDate.getMinutes() ;
var seconds = nowDate.getSeconds() < 10 ? '0' + nowDate.getSeconds() : nowDate.getSeconds();
if (this.dateType === 'date') {
return `${year}-${ month}-${date}`
} else {
return `${year}-${ month}-${date} ${hour}:${ minute}:${seconds}`
}
},
}
}
</script>
<style lang="scss">
.shipment-order-list {
margin-top: 50px;
.search-input {
width: 100%;
position: fixed;
top: 0;
z-index: 999;
height: 100rpx;
background: linear-gradient(to bottom, #005BB5 0%, #005BB5 50%);
/deep/.u-search__content {
height: 80rpx;
margin: 24rpx;
background-color: rgba(240, 240, 240, .5) !important;
.u-search__content__input {
width: 50rpx;
background-color: transparent !important;
}
}
}
.emptyImg {
position: absolute;
left: 50%;
......@@ -92,5 +463,202 @@
text-align: center;
}
}
.block_4 {
position: fixed;
bottom: 53px;
box-shadow: 0px -5px 12px 0px rgba(0, 0, 0, 0.060000);
background-color: rgba(255, 255, 255, 1.000000);
// left: -24rpx;
width: 750rpx;
height: 88rpx;
display: flex;
flex-direction: column;
padding: 24rpx 0 1rpx 0;
}
.block_5 {
width: 702rpx;
align-self: center;
flex-direction: row;
display: flex;
}
.image-text_1 {
width: 96rpx;
flex-direction: row;
display: flex;
justify-content: space-between;
}
.box_7 {
position: fixed;
z-index: 999;
bottom: 0;
background-color: rgba(255, 255, 255, 1.000000);
display: flex;
flex-direction: column;
padding: 16rpx 24rpx 16rpx 24rpx;
}
.box_8 {
position: fixed;
bottom: 0;
background-color: rgba(255, 255, 255, 1.000000);
display: flex;
flex-direction: column;
padding: 16rpx 24rpx 16rpx 24rpx;
}
.section_8 {
width: 702rpx;
flex-direction: row;
display: flex;
justify-content: space-between;
z-index: 999;
margin-bottom: 10px;
.custom-style {
margin: 30rpx;
}
}
.section_9 {
width: 702rpx;
flex-direction: row;
display: flex;
justify-content: space-between;
z-index: 999;
.custom-style {
margin: 30rpx;
}
}
.text_56 {
overflow-wrap: break-word;
color: rgba(89, 89, 89, 1);
font-size: 28rpx;
font-family: PingFangSC-Regular;
font-weight: normal;
text-align: left;
white-space: nowrap;
line-height: 40rpx;
margin-left: 32rpx;
}
.text_57 {
overflow-wrap: break-word;
color: rgba(89, 89, 89, 1);
font-size: 28rpx;
font-family: PingFangSC-Regular;
font-weight: normal;
text-align: left;
white-space: nowrap;
line-height: 40rpx;
margin-left: 8rpx;
}
.box_4 {
position: fixed;
bottom: 105px;
z-index: 999;
box-shadow: 0px -5px 12px 0px rgba(0, 0, 0, 0.060000);
background-color: rgba(255, 255, 255, 1.000000);
margin-left: 10px;
display: flex;
flex-direction: column;
padding: 24rpx 0 1rpx 0;
}
.group_6 {
width: 702rpx;
align-self: center;
flex-direction: row;
display: flex;
}
.image-text_1 {
width: 96rpx;
flex-direction: row;
display: flex;
justify-content: space-between;
}
.text_23 {
overflow-wrap: break-word;
color: rgba(89, 89, 89, 1);
font-size: 28rpx;
font-family: PingFangSC-Regular;
font-weight: normal;
text-align: center;
white-space: nowrap;
line-height: 40rpx;
margin-left: 405rpx;
}
.text_24 {
overflow-wrap: break-word;
color: rgba(89, 89, 89, 1);
font-size: 28rpx;
font-family: PingFangSC-Regular;
font-weight: normal;
text-align: left;
white-space: nowrap;
line-height: 40rpx;
margin-left: 8rpx;
}
.model_box {
width: 360px;
height: 100px;
border-radius: 15rpx;
}
/deep/.basic-info,
/deep/.driving-license {
padding: 0 10rpx;
background-color: #ffffff;
border-radius: 10px;
.input-tip {
font-size: 28rpx;
color: #BFBFBF;
}
.u-form-item__body__left__content__label {
color: #8C8C8C;
font-size: 28rpx;
}
.u-form-item__body {
padding: 25rpx 0;
}
.u-form-item.data-v-5e7216f1 {
padding: 25px 0px 0px 10px;
}
.u-icon {
margin-left: 20rpx;
}
.u-upload__wrap>view {
width: 100%;
}
.previewImages {
width: 100%;
.previewImg {
width: 100% !important;
height: 240rpx !important;
}
}
.uploadeBtn {
width: 100% !important;
height: 240rpx !important;
margin-bottom: 30rpx;
margin-left: 0 !important;
}
.orderTotal {
display: none;
}
}
}
</style>
......@@ -29,8 +29,11 @@
searchValue: "", //搜索值
};
},
onLoad() {
this.initData()
onShow() {
this.pageNum = 1
this.orderList = []
this.initData()
},
//下拉刷新
onPullDownRefresh() {
......@@ -51,6 +54,8 @@
let reqData = {
"args": { pageNum, pageSize }
}
console.log('2222=============')
console.log(reqData)
if(this.searchValue){
reqData.args.restrictions = [{
"field": 'order_base_no',
......@@ -60,7 +65,7 @@
}
getOrderBaseList(reqData).then(res=>{
uni.stopPullDownRefresh()
const data = res.data.data.datas
const data = res.data.data.datas
if (data.length > 0) {
this.orderList = this.orderList.concat(data);
this.pageNum += 1
......
.t-icon {
display: inline-block;
width: 16px;
height: 16px;
width: 30px;
height: 30px;
background-repeat: no-repeat;
background-position: center;
background-size: 100%;
......
<template>
<view class="allotCars content_box">
<view class=" flex_center flex_sb allotCarsHeader">
<view>订单号:{{orderNo}}</view>
<template v-if="allotType !== 'record'">
<u-button @click="addNewCar" :disabled="orderTrucks.length || (allotType === 'multi' ? false : newTrucks.length)" text="添加新车辆"/>
</template>
</view>
<!-- 待分配车辆 -->
<template v-if="newTrucks.length">
<view style="padding: 24rpx;">
<orderTruckCard :ref='`allotTruck${newOrderTruck.id}`' v-for="(newOrderTruck, index) in newTrucks" :key="index"
:propData="newOrderTruck" :isNewAllot="true" />
</view>
</template>
<!-- 已分配车辆 -->
<template v-if="orderTrucks.length">
<view style="padding: 24rpx;">
<orderTruckCard :ref='`allotTruck${orderTruck.id}`' v-for="(orderTruck, index) in orderTrucks" :key="index" :propData="orderTruck" />
</view>
</template>
<view class="operation-btn">
<button v-if="allotType === 'record' ? orderTrucks.length === 0 : newTrucks.length === 0" :class="['submitBtn common_btn', 'disabledBtn' ]"
disabled @click="onConfirmAllot">确认分配</button>
<button v-else :class="['submitBtn common_btn']"
@click="onConfirmAllot">确认分配</button>
<!-- <button :class="['submitBtn common_btn']"
@click="onConfirmAllot">确认分配</button> -->
</view>
</view>
</template>
<script>
import { getMassOrderTruckList, massAssignTruck, updateMassAssignTruck} from '../../api/apiList.js'
export default {
data() {
return {
orderId: '', //订单Id
orderNo: '', //订单号
allotType: 'unMulti', //配车类型 单辆车:unMulti 多辆车:multi 分配记录:record
orderTrucks: [], //订单已分配车辆
deleteTruckIds: [], //订单删除已分配车辆ID列表
newTrucks: [], //新增分配车辆
pageNum: 1, //页码
pageSize: 20, //每页条数
loadMore: true, //加载更多
};
},
onLoad(option) {
const { orderId, orderNo, allotType } = option
this.orderNo = orderNo
this.orderId = orderId
this.allotType = allotType
this.onAddListener() //添加事件监听
if(allotType === 'record'){
this.initTruckList()
}
},
onUnload(){
this.onRemoveListener() //移除事件监听
},
//下拉刷新
onPullDownRefresh() {
if(this.orderTrucks.length){
this.pageNum = 1
this.orderTrucks = []
this.initTruckList()
}
},
// 触底加载更多
onReachBottom() {
if (this.loadMore && this.orderTrucks.length) {
this.initTruckList()
this.loadMore = false
}
},
methods: {
initTruckList() {
const reqData = {
"args": {
pageNum: this.pageNum,
pageSize: this.pageSize,
"restrictions": [{
"field": 'orderCarrier.massOrder.orderNo',
"type": "EQ",
"value": this.orderNo
}]
}
}
getMassOrderTruckList(reqData).then(res => {
uni.stopPullDownRefresh()
const data = res.data.data.datas
if (data.length > 0) {
const newList = this.orderTrucks.concat(data)
this.orderTrucks = [...newList]
this.pageNum += 1
this.loadMore = true
}
})
},
//新增分配车辆
addNewCar() {
const data = {
allotTrucks: this.newTrucks,
isMulti: this.allotType === 'multi'
}
uni.navigateTo({
url: `/subpkg/choiceTruck/choiceTruck?data=${JSON.stringify(data)}`
})
},
onAddListener(){
uni.$on('onAddMassAssignTruck', this.onAddMassAssignTruck) //监听大宗订单车辆分配
uni.$on('onRemoveMassAssignTruck', this.onRemoveMassAssignTruck) //监听大宗订单车辆分配
},
onRemoveListener(){
uni.$off('onAddMassAssignTruck', this.onAddMassAssignTruck)
uni.$off('onRemoveMassAssignTruck', this.onRemoveMassAssignTruck)
},
//添加分配车辆
onAddMassAssignTruck(truckInfo){
let truckList = this.newTrucks.concat(truckInfo)
const newList = []
truckList.map(item => { //数组去重
const flag = newList.find(itm => itm.id === item.id)
if(!flag){
newList.push(item)
}
})
this.newTrucks = [...newList]
},
//移除分配车辆
onRemoveMassAssignTruck(truckId){
if(this.allotType === 'record'){
const list = this.orderTrucks.filter(item => item.id !== truckId)
this.deleteTruckIds = this.deleteTruckIds.concat(truckId)
this.orderTrucks = [...list]
} else {
const list = this.newTrucks.filter(item => item.id !== truckId)
this.newTrucks = [...list]
}
},
//确认分配
onConfirmAllot(){
const _this = this
if(_this.allotType === 'record'){ //更新订单配车
_this.onUpdateAllot()
return
}
let allotData = []
_this.newTrucks.map(item => {
const minShipments = _this.$refs[`allotTruck${item.id}`][0].minFrequency
const maxShipments = _this.$refs[`allotTruck${item.id}`][0].maxFrequency
const capacity = _this.$refs[`allotTruck${item.id}`][0].alloutQty
allotData.push({
truckId: item.id, //车辆ID
driverId: item['driver1.id'] ,//司机ID
minShipments: Number(minShipments), //最少趟数
maxShipments: Number(maxShipments), //最多趟数
capacity: Number(capacity), //核定装运量
})
})
const assignType = _this.allotType === 'multi' ? 'service.mobileAssignTrucks' : 'operation.assignTruck'
const reqData = {
'aux': _this.allotType === 'multi' ? {trucks:allotData} : allotData[0],
'args': {"selectedIds": [_this.orderId]}
}
massAssignTruck(reqData, assignType).then(res => {
if (res.data.messageType === 'success') {
uni.showToast({
title: '分配成功',
duration: 3000
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
})
},
onUpdateAllot(){
const _this = this
let allotData = []
this.orderTrucks.map(item => {
const minShipments = _this.$refs[`allotTruck${item.id}`][0].minFrequency
const maxShipments = _this.$refs[`allotTruck${item.id}`][0].maxFrequency
const capacity = _this.$refs[`allotTruck${item.id}`][0].alloutQty
allotData.push({
truckId: item.id, //车辆ID
driverId: item['driver1.id'] ,//司机ID
minShipments: Number(minShipments), //最少趟数
maxShipments: Number(maxShipments), //最多趟数
capacity: Number(capacity), //核定装运量
})
})
const reqData = {
'aux': {
'trucks': [...allotData],
'delete': [...this.deleteTruckIds]
},
}
updateMassAssignTruck(reqData).then(res => {
if (res.data.messageType === 'success') {
uni.showToast({
title: '分配成功',
duration: 3000
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
})
}
},
}
</script>
<style lang="scss">
.allotCars {
padding-top: 120rpx;
.allotCarsHeader {
background-color: #FFFFFF;
height: 120rpx;
width: 100vw;
padding: 40rpx 24rpx;
font-size: 28rpx;
font-weight: 400;
color: #8C8C8C;
position: fixed;
top: 0;
z-index: 999;
button {
width: 220rpx;
height: 80rpx;
line-height: 80rpx;
border-radius: 40rpx;
color: #2E75E6;
background-color: rgba(46, 117, 230, .1);
margin: 0;
font-size: 28rpx;
font-weight: 500;
}
}
.operation-btn {
padding-bottom: 40rpx;
margin-bottom: 0;
position: fixed;
bottom: 0;
z-index: 999;
background-color: #FFFFFF;
.submitBtn {
width: 90%;
border: none;
font-weight: 500;
color: #FFFFFF;
background: linear-gradient(90deg, #2E75E6 0%, #5E58EE 100%);
box-shadow: 1rpx -3rpx 12rpx 0rpx rgba(0,0,0,0.04);
border-radius: 48rpx;
}
.disabledBtn{
background: linear-gradient(90deg, rgba(46, 117, 230, .3) 0%, rgba(94, 88, 238, .3) 100%);
}
}
}
</style>
\ No newline at end of file
<template>
<view class="view-driver-truck content_box">
<view class="queueSubscribeTitle">
<u--input placeholder="请输入司机姓名" border="surround" prefixIcon="search" shape="circle" color="#ffffff"
placeholderStyle="color:#ffffff" @blur="searchText" v-model="searchValue"></u--input>
</view>
<view class="content-list" style="margin-bottom: 120rpx;">
<u-empty mode="data" textSize='32' iconSize="160" text="暂无数据" v-if="!datas.length" />
<bs-customCell v-for="item in datas" :key="item.id" :label="item.name" labelCol='4' wrapCol="7.2"
:value="isDriver ? item.tel : item['facilityMode.name']" @click.native="onNavDetail(item.id, item.name)">
</bs-customCell>
</view>
</view>
</template>
<script>
import {
searchDriverList,
searchTruckList
} from '../../api/apiList'
export default {
options: {
styleIsolation: 'shared'
},
data() {
return {
datas: [], //候选项列表
isDriver: true, //是否查看司机
pageNum: 1, //页码
pageSize: 20, //每页条数
loadMore: true, //加载更多
searchValue: ''
}
},
onLoad: function() {},
onShow() {
this.pageNum = 1
this.datas = []
this.initData(this.isDriver)
},
onReachBottom() {
if (this.loadMore) {
this.initData(this.isDriver);
this.loadMore = false
}
},
methods: {
//设置页面头部标题
setNavTitle(title) {
uni.setNavigationBarTitle({
title: title,
searchValue: ''
})
},
//初始化数据
initData(isDriver) {
const {
pageNum,
pageSize
} = this
const reqData = {
args: {
pageNum,
pageSize,
"restrictions": [{
"field": "name",
"type": "LK",
"value": this.searchValue
}]
}
}
searchDriverList(reqData).then(res => {
const datas = res.data.data.datas
if (datas.length) {
const newData = this.datas.concat(datas)
this.datas = [...newData]
this.pageNum += 1
this.loadMore = true
}
})
},
searchText(searchValue) {
this.searchValue = searchValue
this.pageNum = 1
this.datas = []
this.initData(this.isDriver)
},
onNavDetail(id, name){
let pages = getCurrentPages(); // 当前页面
if (pages.length > 1) {
var beforePage = pages[pages.length - 2]; // 前一个页面
beforePage.$vm.setTruckDriver(id, name) //clear 是你要调用上个页面的方法,$vm 是必须要有的
}
uni.navigateBack()
}
}
}
</script>
<style lang="scss">
.view-driver-truck {
.queueSubscribeTitle {
width: 100%;
height: 128rpx;
background-color: #2E75E6;
display: flex;
align-items: center;
padding: 0 25rpx;
.u-input {
background-color: rgba(240, 240, 240, .5);
height: 80rpx;
}
.u-icon__icon {
font-size: 48rpx !important;
color: #FFFFFF !important;
}
}
/deep/.content-list {
background-color: #fff;
padding: 0 32rpx;
.custom-cell-row {
padding: 40rpx 0;
margin-top: 0;
border-bottom: 2rpx solid #dadada;
&:last-child {
border-bottom: none;
}
}
}
.submitBtn {
width: 90%;
}
.add_driver_btn {
position: fixed;
bottom: 40rpx;
left: 50%;
transform: translateX(-50%);
margin-bottom: 0;
}
}
</style>
<template>
<view style="padding-top: 128rpx;">
<view class="queueSubscribeTitle">
<u--input placeholder="请输入车牌号" border="surround" prefixIcon="search" shape="circle" color="#ffffff"
placeholderStyle="color:#ffffff" @blur="change"></u--input>
</view>
<view v-for="(truck, index) in truckList" :key="index" style="padding: 0 24rpx;">
<view class="flex_center flex_sb" style="height: 130rpx;">
<view class="">
<view style="color: #262626;font-size: 28rpx;font-weight: bolder;">
{{truck.name || ''}}{{' '}}{{truck['facilityMode.name'] || ''}}
</view>
<view style="color: #8C8C8C;font-size: 24rpx; margin-top: 24rpx;">
{{truck['driver1.name'] || ''}}{{' '}}{{truck['driver1.tel'] || ''}}
</view>
</view>
<view @click="choiceTruck(truck.id)"
:class="['queueSubscribeNoChoice', currentDriver.includes(truck.id) ?'queueSubscribeChoice':'']">
</view>
</view>
<u-line></u-line>
</view>
<view v-if="truckList.length" @click="onConfirm" class="queueSubscribeConfirm">
<button>选择车辆</button>
</view>
</view>
</template>
<script>
import { searchTruckList } from '../../api/apiList.js'
export default {
data() {
return {
isMulti: false, //是否分配多辆车, 分配多辆车时支持多选
truckList: [],
currentDriver: '', //单辆车为字符串,多辆车为数组
searchValue: '',
pageNum: 1, //页码
pageSize: 20, //每页条数
loadMore: true, //加载更多
}
},
//下拉刷新
onPullDownRefresh() {
this.pageNum = 1
this.truckList = []
this.getTruckList()
},
// 触底加载更多
onReachBottom() {
if (this.loadMore) {
this.getTruckList()
this.loadMore = false
}
},
onLoad(option) {
const {isMulti, allotTrucks} = JSON.parse(option.data)
const pageTitle = isMulti ? '分配多辆车' : '分配车辆'
this.isMulti = isMulti
this.setNavTitle(pageTitle)
this.getTruckList()
this.initSelect(isMulti, allotTrucks)
},
methods: {
//设置页面头部标题
setNavTitle(title) {
uni.setNavigationBarTitle({ title })
},
//多选车辆时设置默认值
initSelect(isMulti, allotTrucks){
if(isMulti){
this.currentDriver = allotTrucks.map(item => item.id) || []
}
},
getTruckList() {
searchTruckList({
"args": {
pageNum: this.pageNum,
pageSize: this.pageSize,
"restrictions": [{
"field": 'name',
"type": "LK",
"value": this.searchValue
}]
}
}).then(res => {
uni.stopPullDownRefresh()
const data = res.data.data.datas
if (data.length > 0) {
this.truckList = this.truckList.concat(data)
this.pageNum += 1
this.loadMore = true
}
})
},
change(value) {
this.searchValue = value
this.truckList = []
this.pageNum = 1
this.getTruckList()
},
choiceTruck(truckId) {
if(this.isMulti){
const isSelect = this.currentDriver.find(item => item === truckId)
if(isSelect){
const newList = this.currentDriver.filter(item => item !== truckId) //取消选择
this.currentDriver = [...newList]
} else {
this.currentDriver = this.currentDriver.concat(truckId) //选择
}
} else {
this.currentDriver = truckId
}
},
onConfirm() {
const _this = this
const flag = _this.isMulti ? _this.currentDriver.length : _this.currentDriver
if(flag){
let truckInfo = {}
if(_this.isMulti){ //分配多车
const datas = []
_this.currentDriver.map(truckId => {
const info = _this.truckList.find(item => item.id === truckId)
datas.push(info)
})
truckInfo = [...datas]
} else {
truckInfo = _this.truckList.find(item => item.id === _this.currentDriver)
}
uni.$emit('onAddMassAssignTruck', truckInfo)
uni.navigateBack()
} else {
uni.showToast({
title: '请选择车辆',
icon:'none',
duration: 1500
})
}
}
}
}
</script>
<style lang="scss">
.queueSubscribeTitle {
width: 100%;
height: 128rpx;
background-color: #2E75E6;
display: flex;
align-items: center;
padding: 0 25rpx;
position: fixed;
top: 0;
z-index: 1;
.u-input {
background-color: rgba(240, 240, 240, .5);
height: 80rpx;
border: none;
}
.u-icon__icon {
font-size: 48rpx !important;
color: #FFFFFF !important;
}
}
.queueSubscribeNoChoice {
border: 2rpx solid #BFBFBF;
width: 40rpx;
height: 40rpx;
border-radius: 20rpx;
line-height: 40rpx;
text-align: center;
color: #FFFFFF;
font-weight: bolder;
}
.queueSubscribeChoice {
border: none;
background-color: #2E75E6;
}
.queueSubscribeConfirm {
position: sticky;
background-color: #FFFFFF;
padding: 24rpx;
bottom: 0;
button {
width: 686rpx;
height: 88rpx;
border-radius: 44rpx;
line-height: 88rpx;
background-image: linear-gradient(90deg, #2E75E6, #5E58EE);
color: #FFFFFF;
font-weight: bolder;
font-size: 32rpx;
}
}
</style>
<template>
<view class="reserveDock content_box">
<shipmentBriefInfo />
<view class="select-date flex_sb">
<view class="prevDate" :class="{forbidClick:isToday}" @click="onPrev">前一天</view>
<view class="currentDate">{{convertTime(timestamp)}}</view>
<view class="nextDate" @click="onNext">后一天</view>
</view>
<!-- 道口选择 -->
<view class="selectDock" v-if="dockList.length">
<bs-customCell label="月台" labelCol="2" wrapCol="9.5">
<text slot="value" @click="onVisible" style="display: block;">{{showEnums[dockId]}}</text>
<u-icon slot="right-icon" name="arrow-right" size="36" @click="onVisible" />
</bs-customCell>
</view>
<!-- 可选日期列表 -->
<view class="dock-time-table">
<view class="table-title flex flex_center">
<!-- <view class="vertical-separate" /> -->
<text class="font_bolder">选择时段</text>
</view>
<view class="table-label">
<u-row>
<u-col span="6"> 时段</u-col>
<u-col span="4">可预约</u-col>
<u-col span="2" textAlign="center">选择</u-col>
</u-row>
</view>
<view class="table-value-list">
<u-empty mode="data" textSize='32' iconSize="160" text="暂无可预约时间" v-if="!dockTimes.length" />
<view :class="['table-value-item', reserveTimeId === item.id ? 'activeClass' : '']"
v-for="item in dockTimes" :key="item.id" @click="onSelectTime(item.id)">
<u-row>
<!-- 可预约时间 -->
<u-col span="6"> {{item.startTime}} - {{item.endTime}}</u-col>
<u-col span="4.3">
<!-- 可预约量 -->
<template>
<!-- 可预约车次 -->
<!-- <text>{{item.shipmentCapacity - item.actualShipments}}</text> -->
<!-- 可预约件数 -->
<!-- <text>{{item.qtyCapacity - item.actualQty}}</text> -->
<!-- 可预约重量 -->
<!-- <text>{{item.weightCapacity - item.actualWeight}}千克</text> -->
<!-- 可预约体积 -->
<text :style="{'color': item.volumeCapacity - item.actualVolume > 0 ? '' : '#AAAAAA'}">
{{item.volumeCapacity - item.actualVolume}}
</text>
</template>
</u-col>
<u-col span="2" textAlign="center">
<u-radio-group :value="reserveTimeId" placement="column">
<u-radio checked="true" :size="40" :iconSize="32" :name="item.id" @change="onSelectTime(item.id)" :disabled="item.volumeCapacity - item.actualVolume < 0"/>
</u-radio-group>
</u-col>
</u-row>
</view>
</view>
</view>
<!-- 预约按钮 -->
<view class="operation-btn flex_sb">
<button class="backBtn common_btn" @click="openCancelPop">取消预约</button>
<button class="submitBtn common_btn" :style="reserveTimeId === ''?'background-color:#f8f8f8;color: #8c8c8c;background: none;':''" :disabled="reserveTimeId === ''" @click="onConfirm">预约</button>
</view>
<!-- 类型选择动作面板 -->
<bs-selectPicker ref="mySelectPicker" :pickerEnums="dockList" :visible="visible" @onVisible="onVisible"
@onConfirm="onConfirmPicker" />
<view class="reservePop">
<u-popup :show="cancelPop" mode="center">
<view>
<view class="cancel_pop_header">取消预约</view>
<view class="cancel_pop_content">{{`是否取消 ${reserveTime.arrivalDay} ${reserveTime.arrivalTime}-${reserveTime.departureTime} ${showEnums[dockId]?"在":''}${ showEnums[dockId] || ''} 的预约`}}</view>
<view class="cancel_pop_foot flex_sb">
<button @click="cancelPop = false">取消</button>
<button class="submitBtn" @click="onCancel">确认</button>
</view>
</view>
</u-popup>
</view>
</view>
</template>
<script>
import { searchDockList, searchDockTime, loadDockBooking, dockBookingCancel } from '../../api/apiList';
import { formatTime, formatGMT } from '../../utils/util';
export default {
data() {
return {
dockTimes: [], //道口可预约时间列表
dockId: "", //道口id
addressId: '', //地址id
stopsId: '', //站点id
reserveTimeId: '', //当前可预约时间表id
timestamp: new Date().getTime(), //当前日期时间
dockList: [], //道口地址枚举
showEnums: {}, //页面显示使用
visible: false,
cancelPop: false,
reserveTime:{}
}
},
computed: {
listenChange() {
const { dockId, timestamp } = this
return { dockId, timestamp }
},
isToday() {
return new Date(this.timestamp).toDateString() === new Date().toDateString() || new Date(this.timestamp) < new Date()
},
},
watch: {
listenChange(val) {
this.onReloadDockTime()
}
},
onLoad(options) {
const { stopsId, locationId, arrivalDay, arrivalTime, departureTime, dockId } = JSON.parse(options.data)
this.stopsId = stopsId
this.addressId = locationId
this.reserveTime = {
arrivalDay,arrivalTime,departureTime
}
this.getDockList()
if(dockId){
this.dockId = dockId
}
},
methods: {
//获取道口枚举
getDockList() {
const _this = this
const reqData = {
"args": {
"pageNum": 1,
"pageSize": 100,
"restrictions": [{
"field": "address.id",
"type": "EQ",
"value": this.addressId
}]
}
}
searchDockList(reqData).then(res => {
const datas = res.data.data.datas
let optionEnums = []
let showEnums = {}
datas.map(item => {
showEnums[item.id] = item.name
optionEnums.push({ label: item.name, value: item.id })
})
if (optionEnums.length && !_this.dockId) {
const dockId = optionEnums[0].value
_this.dockId = dockId
}
_this.setPickerValue(_this.dockId)
this.dockList = [...optionEnums]
this.showEnums = showEnums
})
},
//Picker弹窗
onVisible() {
const { visible, dockId } = this
if (visible) {
this.visible = false
} else {
this.setPickerValue(dockId)
this.visible = true
}
},
setPickerValue(dockId) {
const mySelectPicker = this.$refs.mySelectPicker
const index = this.dockList.findIndex(item => item.value === dockId)
mySelectPicker.setDefaultValue(index)
},
//确认选择
onConfirmPicker(value) {
const isReload = this.dockId !== value
if (isReload) { //仅切换道口时刷新道口可预约时间
this.dockId = value
}
this.visible = false
},
//刷新道口预约时间
onReloadDockTime() {
const { dockId, addressId, timestamp } = this
const workDate = formatTime(new Date(timestamp), 'D') //格式化时间
const reqData = {
"args": {
"pageNum": 1,
"pageSize": 100,
"restrictions": [{
"field": "address.id",
"type": "EQ",
"value": addressId
}, {
"field": "dock.id",
"type": "EQ",
"value": dockId
}, {
"field": "workDate",
"type": "EQ",
"value": workDate
}]
}
}
searchDockTime(reqData).then(res => {
const that = this
const datas = res.data.data.datas
const dateArr = []
datas.map(date => { //格式化后台返回时间
date.startTime = formatGMT(date.startTime, 'H')
date.endTime = formatGMT(date.endTime, 'H')
that.reserveTimeId = !that.reserveTimeId &&
formatGMT(timestamp,'D') === that.reserveTime.arrivalDay &&
date.startTime === that.reserveTime.arrivalTime &&
date.endTime === that.reserveTime.departureTime ? date.id : that.reserveTimeId
dateArr.push(date)
})
this.dockTimes = [...dateArr]
})
},
//选择预约时间
onSelectTime(id) {
const currentTime = this.dockTimes.find(item => item.id === id)
if (currentTime.volumeCapacity - currentTime.actualVolume > 0) { // 判断是否可选
this.reserveTimeId = id
} else {
uni.showToast({
title: '所选时段已约满,请选择其它时段',
icon: 'none',
duration: 3000
})
}
},
//确认预约
onConfirm() {
const { stopsId, reserveTimeId } = this
const reqData = {
"args": {
"selectedIds": [stopsId],
"additionalIds": {
"": {
"bizName": "md.DockTimeTable",
"selectedIds": [reserveTimeId]
}
}
}
}
loadDockBooking(reqData).then(res => {
if (res.data.messageType === 'success') {
uni.showToast({
title: '预约成功',
duration: 3000
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
})
},
//取消预约
onCancel() {
this.cancelPop = false
const { stopsId } = this
const reqData = {
"args":
{
"selectedIds":
[
stopsId
]
}
}
dockBookingCancel(reqData).then(res => {
if (res.data.messageType === 'success') {
uni.showToast({
title: '预约取消成功',
duration: 3000
})
setTimeout(() => {
uni.navigateBack()
}, 1500)
}
})
},
openCancelPop(){
if(this.reserveTime.arrivalDay){
this.cancelPop = true
}else{
uni.showToast({
title:"暂无预约时间",
icon:'none',
duration: 2000
})
}
},
//前一天 24h转时间戳 24*60*60*1000
onPrev() {
this.timestamp -= 86400000
},
//后一天
onNext() {
this.timestamp += 86400000
},
//页面展示时间戳转换为日期
convertTime(timestamp) {
if (!timestamp) return
const nowDate = new Date(timestamp)
const year = nowDate.getFullYear();
const month = nowDate.getMonth() + 1;
const date = nowDate.getDate();
const day = nowDate.getDay();
const dayList = { //转换为大写星期
'0': '日',
'1': '一',
'2': '二',
'3': '三',
'4': '四',
'5': '五',
'6': '六',
}
return `${year}${ month}${date}日 周${dayList[day]}`
},
}
}
</script>
<style lang="scss">
.reserveDock {
font-size: 28rpx;
/deep/.u-empty__text{
margin-bottom: 24rpx;
}
.select-date {
background-color: #FFFFFF;
padding: 40rpx 32rpx;
font-weight: bolder;
.prevDate,
.nextDate {
color: #5B8BFC
}
.forbidClick{
pointer-events: none;
color: #BFBFBF;
}
}
.selectDock {
margin-top: 24rpx;
background-color: #FFFFFF;
padding: 40rpx 32rpx;
/deep/.custom-cell-row {
margin-top: 0;
.custom-cell-label {
color: #8C8C8C;
}
}
}
.dock-time-table {
margin-top: 40rpx;
background-color: #FFFFFF;
.table-title {
padding: 32rpx;
.vertical-separate {
height: 40rpx;
border-left: 7rpx solid #797979;
margin-right: 20rpx;
}
}
.table-label {
padding: 10rpx 32rpx;
color: #8C8C8C;
background-color: #FAFAFA;
}
/deep/.table-value-list {
padding: 0 32rpx;
.table-value-item {
margin: 40rpx 0;
padding-right: 10rpx;
.u-radio {
justify-content: center;
}
}
.activeClass {
color: #2E5BFB;
}
}
}
.reservePop{
/deep/.u-popup{
flex: none !important;
.u-popup__content{
width: 620rpx;
height: 378rpx;
border-radius: 24rpx;
padding: 32rpx;
.cancel_pop_header{
width: 144rpx;
height: 50rpx;
font-size: 36rpx;
line-height: 50rpx;
}
.cancel_pop_content{
margin-top: 40rpx;
width: 556rpx;
height: 80rpx;
text-align: center;
font-size: 28rpx;
}
.cancel_pop_foot{
margin-top: 64rpx;
button{
width: 262rpx;
height: 80rpx;
font-size: 32rpx;
color: #2e75e6;
border-radius: 40rpx;
border: 2rpx solid #2e75e6;
background-color: #FFFFFF;
}
.submitBtn{
background-color: #2e75e6 !important;
color: #FFFFFF !important;
border: none !important;
}
}
}
}
}
}
</style>
<template>
<scroll-view class="shipmentDetail content_box">
<shipmentCard :propData="shipmentData" />
<view class="operation-btn" style="margin-top: 10rpx;margin-bottom: 0;">
<button class="common_btn" @click="onNavTransfer" data-action="transferAndChangeTruck">中转换车</button>
<button class="common_btn" @click="onNavTransfer" data-action="transferAndUnload">中转卸货</button>
<button class="common_btn" @click="onNavAllot" data-path="/subpkg/allotTruck/allotTruck">配车</button>
<button class="common_btn" @click="onNavAllot" data-path="/subpkg/signFor/signFor">纸质签收</button>
<view style="width: 370rpx" />
<view class="shipmentDetail-list content_box">
<!-- <u-empty mode="data" textSize='32' iconSize="160" text="暂无订单详细数据" v-if="isEmpty" /> -->
<!-- 基本信息 -->
<view class="module-title flex">
<!-- <view class="vertical-separate" /> -->
<text class="font_bolder">运单信息</text>
</view>
<!-- 预约站点 -->
<view class="module-title flex_sb">
<text>预约站点</text>
<view class="flex_center" @click="onNavShipmentLbs" data-path="/subpkg/shipmentLbs/shipmentLbs">
<view class="t-icon t-icon-view-track"></view>
<text style="margin-left: 10rpx; color: #434343; font-weight: 400;">查看轨迹</text>
<view class="shipmentDetail-item">
<bs-customCell label="运单号 :" :value="shipmentList.shipment_no" labelCol="2" wrapCol="10" />
<bs-customCell label="订单号 :" :value="shipmentList.order_no" labelCol="2" wrapCol="10" />
<bs-customCell label="始发地 :" :value="shipmentList.source_location_name" labelCol="2" wrapCol="10" />
<bs-customCell label="目的地 :" :value="shipmentList.dest_location_name" labelCol="2" wrapCol="10" />
<view class=" flex_sb">
<view style="width: 50%;float: left;">
<bs-customCell label="承运商 :" :value="shipmentList.carrier" labelCol="4" wrapCol="6" />
</view>
<view style="width: 50%;float: left;">
<bs-customCell label="车辆 :" :value="shipmentList.truck_no" labelCol="4" wrapCol="6" />
</view>
</view>
</view>
<view class="station-list">
<view class="station-item flex_center flex_sb" v-for="item in stopsDatas" :key="item.stopsId"
@click.capture="onClickStops(item)">
<view class="station-type" :style="{'background-color': item.loadStop ? '#2E75E6' : '#F7A64A'}">
{{item.loadStop ? '装' : '卸'}}
<view class=" flex_sb">
<view style="width: 50%;float: left;">
<bs-customCell label="司机 :" :value="shipmentList.driver_name" labelCol="4" wrapCol="6" />
</view>
<view style="width: 50%;float: left;">
<bs-customCell label="司机电话 :" :value="shipmentList.driver_tel" labelCol="4.5" wrapCol="6" />
</view>
</view>
<view class=" flex_sb">
<view style="width: 50%;float: left;">
<bs-customCell label="当前节点 :" :value="shipmentList.current_node_label" labelCol="4.5" wrapCol="6" />
</view>
<view style="width: 50%;float: left;">
<bs-customCell label="船公司 :" :value="shipmentList.shipowner" labelCol="4" wrapCol="6" />
</view>
</view>
<view class=" flex_sb">
<view style="width: 50%;float: left;">
<bs-customCell label="提单号 :" :value="shipmentList.bl_no" labelCol="4" wrapCol="6" />
</view>
<view style="width: 50%;float: left;">
<bs-customCell label="运输工具 :" :value="shipmentList.equipment" labelCol="4.5" wrapCol="6" />
</view>
</view>
<view class=" flex_sb">
<view style="width: 50%;float: left;">
<bs-customCell label="航名航次 :" :value="shipmentList.m_vsl_voy" labelCol="4.5" wrapCol="6" />
</view>
<!-- <view style="width: 50%;float: left;">
<bs-customCell label="总毛重 :" :value="shipmentList.weight" labelCol="4.5" wrapCol="6" />
</view> -->
<view style="width: 50%;float: left;">
<bs-customCell label="总体积 :" :value="shipmentList.volume" labelCol="4.5" wrapCol="6" />
</view>
</view>
<view class=" flex_sb">
<view style="width: 50%;float: left;">
<bs-customCell label="总重量 :" :value="shipmentList.weight" labelCol="4.5" wrapCol="6" />
</view>
<view class="station-detail flex_col" @click="onNavReserveDetail(item)">
<view class="flex_sb" :style="[{'margin-top': item.dockId ? '50rpx': '0'} ]">
<view class="station-title font_bolder" @click.stop>{{item.locationName}}</view>
<template v-if="!item.dockId">
<view class="station-item-right flex_center" data-path="/subpkg/reserveDock/reserveDock">
<view class="station-time">
{{item.arrivalTime ? `${item.arrivalDay} ${item.arrivalTime}-${item.departureTime}` : '选择时间'}}
</view>
<view class="t-icon t-icon-rightArrow" />
<view style="width: 50%;float: left;">
<bs-customCell label="总托书 :" :value="shipmentList.pallets" labelCol="4.5" wrapCol="6" />
</view>
</view>
<!-- 节点状态 -->
<uni-collapse v-model="activeNames" @change="onChange">
<view class="outer-frame">
<uni-collapse-item :show-arrow="false" title-border="none" :name="shipmentList.id">
<!-- 自定义标题栏 -->
<template v-slot:title>
<view class="foldPanel-title flex_center">
<text style="flex-grow: 1">节点明细</text>
<!-- 自定义标题栏右侧图标 -->
<view :class="['foldPanel-right-icon', 't-icon', activeNames.includes(shipmentList.id) ? 't-icon-unfold-blue' :'t-icon-fold-blue']" />
</view>
</template>
</view>
<!-- 道口存在时展示样式,反之采用默认展示 -->
<template v-if="item.dockId">
<view style="padding-bottom: 24rpx;">
<bs-customCell :label="item.dockName" labelCol="4.4" wrapCol="7"
:value="`${item.arrivalDay} ${item.arrivalTime}-${item.departureTime}`">
<view slot="right-icon" class="t-icon t-icon-rightArrow" />
</bs-customCell>
<!-- 节点状态 -->
<view class="cargo-detail-table">
<view class="detail-row-title">
<u-row>
<u-col textAlign="center" span="6">当前节点</u-col>
<u-col textAlign="center" span="6">节点时间</u-col>
</u-row>
</view>
<u-empty mode="data" textSize='32' iconSize="160" text="暂无货物明细"
v-if="!cargoEvents.length" />
<view class="detail-col-item" v-for="itm in cargoEvents" :key="itm.id">
<u-row>
<u-col span="6" class="cargo-title" textAlign="center">
<view class="cargo-title">{{itm.current_code_label}}</view>
</u-col>
<u-col span="6" textAlign="center">{{itm.event_time}}</u-col>
</u-row>
</view>
</view>
</template>
</uni-collapse-item>
</view>
</view>
</view>
<view class="module-title">订单列表</view>
<view class="order-list">
<orderCard v-for="item in orderDetails" :key="item.id" :propData="item" />
<view class="order-empty flex_cen" v-if="!orderDetails.length">
<u-empty mode="data" textSize='32' iconSize="160" text="暂无订单" />
</view>
</uni-collapse>
</view>
</scroll-view>
</view>
</template>
<script>
import { getShipmentEvent } from '../../api/apiList.js'
import {
findShipmentDetail,
ordermovementOM,
ordermovementOR,
ordermovementMASS,
findShipmentStops
} from '../../api/apiList.js'
import { formatGMT } from '../../utils/util.js'
const appInstance = getApp()
formatGMT
} from '../../utils/util'
export default {
name: 'shipmentDetail',
options: { styleIsolation: 'shared' },
data() {
return {
shipmentData: '', //运单简要信息
orderDetails: [], //订单明细
shipmentId: '', //运单id
stopsDatas: [], //站点列表
shipmentList: '', //运单列表,当默认为{}时,小程序会自动转结构
cargoEvents:[],//节点明细
isEmpty: true, //是否为空
activeNames: [], //当前展开面板 names => orderIds
}
},
onLoad(options) {
const shipmentId = options.id
const { shipmentBizName } = appInstance.globalData.shipmentInfo
this.shipmentId = shipmentId
this.initOrderDetail(shipmentId, shipmentBizName)
},
onShow() {
this.initData(this.shipmentId)
this.initStops(this.shipmentId)
appInstance.globalData.transferAddress = {} //清除中转数据缓存
const data = getApp().globalData.shipmentDetail
const isEmpty = !Object.keys(data).length
this.shipmentList = data
this.isEmpty = isEmpty
if (!isEmpty) {
this.activeNames = [data.id]
this.onShipmentEvents(data.shipment_no);
}
},
methods: {
//初始化运单信息
initData(shipmentId) {
const data = {
"aux": {
"id": shipmentId
}
}
findShipmentDetail(data).then(res => {
const data = res.data.data
data.header.shipmentDate = formatGMT(data.header.shipmentDate, 'D') //格式化时间
data.header.loadRate = (data.header.loadRate * 100).toFixed() //装载率格式化
this.shipmentData = JSON.stringify(data)
})
},
//初始化站点列表
initStops(shipmentId) {
const reqData = {
"args": {
"pageNum": 1,
"pageSize": 100,
"restrictions": [{
"field": "shipment.id",
"type": "EQ",
"value": shipmentId
}]
}
}
findShipmentStops(reqData).then(res => {
let stopsDatas = res.data.data.datas
let ArrData = []
stopsDatas.sort((a, b) => (a.stopNumber - b.stopNumber || b.loadStop - a.loadStop)) //站点排序
stopsDatas.map(stop => {
ArrData.push({
stopsId: stop.id,
locationName: stop['location.name'],
locationId: stop['location.id'],
dockId: stop['dock.id'],
dockName: stop['dock.name'],
loadStop: stop['loadStop'],
unloadStop: stop['unloadStop'],
arrivalTime: formatGMT(stop['planArrivalTime'], 'M'),
departureTime: formatGMT(stop['planDepartureTime'], 'M'),
arrivalDay: formatGMT(stop['planArrivalTime'], 'D'),
locationAddress: this.getLocationCity(stop), //站点地址
locationOrders: stop.loadOrders || stop.unloadOrders, //订单数
locationQty: stop.planLoadQty || stop.planUnloadQty, //件数数
locationWeight: stop.planLoadWeight || stop.planUnloadWeight, //重量
locationVolume: stop.planLoadVolume || stop.planUnloadVolume, //体积
})
})
this.stopsDatas = ArrData
})
// 折叠面板
onChange(values) {
this.activeNames = values
},
//初始化订单信息
initOrderDetail(shipmentId, shipmentBizName) {
const _this = this
let shipmentMode = ''
switch (shipmentBizName) { //根据shipmentBizName 判断运输模式
case 'tm.MovementShipment':
case 'tm.SectionShipment': //暂时走OM逻辑
shipmentMode = 'OM'
break
case 'tm.MassShipment':
shipmentMode = 'MS'; //大宗运输
break
default:
shipmentMode = 'OR';
}
if(shipmentMode === 'MS'){
const reqData = { "aux": { "id": shipmentId } }
ordermovementMASS(reqData).then(res => {
const data = res.data.data.header
const newDetail = {
'id': data['massOrder.id'], //订单id
'orderNo': data['massOrder.orderNo'], //订单号
'qty': data['massOrder.qty'], //订单件数
'weight': data['massOrder.weight'], //订单重量
'volume': data['massOrder.volume'], //订单体积
'originalAddress.name': data['massOrder.originalAddress.name'], //发货地址
'originalContact.name': data['massOrder.originalContact.name'], //发货人
'originalContact.tel': data['massOrder.originalContact.tel'], //发货人联系方式
'originalContact.remark': data['massOrder.originalContact.remark'], //发货人备注
'destinationAddress.name': data['massOrder.destinationAddress.name'], //收货地址
'destinationContact.name': data['massOrder.destinationContact.name'], //收货人
'destinationContact.tel': data['massOrder.destinationContact.tel'], //收货人联系方式
'destinationContact.remark': data['massOrder.destinationContact.remark'], //收货人备注
'originalRequirement': data['massOrder.originalRequirement'], //提货要求
'destinationRequirement': data['massOrder.destinationRequirement'], //配送要求
'transportRequest': data['massOrder.transportRequest'], //运输要求
'actualPod.podImages': data['massOrder.actualPod.podImages'], //回单图片
}
_this.orderDetails = _this.orderDetails.concat(newDetail)
})
} else {
//获取订单所有节点
onShipmentEvents(shipmentNo) {
const reqData = {
"args": {
"pageNum": 1,
"pageSize": 100,
"restrictions": [{
"field": "shipment.id",
"type": "EQ",
"value": shipmentId
}]
"pageSize": 50,
"shipmentNo": shipmentNo
}
}
const isOM = shipmentMode === 'OM'
const requestFun = isOM ? ordermovementOM : ordermovementOR
requestFun(reqData).then(res => {
const datas = res.data.data.datas
const newDatas = _this.convertData(isOM, datas)
_this.orderDetails = [...newDatas]
})
}
},
//转换请求数据
convertData(isOM, datas) {
let newDatas = []
if (isOM) { //OM模式时自定义数据字段名,默认使用简易的OR模式字段名
datas.map(item => {
newDatas.push({
'id': item.id, //订单id
'orderNo': item.movementNo, //订单号
'qty': item.shipQty, //订单件数
'weight': item.shipWeight, //订单重量
'volume': item.shipVolume, //订单体积
'originalAddress.name': item['originalAddress.name'], //发货地址
'originalContact.name': item['originalAddress.addressContact.name'], //发货人
'originalContact.tel': item['originalAddress.addressContact.tel'], //发货人联系方式
'originalContact.remark': item['originalAddress.addressContact.remark'], //发货人备注
'destinationAddress.name': item['destinationAddress.name'], //收货地址
'destinationContact.name': item['destinationAddress.addressContact.name'], //收货人
'destinationContact.tel': item['destinationAddress.addressContact.tel'], //收货人联系方式
'destinationContact.remark': item['destinationAddress.addressContact.remark'], //收货人备注
'originalRequirement': item['orderRelease.originalRequirement'], //提货要求
'destinationRequirement': item['orderRelease.destinationRequirement'], //配送要求
'transportRequest': item['orderRelease.transportRequest'], //运输要求
'actualPod.podImages': item['orderRelease.actualPod.podImages'], //回单图片
})
})
} else {
newDatas = [...datas]
}
return newDatas
},
//监听面板点击事件
onClickStops(data) {
appInstance.globalData.stopsInfo = data
},
//页面跳转
onNavAllot(e) {
const data = {
shipmentData: JSON.parse(this.shipmentData)
}
const path = e.currentTarget.dataset.path + `?data=${JSON.stringify(data)}`
uni.navigateTo({
url: path,
})
},
//中转操作
onNavTransfer(e) {
const action = e.target.dataset.action
const data = {
selectedId: this.shipmentId,
action
}
uni.navigateTo({
url: `/subpkg/transferChange/transferChange?data=${JSON.stringify(data)}`,
})
},
//跳转预约到站时间
onNavReserveDetail(stopInfo) {
const {stopsId, locationId, arrivalDay, arrivalTime, departureTime, dockId} = stopInfo
const data = {
stopsId,
locationId,
arrivalDay,
arrivalTime,
departureTime,
dockId
}
uni.navigateTo({
url: `/subpkg/reserveDockTime/reserveDockTime?data=${JSON.stringify(data)}`,
})
},
//跳转运单Lbs
onNavShipmentLbs(e) {
const shipmentData = JSON.parse(this.shipmentData)
const {id, shipmentNo} = shipmentData.header
const data = {shipmentId: id, shipmentNo}
const path = e.currentTarget.dataset.path + `?data=${JSON.stringify(data)}`
uni.navigateTo({
url: path,
})
getShipmentEvent(reqData).then(res => {
const datas = res.data.data.datas;
if (datas.length > 0) {
datas.map(item => { //格式化时间
if (item.event_time) {
item.event_time = formatGMT(item.event_time, 'D')
}
})
this.cargoEvents = this.cargoEvents.concat(datas);
}
})
},
}
}
</script>
<style lang="scss">
.shipmentDetail {
padding-bottom: 10rpx;
.module-title {
margin: 24rpx;
}
.order-empty {
min-height: 340rpx;
background-color: #FFFFFF;
}
.station-list {
.shipmentDetail-list {
.module-title {
padding: 32rpx 32rpx 16rpx;
.vertical-separate {
height: 40rpx;
border-left: 7rpx solid #797979;
margin-right: 20rpx;
}
}
.shipmentDetail-item {
padding: 32rpx;
margin-bottom: 24rpx;
background: #FFFFFF;
.detail-title {
font-size: 28rpx;
padding: 8rpx 0 30rpx;
border-bottom: 1rpx solid #E5E5E5;
.station-type {
color: #FFFFFF;
font-size: 32rpx;
font-weight: 500;
margin: 24rpx 24rpx 24rpx 0;
padding: 16rpx 20rpx;
text-align: center;
border-radius: 0 50% 50% 0;
.t-icon-order {
width: 50rpx;
height: 50rpx;
margin-right: 20rpx;
}
}
.station-item {
margin-bottom: 24rpx;
padding-right: 32rpx;
background-color: #FFFFFF;
/deep/.custom-cell-row {
margin-top: 16rpx;
.custom-cell-label {
color: #8C8C8C;
}
}
.station-detail {
flex-grow: 1;
.outer-frame {
margin-top: 32rpx;
border-radius: 16rpx;
border: 2rpx solid #F0F0F0;
overflow: hidden;
.station-time {
.foldPanel-title {
color: #2E75E6;
font-size: 28rpx;
color: #8C8C8C;
margin-right: 8rpx;
white-space: nowrap;
padding-left: 20rpx;
height: 96rpx;
background: rgba(46, 117, 230, .1);
.foldPanel-right-icon {
margin-right: 20rpx;
}
}
/deep/.custom-cell-row {
color: #8C8C8C;
/deep/.cargo-detail-table {
background: #FFFFFF;
padding-bottom: 10rpx;
.detail-row-title {
color: #8C8C8C;
background: #FAFAFA;
padding: 20rpx 0;
}
.custom-cell-value {
text-align: end;
white-space: nowrap;
margin-right: 8rpx;
.detail-col-item {
margin: 20rpx;
.cargo-title {
font-size: 28rpx;
padding-left: 20rpx;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
}
}
}
}
/deep/.t-icon {
background-size: cover !important;
background-position: center !important;
}
.snapshoot image {
margin: 20rpx 15rpx;
width: 140rpx;
height: 140rpx;
}
}
</style>
<template>
<view class="order-tracks" @mouseup="onTouchend">
<!-- #ifndef MP -->
<map id="myMap" style="width: 100vw;height: 100vh;" />
<!-- #endif -->
<!-- #ifdef MP -->
<map id="myMap" style="width: 100vw;height: 100vh;" :polyline="polylines" :markers="markers" :include-points="includePoints" :enable-zoom="true">
<cover-view slot="callout" v-if="shipmentStopShowNumber">
<block v-for="(item,index) in markers" :key="index">
<cover-view class="customCallout shipment-stop-marker" :marker-id="item.id"> {{item.stopNumber}} </cover-view>
</block>
</cover-view>
</map>
<!-- #endif -->
<!--详情弹窗 -->
<view class="stops-steps-popup">
<u-popup :show="true" :overlay='false' round="60">
<view class="drag-btn" @touchstart="onTouchstart" @touchmove="onTouchmove" @touchend="onTouchend"
@mousedown="onTouchstart" @mousemove="onTouchmove" @mouseup="onTouchend">
<view class="drag-icon" />
</view>
<view class="poup-content" :style="{height: popupHeight}">
<!-- 途经站点 -->
<view class="stops-steps">
<view class="font_bolder module-title flex_sb">途经站点</view>
<view style="max-height: 500rpx;overflow-y: auto;">
<u-empty mode="data" textSize='28' iconSize="70" text="暂无详细" v-if="!stopsList.length" />
<!-- 步骤条 -->
<u-steps direction="column" v-else inactiveColor="#2E75E6">
<u-steps-item v-for="(item,index) in stopsList" :key="index">
<view class="slot-icon" slot="icon" style="position: relative;">
<image :src="stepIcon" style="width: 36rpx;height: 36rpx;">
<text class="stepIconNum">{{item.stopNumber}}</text>
</view>
<view :class="['step-desc flex']" slot="desc">
<view class="font_bolder overflowOmitRows" style="margin-right: 48rpx;width: 230rpx;">{{item.name}}</view>
<view class="flex_col">
<template v-if="item.stopNumber === 1">
<view class="flex_center">
<text class="desc-title">计划离开</text>
<text class="desc-value">{{item.planDepartureTime}} </text>
</view>
<view class="flex_center">
<text class="desc-title">实际离开</text>
<text class="desc-value" :style="[{'color': item.statusColor}]"> {{item.actualDepartureTime}} </text>
</view>
</template>
<template v-if="item.stopNumber === 2">
<view class="flex_center">
<text class="desc-title">计划到达</text>
<text class="desc-value">{{item.planArrivalTime}} </text>
</view>
<view class="flex_center">
<text class="desc-title">实际到达</text>
<text class="desc-value" :style="[{'color': item.statusColor}]">{{item.actualArrivalTime}} </text>
</view>
<view class="flex_center">
<text class="desc-title">计划离开</text>
<text class="desc-value">{{item.planDepartureTime}} </text>
</view>
<view class="flex_center">
<text class="desc-title">实际离开</text>
<text class="desc-value" :style="[{'color': item.statusColor}]">{{item.actualDepartureTime}} </text>
</view>
</template>
<template v-if="item.stopNumber === 3">
<view class="flex_center">
<text class="desc-title">计划到达</text>
<text class="desc-value">{{item.planArrivalTime}} </text>
</view>
<view class="flex_center">
<text class="desc-title">实际到达</text>
<text class="desc-value" :style="[{'color': item.statusColor}]">{{item.actualArrivalTime}} </text>
</view>
</template>
</view>
</view>
</u-steps-item>
</u-steps>
</view>
</view>
</view>
</u-popup>
</view>
</view>
</template>
<script>
import { findShipmentLbs, getMap, getMapColor } from '../../api/apiList'
export default {
options: { styleIsolation: 'shared' },
data() {
return {
stopsList: [], //途经站点
shipmentStopShowNumber: false, //运输轨迹站点是否显示数字
completeTracks: [], //补全轨迹
points: [], //实际轨迹
popupHeight: '200rpx', //弹窗高度
isMove: false, //是否可移动
currentPosition: [], //当前位置坐标
mapStyle: 0, //默认地图样式
mapStyleList: [], //地图样式列表
mapTheme: {}, //地图主题色
lbsLowSpeed: 30, //最低速
lbsOverSpeed: 80, //最高速
stepIcon: '',
polylines: [], //仅小程序地图展示数据
markers: [], //仅小程序地图展示数据
includePoints: [], //地图缩放显示所含坐标点,仅小程序地图展示数据
}
},
onLoad: function(options) { //todo 定位为定车辆位置
const { shipmentId, shipmentNo } = JSON.parse(options.data)
this.initData(shipmentId, shipmentNo) //获取LBS数据
//初始化运单事件图片
// #ifdef H5
this.stepIcon = "../../static/img/steps/stepIcon.png"
// #endif
// #ifdef MP
const base64 = 'data:image/jpg;base64,' //小程序不支持png格式,故转为base64
this.stepIcon = base64 + uni.getFileSystemManager().readFileSync("static/img/steps/stepIcon.png",'base64');
// #endif
},
methods: {
//获取地图实例
async getMapInstance() {
let mapCtx = null //MAap 上下文
let newMap = null //MAap 实例
const { serviceProvider, MapIns } = getApp().globalData
// #ifdef MP
newMap = MapIns
mapCtx = uni.createMapContext('myMap')
// #endif
// #ifdef H5
mapCtx = MapIns
newMap = new MapIns.Map('myMap');
if (serviceProvider === 'BMap') { //百度地图初始化设置
const point = new MapIns.Point(112.324224, 33.678136);
newMap.centerAndZoom(point, 5); //初始化地图,设置中心点坐标和地图级别
newMap.addControl(new MapIns.ScaleControl()) // 添加比例尺控件
newMap.enableScrollWheelZoom(); //开启鼠标滚轮缩放
}
let mapStyle = this.mapStyleList[this.mapStyle]; //设置地图样式
newMap.setMapStyle(mapStyle.value)
// #endif
return Promise.resolve({ mapCtx, newMap });
},
//获取地图主题、颜色
findMapThem() {
return new Promise(reslove => {
getMapColor({}).then(res => {
if (res) {
const { mapStyle, mapStyleList, trackColor, shipmentStopShowNumber, lowSpeed, overSpeed} = res.data.data
this.mapStyle = mapStyle
this.mapStyleList = mapStyleList
this.mapTheme = { 'light': trackColor, 'dark': trackColor }
this.shipmentStopShowNumber = shipmentStopShowNumber
this.lbsLowSpeed = lowSpeed
this.lbsOverSpeed = overSpeed
reslove('done')
}
})
})
},
//获取LBS数据
initData(shipmentId, shipmentNo) {
this.$nextTick(async () => {
await this.findMapThem() //获取地图主题色
const { newMap, mapCtx } = await this.getMapInstance() //初始化地图实例
const reqData = {"aux": {id: shipmentId, shipmentNo}} //shipmentNo||shipmentId 528807204405383168
const res = await findShipmentLbs(reqData)
const { stops, completeTracks, tracks, points } = res.data.data || {}
const message = res.data.message
if (message) {
uni.showToast({title: message, icon: 'none', duration: 3000})
}
this.initStops(stops)
this.trackAnalysis(points, newMap, mapCtx) //实际轨迹线路
this.addStopsLine(completeTracks, newMap, mapCtx) //补全轨迹线路
// this.addStopsLine(tracks, newMap, mapCtx) //标准轨迹线路
this.addStopsMarkers(stops, newMap, mapCtx) //添加站点标记
})
},
initStops(stops){
const _this = this
stops.forEach(item => { // 处理每一个经停站是否超时
item.statusColor = _this.getStatusColor(item)
})
this.stopsList = stops.reverse()
},
getStatusColor(item){
let color = '#8C8C8C'
if(item.actualDepartureTime && item.planDepartureTime){ // 实际离开是否超时
color = new Date(item.actualDepartureTime).getTime() - new Date(item.planDepartureTime).getTime() > 0 ? '#EB2F48' : '#3DCCB9'
}
if(item.actualArrivalTime && item.planArrivalTime){ // 实际到达是否超时
color = new Date(item.actualArrivalTimee).getTime() - new Date(item.planArrivalTime).getTime() > 0 ? '#EB2F48' : '#3DCCB9'
}
return color
},
trackAnalysis(points=[], newMap, mapCtx){
if(!points.length) return
let tracks = [{lbsPointList: []}]
for (let i = 0; i < points.length; i++) { //按速度将坐标点分段
let point = points[i]
//相同点去除
if (i > 0 && point.lat === points[i -1].lat && point.lng === points[i - 1].lng) {
continue
}
let status = this.getSpeedType(point)
if (tracks[tracks.length - 1].lbsPointList.length === 0) {
tracks[tracks.length - 1].status = status
} else if (tracks[tracks.length - 1].status !== status) {
tracks.push({lbsPointList: [], status})
}
tracks[tracks.length - 1].lbsPointList.push(point)
}
//分段后拼接轨迹
for (let i = 1; i < tracks.length; i++) {
tracks[i - 1].lbsPointList.push(tracks[i].lbsPointList[0])
}
this.addStopsLine(tracks, newMap, mapCtx)
},
//判断速度类型
getSpeedType(point){
let minSpeed = this.lbsLowSpeed
let maxSpeed = this.lbsOverSpeed
if (point.speed < minSpeed) {
return "LOW_SPEED"
} else if (point.speed > maxSpeed) {
return "HIGH_SPEED"
} else {
return "NORMAL_SPEED"
}
},
//添加站点连线
addStopsLine(tracks, newMap, MapInstance) { //newMap: 地图对象 MapInstance: 地图实例, 小程序中为地图上下文
for (let i in tracks) {
let track = tracks[i]
let lbsPointList = track.lbsPointList
if (lbsPointList.length === 0) {
continue;
}
this.addPolyLine(lbsPointList, track.status, newMap, MapInstance)
}
},
//添加连线
addPolyLine(points, trackStatus, newMap, MapInstance) {
if (!points.length) return
let zIndex = 10;
if (trackStatus === 'STANDARD_TRACK') {
zIndex = 11
} else if (trackStatus === 'COMPLETE_TRACK') {
zIndex = 10
} else {
zIndex = 999
}
const strokeColor = this.getPolyLineColor(trackStatus)
const { serviceProvider } = getApp().globalData
let path = [] //转换线路坐标点
points.forEach(point => {
// #ifndef MP
if (serviceProvider === 'AMap') {
path.push([point.lng, point.lat])
} else {
path.push(new MapInstance.Point(point.lng, point.lat))
}
// #endif
// #ifdef MP
path.push({ latitude: point.lat, longitude: point.lng })
// #endif
})
// #ifndef MP
let line = null
if (serviceProvider === 'AMap') {
// 创建折线实例
line = new MapInstance.Polyline({
path: path,
zIndex,
strokeWeight: 6, // 线条粗细
strokeColor: strokeColor,
showDir: true, //沿路径显示白色箭头
cursor: '', //自定义鼠标悬停时样式
strokeOpacity: 1, //去除路线透明度
});
newMap.add([line]); //添加多个覆盖物[circle, marker]
} else {
line = new MapInstance.Polyline(path, {
sequence: true,
zIndex,
showDir: true, //沿路径显示白色箭头
strokeColor: strokeColor, //连线颜色
strokeWeight: 6, // 线条粗细
strokeStyle: "solid",
strokeOpacity: 1, //去除路线透明度
});
newMap.addOverlay(line);
}
//缩放地图视野
if (serviceProvider === 'AMap') {
newMap.setFitView()
} else {
newMap.setViewport(path);
}
// #endif
// #ifdef MP
const polyline = {
points: path,
width: 6, // 线条粗细
zIndex,
color: strokeColor,
arrowLine: true, //沿路径显示白色箭头
}
this.polylines = this.polylines.concat(polyline)
this.includePoints = this.includePoints.concat(path)
// #endif
},
//添加站点标记
addStopsMarkers(stops, newMap, MapInstance) {
stops.forEach((stop, index) => {
let stopIcon = require('../../static/img/lbs/load-stop.png');
if (this.shipmentStopShowNumber) {
if (stop.unloadStop === true) {
stopIcon = require('../../static/img/lbs/unload-stop.png')
if (stop.loadStop === true) {
stopIcon = require('../../static/img/lbs/load-unload-stop.png')
}
}
} else {
stopIcon = require('../../static/img/lbs/home.png')
}
let marker = null
// #ifndef MP
if (getApp().globalData.serviceProvider === "AMap") {
const newMapIcon = new MapInstance.Icon({
image: stopIcon,// 图标的取图地址
imageSize: new MapInstance.Size(40, 40), // 图标所用图片大小
});
const mapOptions = {
position: [stop.lng, stop.lat],
anchor: 'bottom-center', //icon标记的位置
icon: newMapIcon,
map: newMap,
}
if (this.shipmentStopShowNumber) {
mapOptions.label = {
content: stop.stopNumber,
direction: 'center',
offset: new MapInstance.Pixel(-0.5, 8),
}
} else {
mapOptions.anchor = 'center'
}
marker = new MapInstance.Marker(mapOptions)
newMap.add([marker]);
} else {
const iconSize = new MapInstance.Size(40, 40)
const myIcon = new MapInstance.Icon(stopIcon, iconSize);
const point = new MapInstance.Point(stop.lng, stop.lat);
marker = new MapInstance.Marker(point, { icon: myIcon });
newMap.addOverlay(marker);
}
// #endif
// #ifdef MP
marker = {
id: Number(index), //Mark id应为数字类型
latitude: stop.lat, //纬度
longitude: stop.lng, //经度
iconPath: stopIcon, //显示的图标
stopNumber: stop.stopNumber,
width: 40,
height: 40,
customCallout: { //自定义标记点上方的气泡窗口
anchorY: 50,
anchorX: -0.4,
display: "ALWAYS"
},
}
this.markers = this.markers.concat(marker)
// #endif
})
},
//获取连线颜色
getPolyLineColor(trackStatus) {
let mapIndex = this.mapStyle
let mapStyle = this.mapStyleList[mapIndex]
let lineColor = this.mapTheme[mapStyle.type]
return lineColor[trackStatus]
},
//移动端事件监听
onTouchstart() {
this.isMove = true
},
onTouchend() {
this.isMove = false
},
onTouchmove(e) {
if (this.isMove) {
const { windowHeight } = uni.getSystemInfoSync()
let clientY
if (uni.getSystemInfoSync().platform === 'windows') {
clientY = e.clientY
} else {
clientY = e.touches[0].clientY
}
const height = windowHeight - clientY
if (height <= windowHeight * 0.88 && height >= windowHeight * 0.1) { //判断屏幕间距
this.popupHeight = `${height * 2}rpx` //转换为rpx单位
}
}
}
}
}
</script>
<style lang="scss">
.order-tracks {
//Marker样式
.shipment-stop-marker, /deep/.amap-marker-label{
height: 80rpx;
width: 80rpx;
background-repeat: no-repeat;
background-size: cover;
font-size: 38rpx ;
color: white;
font-weight: bold;
text-align: center;
}
.stops-steps-popup {
position: relative;
/deep/.u-popup__content {
padding: 0 32rpx 20rpx !important;
background: #FFFFFF;
}
.poup-content {
overflow-y: auto;
}
.drag-btn {
width: 100%;
height: 80rpx;
position: absolute;
left: 0;
z-index: 9999999;
&::after {
content: '';
width: 92rpx;
height: 8rpx;
background: #000000;
border-radius: 5rpx;
opacity: 0.6;
position: absolute;
left: 50%;
top: -15%;
transform: translateX(-50%);
}
}
.current-location {
width: 88rpx;
height: 88rpx;
background: #FFFFFF;
box-shadow: 1rpx 3rpx 8rpx 0 rgba(0, 0, 0, 0.08);
border-radius: 24rpx;
display: flex;
justify-content: center;
align-items: center;
position: absolute;
right: 30rpx;
top: -130rpx;
.t-icon-location {
width: 45rpx;
height: 45rpx;
}
}
.module-title {
color: #262626;
font-size: 28rpx;
margin: 20rpx 10rpx;
}
.stops-steps {
border-radius: 32rpx 32rpx 0 0;
/deep/.u-steps-item__wrapper{
width: 50rpx !important;
}
/deep/.u-steps-item__content{
margin-top: 6rpx !important;
}
/deep/.u-text{
display: none !important;
}
.stepIconNum{
font-size: 28rpx;
color: #FFFFFF;
position: absolute;
left: 50%;
top: 40%;
transform: translate(-50%, -50%);
}
.step-desc {
font-size: 32rpx;
margin-left: 10rpx;
.desc-title,
.desc-value {
font-size: 28rpx;
color: #8C8C8C;
white-space: nowrap;
}
.desc-title {
margin-right: 24rpx;
}
}
}
}
}
</style>
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment