185 lines
5.6 KiB
Vue
185 lines
5.6 KiB
Vue
<template>
|
||
<view class="bx-page pl-driver-plan-page">
|
||
<view class="topbar" :style="safeAreaStyle">
|
||
<view class="topbar-left">
|
||
<text class="topbar-back" @click="goBack">←</text>
|
||
<text class="topbar-title">司机运输计划单</text>
|
||
</view>
|
||
<view class="topbar-right" />
|
||
</view>
|
||
|
||
<view class="filters">
|
||
<uni-calendar
|
||
:insert="true"
|
||
:date="selectedDate"
|
||
:showMonth="false"
|
||
@change="onCalendarChange"
|
||
/>
|
||
</view>
|
||
|
||
<view class="list-body">
|
||
<view v-if="loading" class="page-loading">加载中...</view>
|
||
<view v-else-if="!records.length" class="empty-hint">暂无运输记录</view>
|
||
<view
|
||
v-for="(row, index) in records"
|
||
:key="row.planId || index"
|
||
class="record-card"
|
||
@click="openRecord(row)"
|
||
>
|
||
<text class="index-tag">{{ index + 1 }}</text>
|
||
<view class="record-top">
|
||
<text class="card-title">{{ cardTitle(row) }}</text>
|
||
<text class="tag" :class="tagClass(row)">{{ row.statusLabel || '进行中' }}</text>
|
||
</view>
|
||
<view class="meta">
|
||
车牌:<text class="plate-hl">{{ row.licensePlate || '—' }}</text>
|
||
</view>
|
||
<template v-if="(row.stops || []).length">
|
||
<view
|
||
v-for="(stop, sIndex) in row.stops"
|
||
:key="`${stop.stopType}-${stop.seq ?? sIndex}`"
|
||
class="stop-block"
|
||
>
|
||
<view class="stop-block__title"
|
||
>{{ stop.label }} · {{ stop.customerName || '—' }}</view
|
||
>
|
||
<view class="meta">时间:{{ formatDay(stop.stopTime) }}</view>
|
||
<view class="meta">地址:{{ stop.address || '—' }}</view>
|
||
<template v-if="!(stop.products || []).length">
|
||
<view class="meta">产品:—</view>
|
||
</template>
|
||
<template v-for="(prod, pIndex) in stop.products || []" :key="pIndex">
|
||
<view class="meta">产品:{{ prod.productName || '—' }}</view>
|
||
<view class="meta">规格型号:{{ prod.model || '—' }}</view>
|
||
<view class="meta">包装规格:{{ prod.packageSpec || '—' }}</view>
|
||
<view class="meta"
|
||
>数量:{{ formatQty(prod.quantity) }} · 单位:{{ prod.unit || '—' }}</view
|
||
>
|
||
</template>
|
||
</view>
|
||
</template>
|
||
<view class="meta">运输计划号:{{ row.planNo || '—' }}</view>
|
||
</view>
|
||
</view>
|
||
</view>
|
||
</template>
|
||
|
||
<script setup>
|
||
import { ref } from 'vue'
|
||
import { onShow } from '@dcloudio/uni-app'
|
||
import { PAGE_PATHS } from '@/config/api'
|
||
import { driverPlanApi } from '@/api/pl'
|
||
import { getSafeAreaStyle } from '@/utils/safeArea'
|
||
|
||
const safeAreaStyle = getSafeAreaStyle()
|
||
|
||
function todayStr() {
|
||
const d = new Date()
|
||
const m = `${d.getMonth() + 1}`.padStart(2, '0')
|
||
const day = `${d.getDate()}`.padStart(2, '0')
|
||
return `${d.getFullYear()}-${m}-${day}`
|
||
}
|
||
|
||
const selectedDate = ref(todayStr())
|
||
const records = ref([])
|
||
const loading = ref(false)
|
||
|
||
function formatDay(value) {
|
||
if (!value) return '—'
|
||
const normalized = String(value).replace('T', ' ')
|
||
return normalized.length >= 10 ? normalized.slice(0, 10) : normalized
|
||
}
|
||
|
||
function formatQty(value) {
|
||
if (value == null || value === '') return '—'
|
||
return String(value)
|
||
}
|
||
|
||
function cardTitleDate(row) {
|
||
const stopTimes = (row.stops || [])
|
||
.map((stop) => formatDay(stop.stopTime))
|
||
.filter((value) => value !== '—')
|
||
if (stopTimes.length) return stopTimes[0]
|
||
const fromPickup = formatDay(row.pickupTime)
|
||
if (fromPickup !== '—') return fromPickup
|
||
const fromDelivery = formatDay(row.deliveryTime)
|
||
if (fromDelivery !== '—') return fromDelivery
|
||
return selectedDate.value
|
||
}
|
||
|
||
function cardTitle(row) {
|
||
return cardTitleDate(row)
|
||
}
|
||
|
||
function tagClass(row) {
|
||
if (row.planVoided || row.statusLabel === '已作废') return 'tag--danger'
|
||
if (row.planArchived || row.statusLabel === '已归档') return 'tag--muted'
|
||
return 'tag--success'
|
||
}
|
||
|
||
async function loadList() {
|
||
loading.value = true
|
||
try {
|
||
const res = await driverPlanApi.history({ date: selectedDate.value })
|
||
records.value = res.records || []
|
||
} catch (e) {
|
||
records.value = []
|
||
} finally {
|
||
loading.value = false
|
||
}
|
||
}
|
||
|
||
function onCalendarChange(e) {
|
||
const v = e?.fulldate || e?.date || (typeof e === 'string' ? e : '')
|
||
if (typeof v === 'string' && /^\d{4}-\d{2}-\d{2}/.test(v)) {
|
||
selectedDate.value = v.slice(0, 10)
|
||
loadList()
|
||
}
|
||
}
|
||
|
||
function openRecord(row) {
|
||
const id = row.planId || row.plan_id
|
||
if (!id) {
|
||
uni.showToast({ title: '计划无效', icon: 'none' })
|
||
return
|
||
}
|
||
uni.navigateTo({ url: `${PAGE_PATHS.plDriverPlanDetail}?planId=${id}` })
|
||
}
|
||
|
||
function goBack() {
|
||
uni.navigateBack({ fail: () => uni.reLaunch({ url: PAGE_PATHS.workbench }) })
|
||
}
|
||
|
||
onShow(() => {
|
||
loadList()
|
||
})
|
||
</script>
|
||
|
||
<!-- 微信端:scss 须在 style 中 @import;script 里 import 只会生成空 js,H5 有样式而小程序无样式 -->
|
||
<style lang="scss">
|
||
@import '@/styles/bx-theme.scss';
|
||
@import '@/styles/pl-driver-plan.scss';
|
||
</style>
|
||
|
||
<style lang="scss" scoped>
|
||
:deep(.uni-calendar__backtoday) {
|
||
display: none;
|
||
}
|
||
|
||
:deep(.uni-calendar-item--checked),
|
||
:deep(.uni-calendar-item--isDay),
|
||
:deep(.uni-calendar-item--multiple) {
|
||
background-color: #0a9f6d !important;
|
||
color: #fff !important;
|
||
}
|
||
|
||
:deep(.uni-calendar-item--isDay-text) {
|
||
color: #0a9f6d !important;
|
||
}
|
||
|
||
:deep(.uni-calendar-item--checked.uni-calendar-item--isDay-text),
|
||
:deep(.uni-calendar-item--isDay.uni-calendar-item--isDay-text) {
|
||
color: #fff !important;
|
||
}
|
||
</style>
|