init
This commit is contained in:
@@ -0,0 +1,53 @@
|
||||
<!-- 基本信息 - 已完成详情、在途详情、待提货详情 -->
|
||||
<template>
|
||||
<view class="">
|
||||
<view class="baseInfo">
|
||||
<view class="addrCont">
|
||||
<view class="startAddr">{{itemData.startAddress}}</view>
|
||||
<view class="endAddr">{{itemData.endAddress}}</view>
|
||||
</view>
|
||||
<view class="carInfo">
|
||||
<view class="line"> <text>任务编号</text> <text class="ritEl">{{itemData.transportTaskId}}</text> </view>
|
||||
<view class="line"> <text>联系人</text> <text class="ritEl">{{itemData.startHandover}}</text> </view>
|
||||
<view class="line">
|
||||
<text>联系电话</text>
|
||||
<view class="phoneCont">
|
||||
<text class="ritEl">{{itemData.startHandoverPhone}}</text>
|
||||
<image @click="callPhone(itemData.startHandoverPhone)" class="phone" src="../../../static/sj_phone.png" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="line"> <text>提货时间</text> <text class="ritEl">{{itemData.planDepartureTime}}</text> </view>
|
||||
<view class="line"> <text>预计送达时间</text> <text class="ritEl">{{itemData.planArrivalTime}}</text> </view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup >
|
||||
// 获取父组件值、方法
|
||||
const props = defineProps({
|
||||
itemData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
// 拨打电话
|
||||
const callPhone = (phone) => {
|
||||
uni.makePhoneCall({
|
||||
phoneNumber: phone
|
||||
});
|
||||
}
|
||||
</script>
|
||||
<style src="../index.scss" lang="scss"></style>
|
||||
<style lang="scss">
|
||||
.phoneCont{
|
||||
display: flex;
|
||||
align-items: center;
|
||||
.phone{
|
||||
position: relative;
|
||||
padding-left: 10rpx;
|
||||
top: -4rpx;
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
190
project-wl-siji-uniapp-vue3/pages/index/components/ItemList.vue
Normal file
190
project-wl-siji-uniapp-vue3/pages/index/components/ItemList.vue
Normal file
@@ -0,0 +1,190 @@
|
||||
<!-- 任务首页-包含待提货、在途、已完成 -->
|
||||
<template>
|
||||
<view class="">
|
||||
<scroll-view scroll-x="true" class="tabScroll" :scroll-into-view="scrollinto" :scroll-with-animation="true">
|
||||
<view v-for="(item, index) in tabBars" :key="index" :id="'tab' + index" class="scroll-row-item" @click="changeTab(index)">
|
||||
<view :class="tabIndex == index ? 'scroll-row-item-act' : ''">
|
||||
<text class="line"></text>
|
||||
{{ item }}
|
||||
</view>
|
||||
</view>
|
||||
</scroll-view>
|
||||
<!-- 已完成页面 搜索框 - start -->
|
||||
<view class="searchCont" v-if="tabIndex == 2">
|
||||
<SearchInput inputKey="orderId" @searchHandle="searchHandle" ></SearchInput>
|
||||
<view class="timeSearch">
|
||||
<uni-datetime-picker v-model="range" type="daterange" @maskClick="maskClick" rangeSeparator="至" />
|
||||
<view v-show="!isSearch" class="searchBut" @click="searchHandle('time')">
|
||||
<text class="button min" >筛选</text>
|
||||
</view>
|
||||
<view v-show="isSearch" class="searchBut">
|
||||
<text class="button buttonDis1 min">筛选</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 已完成页面 搜索框 - end -->
|
||||
<!-- 滑块内容 对应的是顶部选项卡的切换 :current="tabIndex" 设置的是y方向上可以滚动-->
|
||||
<view class="container">
|
||||
<!-- 垂直滚动区域 scroll和swiper的高度都要给且是一样的高度-->
|
||||
<scroll-view scroll-y="true" class="swiperH" :class="{finshSwiperH: tabIndex == 2}" @scrolltolower="scrolltoupperHandle" :lower-threshold="10">
|
||||
<view class="marg" v-if="itemData.length > 0">
|
||||
<!-- 通用卡片组件 - 待提货、在途 -->
|
||||
<Card v-for="(item, index) in itemData" :data="item" :src="filterUrl(item)" :key="item.id" :type="tabIndex" />
|
||||
</view>
|
||||
<!-- 无数据显示 -->
|
||||
<view v-if="itemData.length === 0 && !loading">
|
||||
<EmptyPage :emptyInfo="emptyInfo" />
|
||||
</view>
|
||||
<!-- end -->
|
||||
<!-- 下拉加载更多Lodding -->
|
||||
<view v-if="loading">
|
||||
<uni-load-more :status="moreStatus" />
|
||||
</view>
|
||||
<!-- end -->
|
||||
</scroll-view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup >
|
||||
import { ref, reactive, onMounted, watchEffect, provide } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
// 组件
|
||||
import Card from '@/components/Card/index.vue'
|
||||
// 取件信息
|
||||
import EmptyPage from '@/components/EmptyPage/index.vue';
|
||||
// searchInput
|
||||
import SearchInput from '@/components/SearchInput/index.vue';
|
||||
|
||||
// 获取父组件值、方法
|
||||
const props = defineProps({
|
||||
itemData: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
moreStatus:{
|
||||
type: String,
|
||||
default: 'loading'
|
||||
},
|
||||
loading:{
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
});
|
||||
|
||||
// ------定义变量------
|
||||
const scrollinto = ref('tab0'); //tab切换
|
||||
const store = useStore();
|
||||
const tabIndex = ref(store.state.taskStatus); //当前tab
|
||||
const scrollH = ref(0); //滚动高度
|
||||
const emptyInfo = ref('未找到相关任务');
|
||||
const tabBars = reactive(['待提货', '在途', '已完成']);
|
||||
const emit = defineEmits(['setTabIndex','searchSubmit']);
|
||||
const page = ref();
|
||||
const pageSize = ref();
|
||||
const taskId = ref(''); // 任务ID
|
||||
const isSearch = ref(true) // 搜索是否可点
|
||||
const range = ref() // 日期选择
|
||||
const orderId = ref('') // 搜索
|
||||
|
||||
// 将对应Id 做provide处理 方便后面使用
|
||||
|
||||
provide('taskId', taskId)
|
||||
|
||||
// ------生命周期------
|
||||
onMounted(() => {
|
||||
// 获取屏幕信息
|
||||
uni.getSystemInfo({
|
||||
success: function(res) {
|
||||
// 获取元素信息
|
||||
let info = uni.createSelectorQuery().select('.swiperH');
|
||||
info
|
||||
.boundingClientRect(function(data) {
|
||||
//data - 各种参数
|
||||
scrollH.value = data.height + 140;
|
||||
})
|
||||
.exec();
|
||||
}
|
||||
});
|
||||
});
|
||||
// 监听日期变更 调试是否可筛选状态
|
||||
watchEffect(() => {
|
||||
if (range.value){
|
||||
isSearch.value = false
|
||||
}
|
||||
})
|
||||
// ------定义方法------
|
||||
|
||||
// 卡片点击去往对应详情的url 处理
|
||||
const filterUrl = (item) => {
|
||||
let src = ''
|
||||
if (tabIndex.value == 0){
|
||||
src = `/pages/index/details?id=${item.id}`
|
||||
} else {
|
||||
switch (Number(item.status)){
|
||||
case 1: // 待提货
|
||||
src = `/pages/index/details?id=${item.id}`
|
||||
break;
|
||||
case 2: // 在途
|
||||
src = `/pages/index/detailsRoad?id=${item.id}`
|
||||
break;
|
||||
case 4: // 已交付
|
||||
src = `/pages/index/refister?id=${item.transportTaskId}&time=${item.actualDepartureTime}`
|
||||
break;
|
||||
case 6: // 已完成(已等级)- 交付之后需要回车等记
|
||||
src = `/pages/index/detailsSuccess?id=${item.id}`
|
||||
break;
|
||||
default: // 3 改派 、5 作废
|
||||
src = ``
|
||||
break;
|
||||
}
|
||||
}
|
||||
return src
|
||||
}
|
||||
// 搜索按钮
|
||||
function searchHandle(type){
|
||||
const params = type == 'time' ? range : type
|
||||
emit('searchSubmit', params)
|
||||
}
|
||||
// 上拉刷新
|
||||
function scrolltoupperHandle(){
|
||||
emit('setTabIndex', tabIndex.value)
|
||||
}
|
||||
// tab选项卡切换轮播
|
||||
const changeTab = index => {
|
||||
// 点击的还是当前数据的时候直接return
|
||||
if (tabIndex.value == index) {
|
||||
return;
|
||||
}
|
||||
tabIndex.value = index;
|
||||
emit('setTabIndex', index)
|
||||
// 滑动
|
||||
// scrollinto.value = 'tab' + index;
|
||||
};
|
||||
//
|
||||
function maskClick(time){
|
||||
console.log(time)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style src="../index.scss" lang="scss"></style>
|
||||
<style lang="scss">
|
||||
.searchCont{
|
||||
background-color: #fff;
|
||||
padding: 0rpx 30rpx 30rpx 30rpx;
|
||||
.searchBut{
|
||||
width: 180rpx;
|
||||
margin-left: 40rpx;
|
||||
}
|
||||
.timeSearch{
|
||||
display: flex;
|
||||
padding-top: 20rpx;
|
||||
}
|
||||
::v-deep .uniui-clear::before{
|
||||
display: none;
|
||||
}
|
||||
::v-deep .uni-input-wrapper{
|
||||
background-color: #f4f4f4;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,55 @@
|
||||
<!-- 订单列表 - 已完成、待提货、在途的详情页面中使用 -->
|
||||
<template>
|
||||
<view class="orderCont">
|
||||
<view class="search">
|
||||
<uni-icons class="searchIcon" @click="search()" type="search"></uni-icons>
|
||||
<input type="text" class="searchInput" @input="onKeyInput" @confirm="search" confirm-type="search" placeholder="请输入运单号" />
|
||||
</view>
|
||||
<view class="items">
|
||||
<view class="item" v-for="item in itemData">
|
||||
<text class="odd">{{item.id}}</text>
|
||||
<text class="piece">{{item.count}} 件</text>
|
||||
<text class="weight">{{item.totalWeight}} kg</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup >
|
||||
import { ref } from 'vue'
|
||||
// 获取父组件值、方法
|
||||
const props = defineProps({
|
||||
itemData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
searchHandle: {
|
||||
type: Function(),
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['searchHandle']);
|
||||
|
||||
// 订单号
|
||||
const orderId = ref('')
|
||||
|
||||
// 搜索按钮
|
||||
const search = ()=>{
|
||||
if(orderId.value == ''){
|
||||
uni.showToast({
|
||||
title: '请输入运单号',
|
||||
duration: 1000,
|
||||
icon: 'none'
|
||||
});
|
||||
return
|
||||
}
|
||||
emit('searchHandle', orderId.value)
|
||||
}
|
||||
// 输入值记录到orderId
|
||||
const onKeyInput = (event) => {
|
||||
orderId.value = event.detail.value
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style src="../index.scss" lang="scss"></style>
|
||||
@@ -0,0 +1,42 @@
|
||||
<!-- 运算路线 -->
|
||||
<template>
|
||||
<view class="routeItem" >
|
||||
<view class="routeLine">
|
||||
<view class="routePoint">
|
||||
<view class="tit"> <text>{{itemData.startProvince}}</text> </view>
|
||||
<view class=""> <text>{{itemData.startCity}}</text> </view>
|
||||
</view>
|
||||
<view class="route">
|
||||
<view class="line" style="">
|
||||
<image class="LineImg" src="../../../static/sj_route_line.png" mode=""></image>
|
||||
</view>
|
||||
</view>
|
||||
<view class="routePoint">
|
||||
<view class="tit"> <text>{{itemData.endProvince}}</text> </view>
|
||||
<view class=""> <text>{{itemData.endCity}}</text> </view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="navigat" v-if="type == 'navigation'">
|
||||
<image class="naviIcon" src="../../../static/sj_navigation.png" mode=""></image>
|
||||
<view class="" @click="() => openMap(itemData.startAddress,itemData.endAddress, '开始导航')">
|
||||
<text>开始导航</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup >
|
||||
import { openMap } from '@/utils/index.js'
|
||||
// 获取父组件值、方法
|
||||
const props = defineProps({
|
||||
type: {
|
||||
type: String,
|
||||
default: 'navigation'
|
||||
},
|
||||
itemData: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style src="../index.scss" lang="scss"></style>
|
||||
@@ -0,0 +1,71 @@
|
||||
|
||||
<!-- 单选按钮组件 - 回车登记页面使用 -->
|
||||
<template>
|
||||
<view class="refisterCards">
|
||||
<view class="title">
|
||||
{{data.title}}
|
||||
</view>
|
||||
<view class="items">
|
||||
<view class="item" v-for="(item, index) in data.data" :key="index" @click="activeHandel(item, index)">
|
||||
<view :class="{buttonDel: true, buttonAct: actVal == item}">
|
||||
<text>{{item}}</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- 布局填充用 -->
|
||||
<view v-if="data.data.length % 3 == 1 || data.data.length % 3 == 2" class="item"></view>
|
||||
<view v-if="data.data.length % 3 == 1" class="item"></view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
<script setup >
|
||||
import {ref} from 'vue'
|
||||
// 获取父组件值、方法
|
||||
const props = defineProps({
|
||||
// 展示源数据
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {}
|
||||
},
|
||||
// 设置默认值
|
||||
value: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
// 选择数据的key
|
||||
choiceKey: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
});
|
||||
|
||||
const emit = defineEmits(['choiceHandel'])
|
||||
|
||||
// 标记选择项
|
||||
let actVal = ref(props.value)
|
||||
|
||||
// 点击选中
|
||||
function activeHandel(val, index){
|
||||
actVal.value = val
|
||||
const param = {key: props.choiceKey, value:index+1, keyInt:val}
|
||||
emit('choiceHandel', param)
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.refisterCards{
|
||||
.title{
|
||||
color: #2A2929;
|
||||
margin-bottom: 30rpx;
|
||||
}
|
||||
.items{
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
.item{
|
||||
width: 29.5%;
|
||||
padding-bottom: 30rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
191
project-wl-siji-uniapp-vue3/pages/index/delayed.vue
Normal file
191
project-wl-siji-uniapp-vue3/pages/index/delayed.vue
Normal file
@@ -0,0 +1,191 @@
|
||||
<!-- 延迟交货 -->
|
||||
<template>
|
||||
<!-- end -->
|
||||
<view class="pageBox">
|
||||
<!-- title -->
|
||||
<DetailsNav title="延迟提货"></DetailsNav>
|
||||
<!-- 取件状态列表 -->
|
||||
<view class="container">
|
||||
<view class="delayedCont">
|
||||
<view class="lineBoder">
|
||||
<text>原定时间</text>
|
||||
<text class="label">{{ orgTime }}</text>
|
||||
</view>
|
||||
<view class="lineBoder">
|
||||
<text>延迟时间</text>
|
||||
<picker
|
||||
mode="time"
|
||||
:value="time"
|
||||
start="09:01"
|
||||
end="21:01"
|
||||
@change="bindTimeChange"
|
||||
>
|
||||
<view class="uni-input timeInfo">
|
||||
<text>{{ time }}</text>
|
||||
<image
|
||||
class="iconImg"
|
||||
src="../../static/sj_open_rit.png"
|
||||
mode=""
|
||||
></image>
|
||||
</view>
|
||||
</picker>
|
||||
</view>
|
||||
<view class="">
|
||||
<textarea
|
||||
class="textInput"
|
||||
v-model="formData.delayReason"
|
||||
placeholder-style="color:#818181"
|
||||
placeholder="请输入延迟提货原因"
|
||||
/>
|
||||
</view>
|
||||
<view class="butCont">
|
||||
<text
|
||||
class="button buttonDis1"
|
||||
v-show="formData.delayReason == '' || time == '不可超过两小时'"
|
||||
>提交</text
|
||||
>
|
||||
<text
|
||||
class="button"
|
||||
v-show="formData.delayReason != '' && time != '不可超过两小时'"
|
||||
@click="formActioin()"
|
||||
>提交</text
|
||||
>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
// 导入接口
|
||||
import { PutDelay } from '@/pages/api/index.js';
|
||||
// 导入组件
|
||||
import DetailsNav from '@/components/DetailsNav/index.vue';
|
||||
// 主体部分
|
||||
|
||||
// ------定义变量------
|
||||
const orgTime = ref(); // 原定提货时间
|
||||
const time = ref('不可超过两小时');
|
||||
// 提交数据
|
||||
const formData = ref({
|
||||
id: '',
|
||||
delayTime: '',
|
||||
delayReason: '',
|
||||
});
|
||||
|
||||
// ------生命周期------
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1].$page.options;
|
||||
orgTime.value = currentPage.time;
|
||||
formData.value.id = currentPage.id;
|
||||
});
|
||||
|
||||
// ------定义方法------
|
||||
const bindTimeChange = (e) => {
|
||||
time.value = e.detail.value;
|
||||
};
|
||||
// 延迟提货提交
|
||||
const formActioin = async () => {
|
||||
const data = formData.value;
|
||||
// 延迟时间必选
|
||||
if (time.value == '不可超过两小时') {
|
||||
uni.showToast({
|
||||
title: '请选择延迟时间!',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 请填写延迟提货原因
|
||||
if (data.delayReason.trim() == '') {
|
||||
uni.showToast({
|
||||
title: '请填写延迟提货原因!',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
return;
|
||||
}
|
||||
// 网络慢的时候添加按钮loading
|
||||
let times = setTimeout(() => {
|
||||
uni.showLoading({
|
||||
title: 'loading',
|
||||
mask:true
|
||||
});
|
||||
}, 500);
|
||||
// 原始时间
|
||||
const lastTime = orgTime.value;
|
||||
// 替换处理 延迟的实际时间
|
||||
data.delayTime = lastTime.replace(/(\d+){2}(:\d+){1}/, time.value);
|
||||
// 延迟提货
|
||||
await PutDelay(formData.value)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
// 操作成功后清除loading
|
||||
setTimeout(function () {
|
||||
uni.hideLoading();
|
||||
}, 500);
|
||||
clearTimeout(times);
|
||||
uni.showToast({
|
||||
title: '延迟提货提交成功',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/index/index',
|
||||
});
|
||||
}, 500);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
};
|
||||
</script>
|
||||
<style lang="scss">
|
||||
@import url('@/styles/theme.scss');
|
||||
.delayedCont {
|
||||
background-color: var(--neutral-color-white);
|
||||
margin: 30rpx;
|
||||
padding: 30rpx 30rpx 40rpx 30rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: var(--font-size-14);
|
||||
.lineBoder {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 40rpx 0;
|
||||
border-bottom: solid 1px var(--neutral-color-cancel);
|
||||
.label {
|
||||
color: var(--neutral-color-font);
|
||||
}
|
||||
}
|
||||
.textInput {
|
||||
font-size: var(--font-size-14);
|
||||
background-color: var(--neutral-color-cancel);
|
||||
width: 100%;
|
||||
border-radius: 20rpx;
|
||||
margin-top: 40rpx;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.butCont {
|
||||
width: 60%;
|
||||
margin: 40rpx auto 0 auto;
|
||||
}
|
||||
.timeInfo {
|
||||
display: flex;
|
||||
line-height: 48rpx;
|
||||
.iconImg {
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
338
project-wl-siji-uniapp-vue3/pages/index/details.vue
Normal file
338
project-wl-siji-uniapp-vue3/pages/index/details.vue
Normal file
@@ -0,0 +1,338 @@
|
||||
<!-- 待提货 - 详情 -->
|
||||
<template>
|
||||
<!-- 详情 -->
|
||||
<view class="details">
|
||||
<DetailsNav title="任务详情"></DetailsNav>
|
||||
<!-- 取件状态列表 -->
|
||||
<view class="container">
|
||||
<!-- 垂直滚动区域 scroll和swiper的高度都要给且是一样的高度-->
|
||||
<scroll-view scroll-y="true" class="swiperH">
|
||||
<view class="cont" v-if="Object.keys(itemData).length > 0">
|
||||
<!-- 通用卡片组件 - 待提货 - 带开关 -->
|
||||
<CardCont title="基本信息" :open="true">
|
||||
<DetailsBaseInfo :itemData="itemData"></DetailsBaseInfo>
|
||||
</CardCont>
|
||||
<CardCont title="车辆司机信息">
|
||||
<view class="carInfo">
|
||||
<view class="line">
|
||||
<text class="tit">车牌号</text>
|
||||
<text class="ritEl">{{ itemData.licensePlate }}</text>
|
||||
</view>
|
||||
<view class="line">
|
||||
<text class="tit">司机姓名</text>
|
||||
<text class="ritEl">{{ itemData.driverName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</CardCont>
|
||||
<CardCont title="运输路线">
|
||||
<RouteCont :itemData="itemData" type="route"></RouteCont>
|
||||
</CardCont>
|
||||
<CardCont title="物品信息" :label="`共计: ${amount}单`">
|
||||
<OrderCont
|
||||
:itemData="orders"
|
||||
@searchHandle="searchHandle"
|
||||
></OrderCont>
|
||||
</CardCont>
|
||||
<CardCont title="提货信息">
|
||||
<view class="upPicCont">
|
||||
<view class="title">请拍照上传回单凭证</view>
|
||||
<uni-file-picker
|
||||
v-model="cargoPickUpPicture"
|
||||
fileMediatype="image"
|
||||
mode="grid"
|
||||
limit="3"
|
||||
@select="selectA"
|
||||
/>
|
||||
</view>
|
||||
<view class="upPicCont">
|
||||
<view class="title">请拍照上传货品照片</view>
|
||||
<uni-file-picker
|
||||
v-model="cargoPicture"
|
||||
fileMediatype="image"
|
||||
mode="grid"
|
||||
limit="3"
|
||||
@select="selectB"
|
||||
/>
|
||||
</view>
|
||||
</CardCont>
|
||||
</view>
|
||||
<!-- 无数据显示 -->
|
||||
<view v-if="Object.keys(itemData).length === 0">
|
||||
<EmptyPage emptyInfo="暂无数据!" />
|
||||
</view>
|
||||
<!-- end -->
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
</view>
|
||||
<!-- footer -->
|
||||
<view class="footCont">
|
||||
<view class="footButCan">
|
||||
<text class="buttonCancel" @click="delayedHandle()">延迟提货</text>
|
||||
</view>
|
||||
<view class="footBut">
|
||||
<text v-show="isTake" class="button" @click="takeGoods()">提货</text>
|
||||
<text v-show="!isTake" class="buttonDis1">提货</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
onMounted,
|
||||
onUpdated,
|
||||
watch,
|
||||
watchEffect,
|
||||
computed,
|
||||
inject,
|
||||
} from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { positionUploadHandle } from '@/utils/index.js';
|
||||
// 导入接口
|
||||
import {
|
||||
GetTaskDetails,
|
||||
GetTaskDetailsOrders,
|
||||
TakeDelivery,
|
||||
} from '@/pages/api/index.js';
|
||||
|
||||
// 导入组件
|
||||
import DetailsNav from '@/components/DetailsNav/index.vue';
|
||||
import EmptyPage from '@/components/EmptyPage/index.vue';
|
||||
import DetailsBaseInfo from './components/DetailsBaseInfo.vue';
|
||||
import OrderCont from './components/OrderCont.vue';
|
||||
import RouteCont from './components/RouteCont.vue';
|
||||
|
||||
// 主体部分
|
||||
import CardCont from '@/components/CardCont/index.vue';
|
||||
// 接口调用
|
||||
import { upload } from '@/pages/api/index.js';
|
||||
|
||||
// ------定义变量------
|
||||
const store = useStore(); //vuex获取储存数据
|
||||
|
||||
const itemData = ref([]);
|
||||
const orders = ref([]); // 货物信息列表
|
||||
const amount = ref(0); // 货物信息总数
|
||||
|
||||
const id = ref(''); // 任务Id
|
||||
const cargoPickUpPicture = ref([]); // 提货凭证
|
||||
const cargoPicture = ref([]); // 货物照片
|
||||
const isTake = ref(true); // 是否可提货
|
||||
const taskId = ref('');
|
||||
|
||||
// ------生命周期------
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1].$page.options;
|
||||
id.value = currentPage.id;
|
||||
getDetailsInfo();
|
||||
});
|
||||
|
||||
// 监听是否可以提货
|
||||
watchEffect(
|
||||
[
|
||||
cargoPickUpPicture,
|
||||
() => {
|
||||
isTake.value = cargoPickUpPicture.length > 0 && cargoPicture.length > 0;
|
||||
},
|
||||
],
|
||||
[
|
||||
cargoPicture,
|
||||
() => {
|
||||
isTake.value = cargoPickUpPicture.length > 0 && cargoPicture.length > 0;
|
||||
},
|
||||
]
|
||||
);
|
||||
|
||||
// ------定义方法------
|
||||
// 获取任务详情的数据
|
||||
const getDetailsInfo = async () => {
|
||||
// 获取任务详情的数据
|
||||
await GetTaskDetails(id.value)
|
||||
.then((res) => {
|
||||
const { data } = res;
|
||||
if (res.code === 200) {
|
||||
itemData.value = data;
|
||||
getOrders(data.transportTaskId);
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
};
|
||||
// 获取物品订单信息
|
||||
const getOrders = async (orderId, transportOrderId = '') => {
|
||||
const params = {
|
||||
transportOrderId,
|
||||
taskId: orderId,
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
};
|
||||
await GetTaskDetailsOrders(params)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
amount.value = res.data.counts ? res.data.counts : 0;
|
||||
orders.value = res.data.items;
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
};
|
||||
|
||||
// 物品信息搜索
|
||||
function searchHandle(transportOrderId) {
|
||||
getOrders(itemData.value.transportTaskId, transportOrderId);
|
||||
}
|
||||
|
||||
// 延迟提货
|
||||
function delayedHandle() {
|
||||
const data = itemData.value;
|
||||
uni.navigateTo({
|
||||
url: `/pages/index/delayed?id=${data.id}&time=${data.planDepartureTime}`,
|
||||
});
|
||||
}
|
||||
|
||||
// 提货
|
||||
async function takeGoods() {
|
||||
const cargoPickUpPictureStr = cargoPickUpPicture.value
|
||||
.map((n) => n.path)
|
||||
.join();
|
||||
const cargoPictureStr = cargoPicture.value.map((n) => n.path).join();
|
||||
const params = {
|
||||
id: id.value,
|
||||
cargoPickUpPicture: cargoPickUpPictureStr,
|
||||
cargoPicture: cargoPictureStr,
|
||||
};
|
||||
// 网络慢的时候添加按钮loading
|
||||
let times = setTimeout(() => {
|
||||
uni.showLoading({
|
||||
title: 'loading',
|
||||
mask:true
|
||||
});
|
||||
}, 500);
|
||||
await TakeDelivery(params)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
// 提货之后上报位置
|
||||
positionUploadHandle(true);
|
||||
// 操作成功后清除loading
|
||||
setTimeout(function () {
|
||||
uni.hideLoading();
|
||||
}, 500);
|
||||
clearTimeout(times);
|
||||
uni.showToast({
|
||||
title: '提货完成',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index',
|
||||
});
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
// 文件上传
|
||||
async function uploadHande(e, type) {
|
||||
await upload(e)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
if (res.data) {
|
||||
isTake.value = true;
|
||||
const name = res.data.split('/')[res.data.split('/').length - 1]; // .at(-1) 新语法APP不支持
|
||||
let data = {
|
||||
url: res.data,
|
||||
name,
|
||||
extName: name.split('.')[name.split('.').length - 1],
|
||||
};
|
||||
if (type == 'cargoPickUpPicture') {
|
||||
cargoPickUpPicture.value = [...cargoPickUpPicture.value, data];
|
||||
} else {
|
||||
cargoPicture.value = [...cargoPicture.value, data];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.showToast({
|
||||
title: '图片上传失败!请联系管理员',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
});
|
||||
}
|
||||
// 文件选择并上传 - 回单凭证上传
|
||||
async function selectA(e) {
|
||||
cargoPickUpPicture.value = [];
|
||||
const tempFiles = e.tempFiles[0];
|
||||
if (
|
||||
tempFiles.size < 1024 * 5 * 1024 &&
|
||||
(tempFiles.extname == 'png' ||
|
||||
tempFiles.extname == 'jpg' ||
|
||||
tempFiles.extname == 'jpeg' ||
|
||||
tempFiles.extname == 'gif')
|
||||
) {
|
||||
uploadHande(e, 'cargoPickUpPicture');
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '上传图片大小不能超过5M,格式需为jpg、png、gif',
|
||||
duration: 2000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
}
|
||||
// 文件选择并上传 - 货品照片上传
|
||||
async function selectB(e) {
|
||||
cargoPicture.value = [];
|
||||
const tempFiles = e.tempFiles[0];
|
||||
if (
|
||||
tempFiles.size < 1024 * 5 * 1024 &&
|
||||
(tempFiles.extname == 'png' ||
|
||||
tempFiles.extname == 'jpg' ||
|
||||
tempFiles.extname == 'jpeg' ||
|
||||
tempFiles.extname == 'gif')
|
||||
) {
|
||||
uploadHande(e, 'cargoPicture');
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '上传图片大小不能超过5M,格式需为jpg、png、gif',
|
||||
duration: 2000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style src="./index.scss" lang="scss"></style>
|
||||
<style lang="scss" scoped>
|
||||
.details {
|
||||
height: calc(100vh - 120rpx);
|
||||
.swiperH {
|
||||
height: calc(100vh - 210rpx);
|
||||
padding-bottom: 26rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
378
project-wl-siji-uniapp-vue3/pages/index/detailsRoad.vue
Normal file
378
project-wl-siji-uniapp-vue3/pages/index/detailsRoad.vue
Normal file
@@ -0,0 +1,378 @@
|
||||
<!-- 在途 - 详情 -->
|
||||
<template>
|
||||
<!-- 详情 -->
|
||||
<view class="details">
|
||||
<DetailsNav title="任务详情"></DetailsNav>
|
||||
<!-- 取件状态列表 -->
|
||||
<view class="container">
|
||||
<!-- 垂直滚动区域 scroll和swiper的高度都要给且是一样的高度-->
|
||||
<scroll-view scroll-y="true" class="swiperH">
|
||||
<view class="cont" v-if="Object.keys(itemData).length > 0">
|
||||
<!-- 通用卡片组件 - 在途 - 带开关 -->
|
||||
<CardCont title="基本信息" :open="true">
|
||||
<DetailsBaseInfo :itemData="itemData"></DetailsBaseInfo>
|
||||
</CardCont>
|
||||
<!-- 司机信息 -->
|
||||
<CardCont title="车辆司机信息">
|
||||
<view class="carInfo">
|
||||
<view class="line">
|
||||
<text class="tit">车牌号</text>
|
||||
<text class="ritEl">{{ itemData.licensePlate }}</text>
|
||||
</view>
|
||||
<view class="line">
|
||||
<text class="tit">司机姓名</text>
|
||||
<text class="ritEl">{{ itemData.driverName }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</CardCont>
|
||||
<CardCont title="运输路线">
|
||||
<RouteCont :itemData="itemData"></RouteCont>
|
||||
</CardCont>
|
||||
<!-- 物品信息 -->
|
||||
<CardCont title="物品信息" :label="`共计: ${amount}单`">
|
||||
<OrderCont
|
||||
:itemData="orders"
|
||||
@searchHandle="searchHandle"
|
||||
></OrderCont>
|
||||
</CardCont>
|
||||
<!-- 异常信息 -->
|
||||
<CardCont title="异常信息">
|
||||
<view v-for="(item, index) in itemData.exception" :key="index">
|
||||
<view class="delay">
|
||||
<view class="info">
|
||||
<view class="line">
|
||||
<text>上报时间 </text
|
||||
><text class="desc"> {{ item.exceptionTime }} </text>
|
||||
</view>
|
||||
<view class="line">
|
||||
<text>异常类型 </text
|
||||
><text class="desc"> {{ item.exceptionType }} </text>
|
||||
</view>
|
||||
<view class="line">
|
||||
<text>继续运输 </text
|
||||
><text class="desc"> {{ item.processResults }} </text>
|
||||
</view>
|
||||
</view>
|
||||
<image
|
||||
@click="ExceptionHandle('?id=' + item.exceptionId)"
|
||||
class="goInfoIcon"
|
||||
src="../../static/sj_open_rit.png"
|
||||
mode=""
|
||||
></image>
|
||||
</view>
|
||||
</view>
|
||||
</CardCont>
|
||||
<!-- 交货信息 -->
|
||||
<CardCont title="交货信息">
|
||||
<view class="upPicCont">
|
||||
<view class="title">请拍照上传回单凭证</view>
|
||||
<uni-file-picker
|
||||
v-model="cargoPickUpPicture"
|
||||
fileMediatype="image"
|
||||
mode="grid"
|
||||
limit="3"
|
||||
@select="selectA"
|
||||
/>
|
||||
</view>
|
||||
<view class="upPicCont">
|
||||
<view class="title">请拍照上传货品照片</view>
|
||||
<uni-file-picker
|
||||
v-model="cargoPicture"
|
||||
fileMediatype="image"
|
||||
mode="grid"
|
||||
limit="3"
|
||||
@select="selectB"
|
||||
/>
|
||||
</view>
|
||||
</CardCont>
|
||||
</view>
|
||||
<!-- 无数据显示 -->
|
||||
<view v-if="Object.keys(itemData).length === 0">
|
||||
<EmptyPage emptyInfo="暂无数据!" />
|
||||
</view>
|
||||
<!-- end -->
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
</view>
|
||||
<!-- footer -->
|
||||
<view class="footCont">
|
||||
<view class="footButCan">
|
||||
<text class="buttonCancel" @click="ExceptionHandle()">上报异常</text>
|
||||
</view>
|
||||
<view class="footBut">
|
||||
<text v-show="isTake" class="button" @click="takeGoods()">交付</text>
|
||||
<text v-show="!isTake" class="buttonDis1">交付</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
mounted() {
|
||||
// #ifdef APP-NVUE
|
||||
const eventChannel = this.$scope.eventChannel; // 兼容APP-NVUE
|
||||
// #endif
|
||||
// #ifndef APP-NVUE
|
||||
const eventChannel = this.getOpenerEventChannel();
|
||||
// #endif
|
||||
eventChannel.emit('acceptDataFromOpenedPage', {
|
||||
data: 'data from test page',
|
||||
});
|
||||
eventChannel.emit('someEvent', {
|
||||
data: 'data from test page for someEvent',
|
||||
});
|
||||
// 监听acceptDataFromOpenerPage事件,获取上一页面通过eventChannel传送到当前页面的数据
|
||||
eventChannel.on('acceptDataFromOpenerPage');
|
||||
},
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, watchEffect } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
import { positionUploadHandle } from '@/utils/index.js';
|
||||
// 导入接口
|
||||
import {
|
||||
GetTaskDetails,
|
||||
GetTaskDetailsOrders,
|
||||
Deliver,
|
||||
} from '@/pages/api/index.js';
|
||||
// 导入组件
|
||||
import DetailsNav from '@/components/DetailsNav/index.vue';
|
||||
import EmptyPage from '@/components/EmptyPage/index.vue';
|
||||
import DetailsBaseInfo from './components/DetailsBaseInfo.vue';
|
||||
import OrderCont from './components/OrderCont.vue';
|
||||
import RouteCont from './components/RouteCont.vue';
|
||||
// 接口调用
|
||||
import { upload } from '@/pages/api/index.js';
|
||||
// 主体部分
|
||||
import CardCont from '@/components/CardCont/index.vue';
|
||||
|
||||
// ------定义变量------
|
||||
const store = useStore(); //vuex获取储存数据
|
||||
const itemData = ref([]);
|
||||
const orders = ref([]); // 货物信息列表
|
||||
const amount = ref(0); // 货物信息总数
|
||||
|
||||
const id = ref(''); // 任务Id
|
||||
const cargoPickUpPicture = ref([]); // 提货凭证
|
||||
const cargoPicture = ref([]); // 货物照片
|
||||
const isTake = ref(false);
|
||||
|
||||
// ------生命周期------
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1].$page.options;
|
||||
id.value = currentPage.id;
|
||||
getDetailsInfo();
|
||||
getOrders();
|
||||
});
|
||||
// 监听是否可以提货
|
||||
watchEffect(
|
||||
[
|
||||
cargoPickUpPicture,
|
||||
() => {
|
||||
isTake.value = cargoPickUpPicture.length > 0 && cargoPicture.length > 0;
|
||||
},
|
||||
],
|
||||
[
|
||||
cargoPicture,
|
||||
() => {
|
||||
isTake.value = cargoPickUpPicture.length > 0 && cargoPicture.length > 0;
|
||||
},
|
||||
]
|
||||
);
|
||||
// ------定义方法------
|
||||
// 获取任务详情的数据
|
||||
const getDetailsInfo = async () => {
|
||||
// 获取任务详情的数据
|
||||
await GetTaskDetails(id.value)
|
||||
.then((res) => {
|
||||
const { data } = res;
|
||||
if (res.code === 200) {
|
||||
itemData.value = data;
|
||||
getOrders(data.transportTaskId);
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
};
|
||||
// 获取物品订单信息
|
||||
const getOrders = async (orderId, transportOrderId = '') => {
|
||||
const params = {
|
||||
transportOrderId,
|
||||
taskId: orderId,
|
||||
page: 1,
|
||||
pageSize: 100,
|
||||
};
|
||||
await GetTaskDetailsOrders(params)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
amount.value = res.data.counts ? res.data.counts : 0;
|
||||
orders.value = res.data.items;
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
};
|
||||
// 物品信息搜索
|
||||
function searchHandle(transportOrderId) {
|
||||
getOrders(itemData.value.transportTaskId, transportOrderId);
|
||||
}
|
||||
// 上报异常 、异常详情
|
||||
function ExceptionHandle(src) {
|
||||
uni.showToast({
|
||||
title: '上报异常暂时接口还在实现中!',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
return false;
|
||||
const url = src ? `/pages/index/exception${src}` : '/pages/index/exception';
|
||||
uni.navigateTo({ url });
|
||||
}
|
||||
|
||||
// 交付
|
||||
async function takeGoods() {
|
||||
const cargoPickUpPictureStr = cargoPickUpPicture.value
|
||||
.map((n) => n.path)
|
||||
.join();
|
||||
const cargoPictureStr = cargoPicture.value.map((n) => n.path).join();
|
||||
const params = {
|
||||
id: id.value,
|
||||
transportCertificate: cargoPickUpPictureStr,
|
||||
deliverPicture: cargoPictureStr,
|
||||
};
|
||||
// 网络慢的时候添加按钮loading
|
||||
let times = setTimeout(() => {
|
||||
uni.showLoading({
|
||||
title: 'loading',
|
||||
mask:true
|
||||
});
|
||||
}, 500);
|
||||
await Deliver(params)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
// 交付之后 上报位置
|
||||
positionUploadHandle(true);
|
||||
// 操作成功后清除loading
|
||||
setTimeout(function () {
|
||||
uni.hideLoading();
|
||||
}, 500);
|
||||
clearTimeout(times);
|
||||
uni.showToast({
|
||||
title: '提货完成',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
uni.redirectTo({
|
||||
url: '/pages/index/index',
|
||||
});
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
// 图片上传
|
||||
const imageValue = ref([]);
|
||||
const upImg = ref(null);
|
||||
// 文件上传
|
||||
async function uploadHande(e, type) {
|
||||
await upload(e)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
if (res.data) {
|
||||
isTake.value = true;
|
||||
const name = res.data.split('/')[res.data.split('/').length - 1]; // .at(-1) 新语法APP不支持
|
||||
let data = {
|
||||
url: res.data,
|
||||
name,
|
||||
extName: name.split('.')[name.split('.').length - 1],
|
||||
};
|
||||
if (type == 'cargoPickUpPicture') {
|
||||
cargoPickUpPicture.value = [...cargoPickUpPicture.value, data];
|
||||
} else {
|
||||
cargoPicture.value = [...cargoPicture.value, data];
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
uni.showToast({
|
||||
title: '图片上传失败!请联系管理员',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
});
|
||||
}
|
||||
// 文件选择并上传 - 回单凭证上传
|
||||
async function selectA(e) {
|
||||
cargoPickUpPicture.value = [];
|
||||
const tempFiles = e.tempFiles[0];
|
||||
if (
|
||||
tempFiles.size < 1024 * 5 * 1024 &&
|
||||
(tempFiles.extname == 'png' ||
|
||||
tempFiles.extname == 'jpg' ||
|
||||
tempFiles.extname == 'jpeg' ||
|
||||
tempFiles.extname == 'gif')
|
||||
) {
|
||||
uploadHande(e, 'cargoPickUpPicture');
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '上传图片大小不能超过5M,格式需为jpg、png、gif',
|
||||
duration: 2000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
}
|
||||
// 文件选择并上传 - 货品照片上传
|
||||
async function selectB(e) {
|
||||
cargoPicture.value = [];
|
||||
const tempFiles = e.tempFiles[0];
|
||||
if (
|
||||
tempFiles.size < 1024 * 5 * 1024 &&
|
||||
(tempFiles.extname == 'png' ||
|
||||
tempFiles.extname == 'jpg' ||
|
||||
tempFiles.extname == 'jpeg' ||
|
||||
tempFiles.extname == 'gif')
|
||||
) {
|
||||
uploadHande(e, 'cargoPicture');
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: '上传图片大小不能超过5M,格式需为jpg、png、gif',
|
||||
duration: 2000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style src="./index.scss" lang="scss"></style>
|
||||
<style lang="scss" scoped>
|
||||
.details {
|
||||
height: calc(100vh - 120rpx);
|
||||
.swiperH {
|
||||
height: calc(100vh - 240rpx);
|
||||
padding-bottom: 26rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
189
project-wl-siji-uniapp-vue3/pages/index/detailsSuccess.vue
Normal file
189
project-wl-siji-uniapp-vue3/pages/index/detailsSuccess.vue
Normal file
@@ -0,0 +1,189 @@
|
||||
<!-- 已完成 - 详情 -->
|
||||
<template>
|
||||
<!-- 详情 -->
|
||||
<view class="details">
|
||||
<DetailsNav title="任务详情"></DetailsNav>
|
||||
<!-- 取件状态列表 -->
|
||||
<view class="container">
|
||||
<!-- 垂直滚动区域 scroll和swiper的高度都要给且是一样的高度-->
|
||||
<scroll-view scroll-y="true" class="successSwiperH">
|
||||
<view class="cont" v-if="Object.keys(itemData).length > 0">
|
||||
<!-- 通用卡片组件 - 待提货 - 带开关 -->
|
||||
<CardCont title="基本信息" :open="true">
|
||||
<DetailsBaseInfo :itemData="itemData"></DetailsBaseInfo>
|
||||
</CardCont>
|
||||
<CardCont title="车辆司机信息">
|
||||
<view class="carInfo">
|
||||
<view class="line"> <text class="tit">车牌号</text> <text class="ritEl">{{itemData.licensePlate}}</text>
|
||||
</view>
|
||||
<view class="line"> <text class="tit">司机姓名</text> <text class="ritEl">{{itemData.driverName}}</text>
|
||||
</view>
|
||||
</view>
|
||||
</CardCont>
|
||||
<CardCont title="运输路线">
|
||||
<RouteCont :itemData="itemData" type="route"></RouteCont>
|
||||
</CardCont>
|
||||
<CardCont title="物品信息" :label="`共计: ${amount}单`">
|
||||
<OrderCont :itemData="orders" @searchHandle="searchHandle"></OrderCont>
|
||||
</CardCont>
|
||||
<CardCont title="提货凭证">
|
||||
<view class="upPicCont">
|
||||
<div class="tit">回单凭证</div>
|
||||
<view class="upPicContImg">
|
||||
<img class="image" v-for="item in itemData.cargoPickUpPicture" :src="item" alt="" srcset="">
|
||||
</view>
|
||||
</view>
|
||||
<view class="upPicCont">
|
||||
<div class="tit">提货照片</div>
|
||||
<view class="upPicContImg">
|
||||
<img class="image" v-for="item in itemData.cargoPicture" :src="item" alt="" srcset="">
|
||||
</view>
|
||||
</view>
|
||||
</CardCont>
|
||||
<CardCont title="交货信息">
|
||||
<view class="upPicCont">
|
||||
<div class="tit">回单凭证</div>
|
||||
<view class="upPicContImg">
|
||||
<img class="image" v-for="item in itemData.deliverPicture" :src="item" alt="" srcset="">
|
||||
</view>
|
||||
</view>
|
||||
<view class="upPicCont">
|
||||
<div class="tit">货品照片</div>
|
||||
<view class="upPicContImg">
|
||||
<img class="image" v-for="item in itemData.transportCertificate" :src="item" alt="" srcset="">
|
||||
</view>
|
||||
</view>
|
||||
</CardCont>
|
||||
<CardCont title="异常信息">
|
||||
|
||||
</CardCont>
|
||||
</view>
|
||||
<!-- 无数据显示 -->
|
||||
<view v-if="Object.keys(itemData).length === 0">
|
||||
<EmptyPage emptyInfo="暂无数据!" />
|
||||
</view>
|
||||
<!-- end -->
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import {
|
||||
ref,
|
||||
reactive,
|
||||
onMounted,
|
||||
onUpdated,
|
||||
watch,
|
||||
watchEffect,
|
||||
computed,
|
||||
inject
|
||||
} from 'vue';
|
||||
import {
|
||||
useStore
|
||||
} from 'vuex';
|
||||
// 导入接口
|
||||
import {
|
||||
GetTaskDetails,
|
||||
GetTaskDetailsOrders,
|
||||
TakeDelivery
|
||||
} from '@/pages/api/index.js';
|
||||
|
||||
// 导入组件
|
||||
import DetailsNav from '@/components/DetailsNav/index.vue'
|
||||
import EmptyPage from '@/components/EmptyPage/index.vue'
|
||||
import DetailsBaseInfo from './components/DetailsBaseInfo.vue'
|
||||
import OrderCont from './components/OrderCont.vue'
|
||||
import RouteCont from './components/RouteCont.vue'
|
||||
|
||||
// 主体部分
|
||||
import CardCont from '@/components/CardCont/index.vue';
|
||||
// 接口调用
|
||||
import {
|
||||
upload
|
||||
} from '@/pages/api/index.js'
|
||||
|
||||
// ------定义变量------
|
||||
const store = useStore(); //vuex获取储存数据
|
||||
|
||||
const itemData = ref({});
|
||||
const orders = ref([]); // 货物信息列表
|
||||
const amount = ref(0); // 货物信息总数
|
||||
|
||||
const id = ref('') // 任务Id
|
||||
const cargoPickUpPicture = ref([]) // 提货凭证
|
||||
const cargoPicture = ref([]) // 货物照片
|
||||
const isTake = ref(true) // 是否可提货
|
||||
const taskId = ref('')
|
||||
|
||||
// ------生命周期------
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1].$page.options;
|
||||
id.value = currentPage.id;
|
||||
getDetailsInfo();
|
||||
});
|
||||
|
||||
|
||||
|
||||
// ------定义方法------
|
||||
// 获取任务详情的数据
|
||||
const getDetailsInfo = async () => {
|
||||
// 获取任务详情的数据
|
||||
await GetTaskDetails(id.value)
|
||||
.then(res => {
|
||||
const {
|
||||
data
|
||||
} = res
|
||||
if (res.code === 200) {
|
||||
itemData.value = data
|
||||
getOrders(data.transportTaskId)
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {});
|
||||
};
|
||||
// 获取物品订单信息
|
||||
const getOrders = async (orderId, transportOrderId='' ) => {
|
||||
const params = {
|
||||
transportOrderId,
|
||||
taskId: orderId,
|
||||
page: 1,
|
||||
pageSize: 100
|
||||
}
|
||||
await GetTaskDetailsOrders(params)
|
||||
.then(res => {
|
||||
if (res.code === 200) {
|
||||
amount.value = res.data.counts ? res.data.counts : 0
|
||||
orders.value = res.data.items
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {});
|
||||
}
|
||||
|
||||
// 物品信息搜索
|
||||
function searchHandle(transportOrderId) {
|
||||
getOrders(itemData.value.transportTaskId, transportOrderId)
|
||||
}
|
||||
</script>
|
||||
<style src="./index.scss" lang="scss"></style>
|
||||
<style lang="scss" scoped>
|
||||
.details {
|
||||
.successSwiperH {
|
||||
height: calc(100vh - 160rpx);
|
||||
padding-bottom: 26rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
279
project-wl-siji-uniapp-vue3/pages/index/exception.vue
Normal file
279
project-wl-siji-uniapp-vue3/pages/index/exception.vue
Normal file
@@ -0,0 +1,279 @@
|
||||
<!-- 上报异常 -->
|
||||
<template>
|
||||
<!-- end -->
|
||||
<view class="pageBox">
|
||||
<!-- title -->
|
||||
<DetailsNav :title="title"></DetailsNav>
|
||||
<!-- 取件状态列表 -->
|
||||
<view class="container">
|
||||
<view class="delayedCont">
|
||||
<view class="lineBoder">
|
||||
<text>异常时间</text>
|
||||
<text v-if="type == 'details'">{{ exceptionsDeta.time }}</text>
|
||||
<!-- <text v-else class="label">请选择</text> -->
|
||||
<uni-datetime-picker
|
||||
v-else
|
||||
type="datetime"
|
||||
v-model="exceptionsDeta.time"
|
||||
:clear-icon="false"
|
||||
/>
|
||||
</view>
|
||||
<view class="lineBoder">
|
||||
<text>上报位置</text>
|
||||
<text v-if="type == 'details'">{{ exceptionsDeta.province }}</text>
|
||||
<text v-else class="label">请选择</text>
|
||||
</view>
|
||||
<view class="lineBoder">
|
||||
<text>异常类型</text>
|
||||
<text v-if="type == 'details'">{{ exceptionsDeta.type }}</text>
|
||||
<view v-else class="label">
|
||||
<Select :options="typeOptions"></Select>
|
||||
</view>
|
||||
</view>
|
||||
<view v-if="type == 'details'" class="lineBoder noborder">
|
||||
<view class="" style="width: 100%">
|
||||
<view>
|
||||
<text>异常描述</text>
|
||||
</view>
|
||||
<view>
|
||||
<text class="desc">{{ exceptionsDeta.description }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view v-else class="lineBoder">
|
||||
<view class="" style="width: 100%">
|
||||
<text>异常描述</text>
|
||||
<textarea
|
||||
class="textInput"
|
||||
v-model="formData.delayReason"
|
||||
placeholder-style="color:#818181"
|
||||
placeholder="请输入异常描述"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<view class="delayedCont">
|
||||
<view :class="{ upPicCont: true, setBottom: type == 'details' }">
|
||||
<view class="title">上传图片(最多6张)</view>
|
||||
<view v-if="type == 'details'" class="exceptionImages">
|
||||
<image
|
||||
class="exceptionImage"
|
||||
v-for="(item, index) in exceptionsDeta.images"
|
||||
:src="item"
|
||||
key="index"
|
||||
mode=""
|
||||
></image>
|
||||
</view>
|
||||
<uni-file-picker
|
||||
v-else
|
||||
v-model="imageValue"
|
||||
fileMediatype="image"
|
||||
mode="grid"
|
||||
@select="select"
|
||||
@progress="progress"
|
||||
@success="success"
|
||||
@fail="fail"
|
||||
/>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
<view class="footCont positionBot" style="justify-content: center">
|
||||
<view class="footBut" style="width: 400rpx; flex: initial">
|
||||
<text class="button" @click="exceptionHandle()">提交</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
// 导入接口
|
||||
import { Exception, ExceptionDetails } from '@/pages/api/index.js';
|
||||
// 导入组件
|
||||
import DetailsNav from '@/components/DetailsNav/index.vue';
|
||||
import Select from '@/components/Select/index.vue';
|
||||
// 主体部分
|
||||
|
||||
// ------定义变量------
|
||||
const imageValue = ref([]); // 上次图片
|
||||
const type = ref('add'); // 类型
|
||||
const title = ref('上报异常'); // 标题
|
||||
const exceptionId = ref(''); // 异常的id - 详情
|
||||
const exceptionsDeta = ref({});
|
||||
// 类型
|
||||
const typeOptions = [
|
||||
{ title: '发动机启动困难', value: '1' },
|
||||
{ title: '不着车,漏油', value: '2' },
|
||||
{ title: '照明失灵', value: '3' },
|
||||
{ title: '有异常响动', value: '4' },
|
||||
{ title: '排烟异常、温度异常', value: '5' },
|
||||
{ title: '其他问题', value: '6' },
|
||||
];
|
||||
|
||||
// 提交数据
|
||||
const formData = ref({
|
||||
id: '',
|
||||
delayTime: '',
|
||||
delayReason: '',
|
||||
});
|
||||
// ------生命周期------
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1].$page.options;
|
||||
if (Object.keys(currentPage).length > 0) {
|
||||
type.value = 'details';
|
||||
title.value = '异常详情';
|
||||
exceptionId.value = currentPage.exceptionId;
|
||||
getDetails();
|
||||
} else {
|
||||
type.value = 'add';
|
||||
title.value = '上报异常';
|
||||
}
|
||||
});
|
||||
// ------定义方法------
|
||||
// 上报异常
|
||||
const exceptionHandle = async () => {
|
||||
// 网络慢的时候添加按钮loading
|
||||
let times = setTimeout(() => {
|
||||
uni.showLoading({
|
||||
title: 'loading',
|
||||
mask:true
|
||||
});
|
||||
}, 500);
|
||||
// 上报异常
|
||||
await Exception(formData)
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
// 操作成功后清除loading
|
||||
setTimeout(function () {
|
||||
uni.hideLoading();
|
||||
}, 500);
|
||||
clearTimeout(times);
|
||||
uni.showToast({
|
||||
title: '提交成功',
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
setTimeout(() => {
|
||||
uni.navigateTo({
|
||||
url: '/pages/index/index',
|
||||
});
|
||||
}, 500);
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
};
|
||||
|
||||
// 获取异常详情数据
|
||||
async function getDetails() {
|
||||
await ExceptionDetails({ exceptionId: exceptionId })
|
||||
.then((res) => {
|
||||
if (res.code === 200) {
|
||||
const data = res.data;
|
||||
data.images = [
|
||||
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.duoziwang.com%2F2018%2F04%2F2411191727687.jpg&refer=http%3A%2F%2Fimg.duoziwang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658645143&t=8fed835d7336cac9b3fedb170766a678',
|
||||
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.duoziwang.com%2F2017%2F03%2F26%2FB1371.jpg&refer=http%3A%2F%2Fimg.duoziwang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658645178&t=07a6e8bcc05b75d3dd86c369c70f7274',
|
||||
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.duoziwang.com%2F2017%2F03%2F26%2FB2154.jpg&refer=http%3A%2F%2Fimg.duoziwang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658645143&t=54afc59b141abad9f7799f005e20c944',
|
||||
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.duoziwang.com%2F2019%2F05%2F08211345608033.jpg&refer=http%3A%2F%2Fimg.duoziwang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658645143&t=c8a2aa7a7bd874381fbb98bc4223e6fe',
|
||||
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.duoziwang.com%2F2017%2F03%2F26%2FB1365.jpg&refer=http%3A%2F%2Fimg.duoziwang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658645143&t=55b411cc1ad4aea58cef44fe11438f72',
|
||||
'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fimg.duoziwang.com%2F2019%2F04%2F07090912704156.jpg&refer=http%3A%2F%2Fimg.duoziwang.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1658645143&t=fa6d42ffb721c66f1e42548895a64e89',
|
||||
];
|
||||
exceptionsDeta.value = res.data;
|
||||
} else {
|
||||
uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none',
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err) => {});
|
||||
}
|
||||
|
||||
// 获取上传状态
|
||||
function select(e) {
|
||||
console.log('选择文件:', e);
|
||||
}
|
||||
// 获取上传进度
|
||||
function progress(e) {
|
||||
console.log('上传进度:', e);
|
||||
}
|
||||
|
||||
// 上传成功
|
||||
function success(e) {
|
||||
console.log('上传成功');
|
||||
}
|
||||
|
||||
// 上传失败
|
||||
function fail(e) {
|
||||
console.log('上传失败:', e);
|
||||
}
|
||||
</script>
|
||||
<style src="./index.scss" lang="scss"></style>
|
||||
<style lang="scss">
|
||||
@import url('@/styles/theme.scss');
|
||||
.delayedCont {
|
||||
background-color: var(--neutral-color-white);
|
||||
margin: 30rpx;
|
||||
padding: 30rpx 30rpx 40rpx 30rpx;
|
||||
border-radius: 20rpx;
|
||||
font-size: var(--font-size-14);
|
||||
.lineBoder {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 40rpx 0;
|
||||
border-bottom: solid 1px var(--neutral-color-cancel);
|
||||
.label {
|
||||
color: var(--neutral-color-font);
|
||||
}
|
||||
}
|
||||
.noborder {
|
||||
border: none;
|
||||
}
|
||||
.desc {
|
||||
display: inline-block;
|
||||
padding-top: 40rpx;
|
||||
}
|
||||
.textInput {
|
||||
font-size: var(--font-size-14);
|
||||
background-color: var(--neutral-color-cancel);
|
||||
width: 100%;
|
||||
border-radius: 20rpx;
|
||||
margin-top: 40rpx;
|
||||
padding: 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.butCont {
|
||||
width: 60%;
|
||||
margin: 40rpx auto 0 auto;
|
||||
}
|
||||
.exceptionImages {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-wrap: wrap;
|
||||
.exceptionImage {
|
||||
width: 26vw;
|
||||
height: 26vw;
|
||||
margin-bottom: 3vw;
|
||||
}
|
||||
}
|
||||
.setBottom {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
::v-deep .uni-input-placeholder {
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
.positionBot {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
}
|
||||
</style>
|
||||
257
project-wl-siji-uniapp-vue3/pages/index/index.scss
Normal file
257
project-wl-siji-uniapp-vue3/pages/index/index.scss
Normal file
@@ -0,0 +1,257 @@
|
||||
.container{
|
||||
border-radius: 20rpx;
|
||||
.swiperH{
|
||||
height: calc(100vh - 270rpx);
|
||||
padding-bottom: 30rpx;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.finshSwiperH{
|
||||
height: calc(100vh - 460rpx);
|
||||
}
|
||||
.cont{
|
||||
padding:0 30rpx;
|
||||
}
|
||||
}
|
||||
// 首页 - 通用 - 左右结构
|
||||
.carInfo{
|
||||
.line{
|
||||
.tit{
|
||||
display: inline-block;
|
||||
min-width: 120rpx;
|
||||
}
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
color: var(--neutral-color-font);
|
||||
font-size: var(--font-size-14);
|
||||
line-height: 60rpx;
|
||||
.ritEl{
|
||||
color: var(--neutral-color-main);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 详情-基本信息
|
||||
.baseInfo{
|
||||
.addrCont{
|
||||
font-weight: 400;
|
||||
font-size: 28rpx;
|
||||
color: var(--neutral-color-font);
|
||||
letter-spacing: 0.32rpx;
|
||||
padding-bottom: 40rpx;
|
||||
margin-bottom: 20rpx;
|
||||
border-bottom: 1px solid var(--neutral-color-segmentation);
|
||||
position: relative;
|
||||
&:before{
|
||||
position: absolute;
|
||||
left: 18rpx;
|
||||
color:var(--neutral-color-white);
|
||||
text-align: center;
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 0px;
|
||||
height: 56%;
|
||||
border-left: dashed 2px var(--neutral-color-border);
|
||||
border-radius: 11px;
|
||||
}
|
||||
.startAddr{
|
||||
padding-left: 66rpx;
|
||||
position: relative;
|
||||
margin-bottom: 20rpx;
|
||||
line-height: 44rpx;
|
||||
&:before{
|
||||
position: absolute;
|
||||
font-size: 22rpx;
|
||||
left: 0;
|
||||
color:var(--neutral-color-white);
|
||||
text-align: center;
|
||||
content: '起';
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background: var(--neutral-color-main);
|
||||
border-radius: 11px;
|
||||
}
|
||||
}
|
||||
.endAddr{
|
||||
padding-left: 66rpx;
|
||||
position: relative;
|
||||
line-height: 44rpx;
|
||||
&:before{
|
||||
font-size: 22rpx;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
color: var(--neutral-color-white);
|
||||
text-align: center;
|
||||
content: '止';
|
||||
display: inline-block;
|
||||
width: 22px;
|
||||
height: 22px;
|
||||
background: var(--essential-color-red);
|
||||
border-radius: 11px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 详情-运算路线
|
||||
.routeItem{
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
.navigat{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding: 0rpx 0rpx 0rpx 40rpx;
|
||||
border-left: 2rpx solid #EEEEEE;
|
||||
margin-left: 20rpx;
|
||||
font-size: var(--font-size-12);
|
||||
.naviIcon{
|
||||
width: 64rpx;
|
||||
height: 64rpx;
|
||||
}
|
||||
|
||||
}
|
||||
.routeLine{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding:0 20rpx;
|
||||
flex:1;
|
||||
.route{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
font-size: var(--font-size-12);
|
||||
color: var(--neutral-color-main);
|
||||
flex: 1;
|
||||
.line{
|
||||
width: 80%;
|
||||
.LineImg{
|
||||
width: 72rpx;
|
||||
height: 32rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
.routePoint{
|
||||
text-align: center;
|
||||
font-weight: 400;
|
||||
font-size: var(--font-size-14);
|
||||
color: var(--neutral-color-main);
|
||||
line-height: 60rpx;
|
||||
.tit{
|
||||
font-weight: 600;
|
||||
font-size: var(--font-size-16);
|
||||
color: var(--neutral-color-main);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 详情-物品信息
|
||||
.orderCont{
|
||||
.search{
|
||||
margin-bottom: 20rpx;
|
||||
position: relative;
|
||||
.searchIcon{
|
||||
position: absolute;
|
||||
left: 20rpx;
|
||||
top: 18rpx;
|
||||
}
|
||||
.searchInput{
|
||||
background-color: var(--neutral-color-cancel);
|
||||
border-radius: 32rpx;
|
||||
font-size: var(--font-size-12);
|
||||
line-height: 64rpx;
|
||||
height: 64rpx;
|
||||
padding: 0 20rpx 0 60rpx;
|
||||
}
|
||||
}
|
||||
.items{
|
||||
.item{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 28rpx;
|
||||
line-height: 60rpx;
|
||||
color: var(--neutral-color-main);
|
||||
.odd{
|
||||
flex: 1;
|
||||
}
|
||||
.piece, .weight{
|
||||
text-align: right;
|
||||
width: 200rpx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// 详情-异常信息
|
||||
.delay{
|
||||
display: flex;
|
||||
font-size: var(--font-size-14);
|
||||
align-items: center;
|
||||
border-bottom: solid 2rpx var(--neutral-color-background);
|
||||
padding: 20rpx 0;
|
||||
.info{
|
||||
flex: 1;
|
||||
color: var(--neutral-color-main);
|
||||
|
||||
.line{
|
||||
line-height: 60rpx;
|
||||
.desc{
|
||||
padding-left: 40rpx;
|
||||
color: var(--neutral-color-font);
|
||||
}
|
||||
}
|
||||
}
|
||||
.goInfoIcon{
|
||||
width: 48rpx;
|
||||
height: 48rpx;
|
||||
}
|
||||
}
|
||||
|
||||
// 图片上传
|
||||
.upPicCont{
|
||||
margin-bottom: 32rpx;
|
||||
.title{
|
||||
font-weight: 400;
|
||||
font-size: var(--font-size-14);
|
||||
color: var(--neutral-color-font);
|
||||
margin-bottom: 32rpx;
|
||||
}
|
||||
.file-picker__box-content{
|
||||
border:none;
|
||||
background: var(--neutral-color-cancel);
|
||||
}
|
||||
// 已完成的详情图片回显
|
||||
.tit{
|
||||
font-size: 28rpx;
|
||||
margin-bottom: 20rpx;
|
||||
}
|
||||
.upPicContImg{
|
||||
display: flex;
|
||||
.image{
|
||||
width: 180rpx;
|
||||
height: 180rpx;
|
||||
margin:0 30rpx 30rpx 0;
|
||||
}
|
||||
.image:nth-child(3){
|
||||
margin-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// 详情 - 底部的两按钮
|
||||
.footCont{
|
||||
display: flex;
|
||||
background-color: var(--neutral-color-white);
|
||||
padding: 20rpx 30rpx;
|
||||
box-sizing: border-box;
|
||||
.footButCan{
|
||||
flex: 125;
|
||||
margin-right: 30rpx;
|
||||
}
|
||||
.footBut{
|
||||
flex: 200;
|
||||
}
|
||||
}
|
||||
148
project-wl-siji-uniapp-vue3/pages/index/index.vue
Normal file
148
project-wl-siji-uniapp-vue3/pages/index/index.vue
Normal file
@@ -0,0 +1,148 @@
|
||||
<!-- 待提货-首页 -->
|
||||
<template>
|
||||
<!-- end -->
|
||||
<view class="pageBox">
|
||||
<!-- 取件状态列表 -->
|
||||
<ItemList :itemData="itemData.value" @setTabIndex="setTabIndex" @searchSubmit="searchHandle" :loadding="loading" :moreStatus="moreStatus" />
|
||||
<!-- end -->
|
||||
</view>
|
||||
<!-- footer -->
|
||||
<UniFooter :pagePath="'pages/index/index'"></UniFooter>
|
||||
<!-- end -->
|
||||
</template>
|
||||
<script>
|
||||
export default {
|
||||
name: 'list',
|
||||
// 上拉刷新
|
||||
onPullDownRefresh() {
|
||||
uni.stopPullDownRefresh();
|
||||
}
|
||||
};
|
||||
</script>
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { useStore } from 'vuex';
|
||||
// 导入接口
|
||||
import { GetTasksList, GetTaskDetails, PositionUpload } from '@/pages/api/index.js';
|
||||
import { positionsUploadInit } from '@/utils/index.js';
|
||||
// 导入组件
|
||||
// 底部导航
|
||||
import UniFooter from '@/components/Footer/index.vue';
|
||||
// 主体部分
|
||||
import ItemList from './components/ItemList.vue';
|
||||
|
||||
// ------定义变量------
|
||||
const store = useStore(); //vuex获取储存数据
|
||||
const itemData = reactive([]);
|
||||
const tabIndex = ref(store.state.taskStatus); //当前tab
|
||||
const moreStatus = ref('loading'); //加载更多状态 loading more noMore
|
||||
const loading = ref(false); // 是否展示加载更多
|
||||
const date = new Date();
|
||||
const year = date.getFullYear();
|
||||
const month = computed(() => {
|
||||
const mt = date.getMonth();
|
||||
if (mt > 0 && mt < 10) {
|
||||
return '0' + mt;
|
||||
} else if (mt == 0) {
|
||||
return 12;
|
||||
} else {
|
||||
return mt;
|
||||
}
|
||||
});
|
||||
const month1 = date.getMonth() + 1 < 10 ? '0' + (date.getMonth() + 1) : date.getMonth() + 1;
|
||||
const day = date.getDate() < 10 ? '0' + date.getDate() : date.getDate();
|
||||
const params = reactive({
|
||||
status: tabIndex != 2 ? tabIndex.value + 1 : 4,
|
||||
transportTaskId: '', // 运单号 非必传
|
||||
|
||||
page: 1,
|
||||
pageSize: 10
|
||||
});
|
||||
const pages = ref(0); // 总页数
|
||||
// ------生命周期------
|
||||
onMounted(() => {
|
||||
// 上报位置 进入首页立即上报
|
||||
positionsUploadInit();
|
||||
getNewData();
|
||||
});
|
||||
// ------定义方法------
|
||||
const isSendRequest = ref(false); // 是否继续发送请求
|
||||
|
||||
// 获取任务列表
|
||||
const getNewData = async type => {
|
||||
if (isSendRequest.value) {
|
||||
return;
|
||||
}
|
||||
loading.value = true;
|
||||
let infoParams = {};
|
||||
if (store.state.taskStatus === 2) {
|
||||
infoParams = {
|
||||
...params,
|
||||
startTime: month.value == 12 ? `${year - 1}-${month.value}-${day}` : `${year}-${month.value}-${day}`,
|
||||
endTime: `${year}-${month1}-${day}`
|
||||
};
|
||||
} else {
|
||||
infoParams = {
|
||||
...params
|
||||
};
|
||||
}
|
||||
await GetTasksList(infoParams)
|
||||
.then(res => {
|
||||
if (res.code == 200) {
|
||||
const { data } = res;
|
||||
// 搜索数据处理
|
||||
if (type && type == 'search') {
|
||||
params.page = 1;
|
||||
params.pageSize = 10;
|
||||
itemData.value = data.items ? data.items : [];
|
||||
} else {
|
||||
// items == null 会报错 把他处理掉
|
||||
const items = data.items == null ? [] : data.items;
|
||||
// 从第一页请求 清空之前的数据
|
||||
params.page == 1 ? (itemData.value = undefined) : null;
|
||||
// 下拉数据合并
|
||||
itemData.value = itemData.value ? [...itemData.value, ...items] : items;
|
||||
// 如果 当前页面的数据已经全部数据了 那么停止拿数据
|
||||
if (data.counts == 0) {
|
||||
isSendRequest.value = true;
|
||||
}
|
||||
}
|
||||
|
||||
loading.value = false;
|
||||
counts.value = data.pages;
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {});
|
||||
};
|
||||
|
||||
// 切换 1待提货、2在途、4已完成
|
||||
const setTabIndex = index => {
|
||||
const tab = store.state.taskStatus;
|
||||
store.commit('setTaskStatus', index);
|
||||
// 下拉加载和切换的时候处理分页参数
|
||||
params.page = tab == index ? params.page + 1 : 1;
|
||||
params.status = index != 2 ? index + 1 : 6;
|
||||
isSendRequest.value = false;
|
||||
getNewData();
|
||||
};
|
||||
|
||||
// 已完成搜索
|
||||
const searchHandle = val => {
|
||||
// 已完成列表提交搜索
|
||||
if (typeof val == 'string') {
|
||||
params.transportTaskId = val;
|
||||
} else {
|
||||
params.startTime = val.value[0];
|
||||
params.endTime = val.value[1];
|
||||
}
|
||||
|
||||
getNewData('search');
|
||||
};
|
||||
</script>
|
||||
<style src="./index.scss" lang="scss"></style>
|
||||
222
project-wl-siji-uniapp-vue3/pages/index/refister.vue
Normal file
222
project-wl-siji-uniapp-vue3/pages/index/refister.vue
Normal file
@@ -0,0 +1,222 @@
|
||||
<!-- 回车登记 -->
|
||||
<template>
|
||||
<view>
|
||||
<!-- 详情 -->
|
||||
<view class="refister">
|
||||
<DetailsNav title="回车登记"></DetailsNav>
|
||||
<view class="container">
|
||||
<!-- 垂直滚动区域 scroll和swiper的高度都要给且是一样的高度-->
|
||||
<scroll-view scroll-y="true" class="swiperH">
|
||||
<view class="boxBg">
|
||||
<view class="infoCard">
|
||||
<view class="line">
|
||||
<text>出车时间</text>
|
||||
<text>{{startTime}}</text>
|
||||
</view>
|
||||
<view class="line">
|
||||
<text>回车时间</text>
|
||||
<uni-datetime-picker type="datetime" v-model="params.endTime" :clear-icon="false" @change="changeLog" />
|
||||
</view>
|
||||
</view>
|
||||
<!-- 通用卡片组件 - 待提货 - 带开关 -->
|
||||
<CardCont title="车辆违章" type="redio" redioKey="isBreakRules" @redioChange = "redioChange">
|
||||
<refisterCards :data="breakRulesType" :value="breakRulesType.data[0]" choiceKey="breakRulesType" @choiceHandel = "choiceHandel" />
|
||||
<refisterCards :data="penaltyAmount" :value="penaltyAmount.data[0]" choiceKey="penaltyAmount" @choiceHandel = "choiceHandel" />
|
||||
<refisterCards :data="deductPoints" :value="deductPoints.data[0]" choiceKey="deductPoints" @choiceHandel = "choiceHandel" />
|
||||
</CardCont>
|
||||
<CardCont title="车辆故障" type="redio" redioKey="isFault" @redioChange = "redioChange">
|
||||
<!-- 车辆是否可用 -->
|
||||
<refisterCards :data="isAvailable" :value="isAvailable.data[0]" choiceKey="isAvailable" @choiceHandel = "choiceHandel" />
|
||||
<!-- 故障类型 -->
|
||||
<refisterCards :data="faultType" :value="faultType.data[0]" choiceKey="faultType" @choiceHandel = "choiceHandel" />
|
||||
<TextArea placeholder="请简单描述故障"></TextArea>
|
||||
<ImageUpload title="请拍照" @uploadImage="uploadImage" tit='faultImages'></ImageUpload>
|
||||
</CardCont>
|
||||
<CardCont title="车辆事故" type="redio" redioKey="isAccident" @redioChange = "redioChange">
|
||||
<refisterCards :data="accidentType" :value="accidentType.data[0]" choiceKey="accidentType" @choiceHandel = "choiceHandel" />
|
||||
<TextArea placeholder="请简单描述故障"></TextArea>
|
||||
<ImageUpload title="请拍照" @uploadImage="uploadImage" tit='accidentImages'></ImageUpload>
|
||||
</CardCont>
|
||||
</view>
|
||||
</scroll-view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
</view>
|
||||
<!-- footer -->
|
||||
<view class="footCont">
|
||||
<view class="footBut">
|
||||
<text class="button" v-show="params.endTime != '' && (params.endTime).length == 19 " @click="submit()">交车</text>
|
||||
<text class="button buttonDis1" v-show="params.endTime == '' || (params.endTime).length < 19" >交车</text>
|
||||
</view>
|
||||
</view>
|
||||
<!-- end -->
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, reactive, onMounted, onUpdated, watch, watchEffect, computed, inject } from 'vue';
|
||||
// 导入接口
|
||||
import { TruckRegistration } from '@/pages/api/index.js';
|
||||
// 导入组件
|
||||
import DetailsNav from '@/components/DetailsNav/index.vue'
|
||||
import CardCont from '@/components/CardCont/index.vue';
|
||||
import refisterCards from './components/refisterCards.vue'
|
||||
import ImageUpload from '@/components/ImageUpload/index.vue'
|
||||
import TextArea from '@/components/TextArea/index.vue'
|
||||
|
||||
|
||||
// ------定义变量------
|
||||
const startTime = ref('')
|
||||
const breakRulesType = {
|
||||
title: '违章类型',
|
||||
data: ['闯红灯', '无证驾驶', '超载', '酒后驾驶', '超速驾驶']
|
||||
}
|
||||
|
||||
const penaltyAmount = {
|
||||
title: '罚款金额',
|
||||
data: ['0元', '100元', '200元', '300元', '500元', '1000元', '2000元']
|
||||
}
|
||||
|
||||
const deductPoints = {
|
||||
title: '扣分',
|
||||
data: ['0分', '1分', '2分', '3分', '6分', '12分']
|
||||
}
|
||||
const isAvailable = {
|
||||
title: '车辆是否可用',
|
||||
data: ['是', '否']
|
||||
}
|
||||
const faultType = {
|
||||
title: '故障类型',
|
||||
data: ['启动困难', '不着车', '漏油', '漏水', '照明失灵', '有异响', '排烟异常', '温度异常', '其他']
|
||||
}
|
||||
|
||||
const accidentType = {
|
||||
title: '事故类型',
|
||||
data: ['直行事故', '追尾事故', '超车事故', '左转弯事故', '右转弯事故', '弯道事故', '坡道事故', '会车事故', '其他']
|
||||
}
|
||||
|
||||
let params = reactive({
|
||||
id: '',
|
||||
startTime: '', //出车时间
|
||||
endTime: '', //回车时间
|
||||
isBreakRules: false, //违章
|
||||
breakRulesType: 1, //违章类型
|
||||
penaltyAmount: 1, //罚款金额
|
||||
deductPoints: 1, //扣分
|
||||
isFault: false, //是否有故障
|
||||
isAvailable: true, //车辆是否可用
|
||||
faultType: 1, //故障类型
|
||||
faultImages: '', //故障图片
|
||||
isAccident: false, // 是否有事故
|
||||
accidentType: 1,
|
||||
accidentImages: '' // 事故图片
|
||||
})
|
||||
|
||||
// ------生命周期------
|
||||
onMounted(() => {
|
||||
const pages = getCurrentPages();
|
||||
const currentPage = pages[pages.length - 1].$page.options;
|
||||
startTime.value = currentPage.time;
|
||||
params.startTime = currentPage.time;
|
||||
params.id = currentPage.id
|
||||
});
|
||||
|
||||
// ------定义方法------
|
||||
// 回车登级-交车数据提交
|
||||
async function submit() {
|
||||
// 网络慢的时候添加按钮loading
|
||||
let times =
|
||||
setTimeout(()=>{
|
||||
uni.showLoading({
|
||||
title: 'loading',
|
||||
mask:true
|
||||
});
|
||||
},500)
|
||||
await TruckRegistration(params)
|
||||
.then(res => {
|
||||
if (res.code === 200) {
|
||||
// 操作成功后清除loading
|
||||
setTimeout(function () {
|
||||
uni.hideLoading();
|
||||
}, 500);
|
||||
clearTimeout(times)
|
||||
uni.showToast({
|
||||
title: '回车登记数据提交成功!',
|
||||
duration: 1000,
|
||||
icon: 'none'
|
||||
});
|
||||
uni.navigateTo({
|
||||
url: '/pages/index/index'
|
||||
})
|
||||
} else {
|
||||
return uni.showToast({
|
||||
title: res.msg,
|
||||
duration: 1000,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch(err => {});
|
||||
}
|
||||
// 是否打开相关的违章、故障、事故并赋值到params
|
||||
function redioChange(item){
|
||||
params[item.key] = item.value == 2 ? true : false
|
||||
}
|
||||
|
||||
// 图片上传
|
||||
const uploadImage = (item) => {
|
||||
if (item.key == 'accidentImages'){
|
||||
params.accidentImages = params.accidentImages == '' ? item.value : params.accidentImages + ',' + item.value
|
||||
} else {
|
||||
params.faultImages = params.faultImages == '' ? item.value : params.faultImages + ',' + item.value
|
||||
}
|
||||
}
|
||||
// 回车时间
|
||||
function changeLog(e){
|
||||
if (e.length < 19){
|
||||
uni.showToast({
|
||||
title: '请选择回车时间(包含日期及时间)',
|
||||
duration: 3000,
|
||||
icon: 'none'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// 选择违章的数据
|
||||
function choiceHandel(item){
|
||||
if (item.key == 'isAvailable'){
|
||||
params[item.key] = item.value == 1 ? true : false
|
||||
} else {
|
||||
params[item.key] = item.value
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style src="./index.scss" lang="scss"></style>
|
||||
<style lang="scss">
|
||||
.refister .container{
|
||||
padding-top: 30rpx;
|
||||
font-size: var(--font-size-14);
|
||||
.infoCard{
|
||||
background: #FFFFFF;
|
||||
border-radius: 20rpx;
|
||||
padding:0 30rpx;
|
||||
.line{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
line-height: 60rpx;
|
||||
border-bottom: solid 2rpx #EEEEEE;
|
||||
padding: 20rpx 0;
|
||||
.desc{
|
||||
color: #818181;
|
||||
}
|
||||
}
|
||||
.line:last-child{
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
::v-deep .uni-input-placeholder{
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user