<template>
|
<view class="container">
|
<!-- 导航栏 -->
|
<Nav :title="pageTitle" custom-back="/pages/beReferred/index" />
|
|
<!-- 基础信息 - 使用统一的 InfoSection 组件 -->
|
<InfoSection :list="infoList" />
|
|
<!-- 表单区域 -->
|
<view class="form-content">
|
<view class="form-section">
|
<!-- 甩挂表单 -->
|
<template v-if="statusStr === '待甩挂'">
|
<u--form ref="dropForm" :rules="rules" :model="form" labelPosition="left">
|
<!-- 甩挂地址 -->
|
<u-form-item borderBottom label=" " labelWidth="0" prop="address">
|
<view class="form-row" @click="getLocation">
|
<view class="form-label required">
|
<view class="label-icon">
|
<u--image :showLoading="true" src="/static/bt.png" width="18" height="18" />
|
</view>
|
<text class="label-text">甩挂地址</text>
|
</view>
|
<view class="address-box">
|
<u--text
|
:lines="3"
|
:text="form.address"
|
:placeholder="locationLoading ? '正在获取位置...' : '点击获取当前地址'"
|
/>
|
<view class="location-icon">
|
<u-loading-icon v-if="locationLoading" size="20" color="#409eff" />
|
<u-icon v-else name="map-fill" color="#409eff" size="22" />
|
</view>
|
</view>
|
</view>
|
</u-form-item>
|
|
<!-- 甩挂时间 -->
|
<u-form-item borderBottom label=" " labelWidth="0" prop="tripTime">
|
<view class="form-row">
|
<view class="form-label">
|
<u--image :showLoading="true" src="/static/bt.png" width="20" height="20" />
|
<text>甩挂时间</text>
|
</view>
|
<uni-datetime-picker type="datetime" v-model="form.tripTime" class="flex-1" />
|
</view>
|
</u-form-item>
|
|
<!-- 凭证上传 -->
|
<u-form-item label="凭证" labelWidth="80" :borderBottom="false">
|
<u-upload
|
:fileList="fileList"
|
name="file"
|
multiple
|
:maxCount="6"
|
:maxSize="50 * 1024 * 1024"
|
@afterRead="afterRead"
|
@delete="deletePic"
|
@oversize="overSize"
|
/>
|
</u-form-item>
|
</u--form>
|
|
<BottomBar :loading="loading" @submit="submitForm" @advance="goToAdvanceList" />
|
</template>
|
|
<!-- 接挂表单 -->
|
<template v-if="statusStr === '待接挂'">
|
<u--form ref="pickForm" :rules="rules" :model="form" labelPosition="left">
|
<!-- 接挂地址 -->
|
<u-form-item borderBottom label=" " labelWidth="0" prop="address">
|
<view class="form-row" @click="getLocation">
|
<view class="form-label required">
|
<view class="label-icon">
|
<u--image :showLoading="true" src="/static/bt.png" width="18" height="18" />
|
</view>
|
<text class="label-text">接挂地址</text>
|
</view>
|
<view class="address-box">
|
<u--text
|
:lines="3"
|
:text="form.address"
|
:placeholder="locationLoading ? '正在获取位置...' : '点击获取当前地址'"
|
/>
|
<view class="location-icon">
|
<u-loading-icon v-if="locationLoading" size="20" color="#409eff" />
|
<u-icon v-else name="map-fill" color="#409eff" size="22" />
|
</view>
|
</view>
|
</view>
|
</u-form-item>
|
|
<!-- 接挂时间 -->
|
<u-form-item borderBottom label=" " labelWidth="0" prop="tripTime">
|
<view class="form-row">
|
<view class="form-label">
|
<u--image :showLoading="true" src="/static/bt.png" width="20" height="20" />
|
<text>接挂时间</text>
|
</view>
|
<uni-datetime-picker type="datetime" v-model="form.tripTime" class="flex-1" />
|
</view>
|
</u-form-item>
|
|
<!-- 凭证上传 -->
|
<u-form-item label="凭证" labelWidth="80" :borderBottom="false">
|
<u-upload
|
:fileList="fileList"
|
name="file"
|
multiple
|
:maxCount="6"
|
:maxSize="50 * 1024 * 1024"
|
@afterRead="afterRead"
|
@delete="deletePic"
|
@oversize="overSize"
|
/>
|
</u-form-item>
|
</u--form>
|
|
<BottomBar :loading="loading" @submit="submitForm" @history="goTravelItinerary" />
|
</template>
|
</view>
|
</view>
|
</view>
|
</template>
|
|
<!-- 底部按钮 -->
|
<view class="btn-group">
|
<u-button class="btn-default" @click="goTravelItinerary" text="行程历史" />
|
<u-button class="btn-primary" :loading="loading" @click="submitForm" type="primary" text="提交" />
|
</view>
|
</template>
|
</view>
|
</view>
|
</template>
|
|
<script>
|
import InfoSection from '@/components/InfoSection/index.vue'
|
import BottomBar from '@/components/BottomBar/index.vue'
|
import {
|
getcarDispatch,
|
getcarType,
|
carSubmitDropHoo,
|
carSubmitPickHook
|
} from '@/common/examine'
|
import { uploadImage } from '@/common/upload'
|
import config from '@/config'
|
import amap from '@/common/amap-wx.130.js'
|
import {navigateTo, PAGES, reLaunch} from '@/common/router'
|
|
const INFO_FIELDS = Object.freeze([
|
{ key: 'dispatchNo', label: '调度单号' },
|
{ key: 'licensePlate', label: '车牌号' },
|
{ key: 'transportLine', label: '路线' },
|
{ key: 'customerName', label: '客户' },
|
{ key: 'statusStr', label: '当前状态', status: true, default: '待发车' },
|
{ key: 'latestDeparture', label: '最晚发车时间' }
|
])
|
|
export default {
|
components: { InfoSection, BottomBar },
|
|
data() {
|
return {
|
// 高德地图配置
|
mapApiKey: 'fdb2d2e64ffc9254045935d3227d5cd9',
|
amapPlugin: null,
|
isHk: false,
|
|
// 页面参数
|
dispatchId: '',
|
statusStr: '',
|
pageTitle: '',
|
|
// 调度信息
|
newForm: {},
|
infoList: INFO_FIELDS.map(f => ({ ...f, value: f.default || '' })),
|
|
// 表单数据
|
form: {
|
address: '',
|
tripTime: '',
|
tripType: ''
|
},
|
|
// 文件列表
|
fileList: [],
|
|
// 加载状态
|
loading: false,
|
locationLoading: false,
|
|
// 表单验证规则
|
rules: {
|
address: [{ required: true, message: '请获取地址', trigger: 'blur' }],
|
tripTime: [{ required: true, message: '请选择时间', trigger: 'change' }],
|
fileList: [{ validator: this.validateFiles, trigger: 'change' }]
|
}
|
}
|
},
|
|
onLoad(options) {
|
// 使用新的参数方式
|
this.dispatchId = options.id || ''
|
this.statusStr = options.statusStr || ''
|
|
// 根据状态设置标题
|
this.pageTitle = this.statusStr || '上传行程'
|
|
// 初始化高德地图
|
this.amapPlugin = new amap.AMapWX({ key: this.mapApiKey })
|
|
// 获取位置
|
this.getLocation()
|
|
// 加载数据
|
if (this.dispatchId) {
|
this.loadDispatchInfo()
|
}
|
},
|
|
created() {
|
this.form.tripTime = this.getCurrentDateTime()
|
},
|
|
methods: {
|
// 获取当前时间
|
getCurrentDateTime() {
|
const now = new Date()
|
const pad = (n) => n.toString().padStart(2, '0')
|
return `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())} ${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`
|
},
|
|
// 加载调度信息
|
async loadDispatchInfo() {
|
try {
|
const res = await getcarDispatch(this.dispatchId)
|
this.newForm = { ...res, statusStr: this.statusStr }
|
this.infoList = INFO_FIELDS.map(f => ({ ...f, value: res[f.key] ?? f.value }))
|
|
// 加载行程类型
|
const tripTypes = await getcarType('trip_type')
|
// 可根据需要存储 tripTypes
|
} catch (err) {
|
console.error('加载调度信息失败:', err)
|
uni.$u.toast('加载数据失败')
|
}
|
},
|
|
// 文件验证
|
validateFiles(rule, value, callback) {
|
if (this.fileList.length === 0) {
|
callback(new Error('请上传凭证'))
|
} else {
|
callback()
|
}
|
},
|
|
// 图片上传
|
async afterRead(event) {
|
try {
|
const res = await uploadImage(event.file[0].url, this.isHk)
|
this.fileList.push(res)
|
} catch (err) {
|
console.error('上传失败:', err)
|
uni.$u.toast('上传失败')
|
}
|
},
|
|
// 删除图片
|
deletePic(event) {
|
this.fileList.splice(event.index, 1)
|
},
|
|
// 图片超出大小
|
overSize() {
|
uni.$u.toast('图片大小不能超过2MB')
|
},
|
|
// 获取位置(添加超时处理)
|
getLocation() {
|
this.locationLoading = true
|
|
// 设置 10 秒超时
|
const timeout = setTimeout(() => {
|
this.locationLoading = false
|
uni.$u.toast('定位超时,请手动输入地址')
|
}, 10000)
|
|
uni.getLocation({
|
type: 'gcj02',
|
success: (res) => {
|
clearTimeout(timeout)
|
this.getAddress(res.latitude, res.longitude)
|
},
|
fail: (err) => {
|
clearTimeout(timeout)
|
this.locationLoading = false
|
console.error('获取位置失败:', err)
|
uni.$u.toast('获取位置失败,请手动输入地址')
|
}
|
})
|
},
|
|
// 解析地址
|
getAddress(latitude, longitude) {
|
this.amapPlugin.getRegeo({
|
location: `${longitude},${latitude}`,
|
success: (data) => {
|
this.locationLoading = false
|
const datum = data[0]
|
if (datum.regeocodeData?.addressComponent?.province) {
|
this.isHk = datum.regeocodeData.addressComponent.province.includes('香港')
|
}
|
this.form.address = datum.name || datum.desc
|
},
|
fail: (err) => {
|
this.locationLoading = false
|
console.error('地址解析失败:', err)
|
uni.$u.toast('地址解析失败,请手动输入地址')
|
}
|
})
|
},
|
|
// 提交表单
|
submitForm() {
|
if (this.loading) return
|
|
const formRef = this.statusStr === '待甩挂' ? 'dropForm' : 'pickForm'
|
|
this.$refs[formRef].validate().then(() => {
|
this.doSubmit()
|
}).catch(() => {
|
uni.$u.toast('请完善表单信息')
|
})
|
},
|
|
// 执行提交
|
async doSubmit() {
|
this.loading = true
|
|
const submitData = {
|
...this.form,
|
voucherUrl: this.fileList.map(item => item.url).join(','),
|
dispatchOrderId: this.newForm.dispatchId,
|
driverId: this.newForm.driverId
|
}
|
|
try {
|
const api = this.statusStr === '待甩挂' ? carSubmitDropHoo : carSubmitPickHook
|
const res = await api(submitData)
|
|
uni.$u.toast('操作成功')
|
reLaunch('/pages/beReferred/index')
|
|
} catch (err) {
|
uni.$u.toast(err.message || '提交失败')
|
} finally {
|
setTimeout(() => {
|
this.loading = false
|
}, 500)
|
}
|
},
|
|
// 重置表单
|
resetForm() {
|
this.form = {
|
address: '',
|
tripTime: this.getCurrentDateTime(),
|
tripType: ''
|
}
|
this.fileList = []
|
},
|
|
// 跳转到垫付列表
|
goToAdvanceList() {
|
navigateTo(PAGES.PAYMENT_LIST, { id: this.dispatchId })
|
},
|
|
// 跳转到行程历史
|
goTravelItinerary() {
|
navigateTo(PAGES.TRAVEL_ITINERARY, { id: this.dispatchId })
|
}
|
}
|
}
|
</script>
|
|
<style scoped>
|
.container {
|
display: flex;
|
flex-direction: column;
|
min-height: 100vh;
|
background-color: #f7f7f7;
|
}
|
|
.form-content {
|
flex: 1;
|
padding-bottom: 40rpx;
|
}
|
|
.form-section {
|
padding: 20rpx;
|
background-color: #fff;
|
border-radius: 12rpx;
|
margin: 20rpx;
|
}
|
|
.form-row {
|
display: flex;
|
align-items: flex-start;
|
width: 100%;
|
padding: 10rpx 0;
|
}
|
|
.form-label {
|
display: flex;
|
align-items: center;
|
flex-shrink: 0;
|
margin-right: 20rpx;
|
min-width: 120rpx;
|
padding-top: 16rpx;
|
}
|
|
.label-icon {
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
width: 36rpx;
|
height: 36rpx;
|
margin-right: 8rpx;
|
}
|
|
.label-text {
|
font-size: 28rpx;
|
color: #303133;
|
font-weight: 500;
|
}
|
|
.form-label.required .label-text::after {
|
content: '*';
|
color: #ff4d4f;
|
margin-left: 4rpx;
|
}
|
|
.flex-1 {
|
flex: 1;
|
}
|
|
.address-box {
|
flex: 1;
|
display: flex;
|
align-items: center;
|
background-color: #f5f7fa;
|
border: 2rpx solid #e4e7ed;
|
border-radius: 12rpx;
|
padding: 20rpx 80rpx 20rpx 20rpx;
|
position: relative;
|
}
|
|
.location-icon {
|
position: absolute;
|
top: 50%;
|
right: 0;
|
transform: translateY(-50%);
|
width: 72rpx;
|
height: 72rpx;
|
display: flex;
|
align-items: center;
|
justify-content: center;
|
}
|
</style>
|
top: 50%;
|
right: 16rpx;
|
transform: translateY(-50%);
|
}
|
|
// 时间选择
|
.datetime-wrapper {
|
display: flex;
|
align-items: center;
|
width: 100%;
|
}
|
|
.datetime-picker {
|
flex: 1;
|
}
|
|
// 按钮组
|
.btn-group {
|
display: flex;
|
gap: 20rpx;
|
margin-top: 40rpx;
|
padding-top: 20rpx;
|
border-top: 1rpx solid #ebeef5;
|
}
|
|
.btn-default {
|
flex: 1;
|
}
|
|
.btn-primary {
|
flex: 2;
|
}
|
</style>
|