<template>
|
<view class="container">
|
<!-- 标题栏 -->
|
<Nav :title="formData.name" :customBack="formData.router"></Nav>
|
|
<!-- 基础信息区域 -->
|
<view class="info-section">
|
<view class="info-item" v-for="(item, index) in infoList" :key="index">
|
<view class="item-label">{{ item.label }}</view>
|
<view class="item-value" :class="{ status: item.status }">{{ item.value }}</view>
|
</view>
|
</view>
|
|
<!-- 表单切换标签 -->
|
<view class="tab-bar" v-if="ishowDisplay">
|
<view class="tab-item" :class="{ active: activeTab === 'upload' }" @tap="switchTab('upload')">
|
上传行程
|
</view>
|
<view class="tab-item" :class="{ active: activeTab === 'advance' }" @tap="switchTab('advance')">
|
上报垫付
|
</view>
|
</view>
|
|
|
<!-- 上传行程表单 -->
|
<view class="form-section" v-if="activeTab === 'upload' && ishowDisplay">
|
<!-- 单选操作按钮组(遍历优化) -->
|
<view class="action-buttons-container">
|
<view class="action-buttons-row" >
|
<view v-for="(row, rowIndex) in actionButtonRows" :key="rowIndex" style="position: relative">
|
<text class="badge" v-if="!['0','1','4','5','8','100'].includes(row.dictValue) && row.count > 0">{{ row.count }}</text>
|
<button class="action-btn"
|
:class="{ selected: selectedAction == row.dictValue, disabled: getBtnDisabled(row) , success: getBtnSuccess(row) }"
|
@tap="selectAction(row)">
|
{{ row.dictLabel }}
|
|
</button>
|
</view>
|
</view>
|
</view>
|
|
<u--form ref="uForm" :rules="rules" :model="form" labelPosition="left">
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="address">
|
<!-- <view style="display: flex; align-items: center; width: 100%;">
|
<view style="display: flex; align-items: center; flex-shrink: 0; margin-right: 10px;">
|
<u--image :showLoading="true" src="/static/bt.png" width="20px" height="20px"></u--image>
|
<text>地址:</text>
|
</view>
|
<view @click="getLocation" style="width: 100%;">
|
<u--input placeholder="请获取地址" readonly v-model="form.address" suffixIcon="map-fill"
|
suffixIconStyle="color: #909399"></u--input>
|
</view>
|
|
|
</view> -->
|
<view style="display: flex; align-items: flex-start; width: 100%;">
|
<!-- 左侧标签(带必填星号) -->
|
<view style="display: flex; align-items: center; flex-shrink: 0; margin-right: 10px; padding-top: 12rpx;">
|
<u--image :showLoading="true" src="/static/bt.png" width="20px" height="20px"></u--image>
|
<text style="display: flex; align-items: center;">
|
<span style="color: #ff4d4f; margin-right: 4rpx;">*</span> <!-- 红色必填星号 -->
|
地址:
|
</text>
|
</view>
|
|
<!-- 右侧文本框+图标(带边框,图标在框内) -->
|
<view style="position: relative; width: 100%; margin-top: 6rpx;" @click="getLocation">
|
<view class="custom-textarea" style="border: 1px solid #e5e5e5;">
|
<u--text :lines="2" :text="form.address"></u--text>
|
<view style="position: absolute; top: 50%; right: 10rpx; transform: translateY(-50%);">
|
<u-icon name="map-fill" color="#909399" size="24" @click="getLocation"></u-icon>
|
</view>
|
</view>
|
|
</view>
|
</view>
|
</u-form-item>
|
|
|
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="tripTime">
|
<view style="display: flex; align-items: center; width: 100%;">
|
<view style="display: flex; align-items: center; flex-shrink: 0; margin-right: 10px;">
|
<u--image :showLoading="true" src="/static/bt.png" width="20px" height="20px"></u--image>
|
<text>时间:</text>
|
</view>
|
<uni-datetime-picker type="datetime" v-model="form.tripTime" style="flex: 1;" @change="onDateTimeChange">
|
</uni-datetime-picker>
|
</view>
|
</u-form-item>
|
|
<!-- <u-form-item ref="item1" v-if="selectedAction !=='1'" borderBottom label=" " labelWidth="0" prop="odometer">
|
<view style="display: flex; align-items: center; width: 100%;">
|
<view style="display: flex; align-items: center; flex-shrink: 0; margin-right: 10px;">
|
<u--image :showLoading="true" src="/static/bt.png" width="20px" height="20px"></u--image>
|
<text>仪表里程(km):</text>
|
</view>
|
|
<u-number-box v-model="form.odometer" style="width: 45%;margin-left: 2%;" :min="0" :step="1"
|
button-size="28" color="#1e1e1e" bg-color="#ebecee" integer>
|
<view slot="minus" class="minus">
|
<div
|
style="width: 30rpx;height: 28rpx;background-color: #ebecee;display: flex;justify-content: center;align-items: center;border-radius: 4rpx;">
|
<u-icon name="minus" color="#1e1e1e" size="12"></u-icon>
|
</div>
|
</view>
|
<div style="margin-left: 5rpx;margin-right: 5rpx;width: 70%;" slot="input" class="input">
|
<u--input placeholder="请输入仪表里程" type="number"
|
style="background-color: #ebecee;border-radius: 4rpx;height: 28rpx;font-size: 14px;" border="surround"
|
inputAlign="center" v-model="form.odometer"></u--input>
|
</div>
|
<view slot="plus" class="plus">
|
<div
|
style="width: 30rpx;height: 28rpx;background-color: #ebecee;display: flex;justify-content: center;align-items: center;border-radius: 4rpx;">
|
<u-icon name="plus" color="#1e1e1e" size="12"></u-icon>
|
</div>
|
</view>
|
</u-number-box>
|
|
|
</view>
|
|
|
</u-form-item> -->
|
|
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="" :borderBottom="false">
|
<view style="display: flex;align-items: center;"><u--image :showLoading="true" src="/static/bt.png"
|
width="20px" height="20px"></u--image>凭证<span
|
style="color: #c6c0ba;margin-left: 10px;display: inline-block;"></span></view>
|
</u-form-item>
|
<!-- 行程凭证上传区域(5个指定位置) -->
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="voucher" :borderBottom="false">
|
<view style="margin: 20rpx 0;">
|
<!-- 上传区域网格容器 -->
|
<view class="upload-grid">
|
<!-- 遍历5个上传区域 -->
|
<view class="upload-item" v-for="(area, index) in uploadAreas" :key="index">
|
<!-- 已上传图片时显示预览 -->
|
<view class="upload-img-preview" v-if="area.imageUrl">
|
<image :src="area.imageUrl" mode="aspectFill"></image>
|
<view class="delete-btn" @click.stop="deleteAreaPic(index)">
|
<u-icon name="close-circle" color="#fff" size="36rpx"></u-icon>
|
</view>
|
</view>
|
|
<!-- 未上传时显示占位框 -->
|
<view class="upload-placeholder" v-else @click="chooseAreaPic(index)">
|
<u-icon name="plus" color="#ccc" size="48rpx"></u-icon>
|
<text class="area-name">{{ area.name }}</text>
|
</view>
|
</view>
|
</view>
|
</view>
|
</u-form-item>
|
|
|
|
|
</u--form>
|
<view class="bottom-btn-group">
|
<u-button class="btn-list" @click="goThistory" text="行程历史"></u-button>
|
<u-button class="btn-list" @click="goToAdvanceList" text="垫付列表"></u-button>
|
<!-- <u-button class="btn-budget" @click="goToAdvanceBudget" type="success" text="垫付预算"></u-button> -->
|
<u-button class="btn-submit" @click="submitForm" type="primary" text="提交"></u-button>
|
</view>
|
|
</view>
|
|
|
|
|
<!-- 上报垫付表单 -->
|
<view class="form-section" v-if="activeTab === 'advance' && ishowDisplay">
|
|
<u--form ref="uForm" :rules="rules" :model="form" labelPosition="left">
|
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="feeType">
|
<view style="display: flex; align-items: center; width: 100%;">
|
<view style="display: flex; align-items: center; flex-shrink: 0; margin-right: 10px;">
|
<u--image :showLoading="true" src="/static/bt.png" width="20px" height="20px"></u--image>
|
<text>费用类型</text>
|
</view>
|
|
<!-- <uni-number-box v-model="form.odometer" @change="changeValue" /> -->
|
<uni-data-select v-model="form.feeType" :localdata="range" ></uni-data-select>
|
</view>
|
</u-form-item>
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="currency">
|
<view style="display: flex; align-items: center; width: 100%;">
|
<view style="display: flex; align-items: center; flex-shrink: 0; margin-right: 20px;">
|
<u--image :showLoading="true" src="/static/bt.png" width="20px" height="20px"></u--image>
|
<text>币制</text>
|
</view>
|
|
<!-- <uni-number-box v-model="form.odometer" @change="changeValue" /> -->
|
<uni-data-select v-model="form.currency" :localdata="currencyRange"></uni-data-select>
|
</view>
|
</u-form-item>
|
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="actualFeeAmount">
|
<view style="display: flex; align-items: center; width: 100%;">
|
<view style="display: flex; align-items: center; flex-shrink: 0; margin-right: 10px;">
|
<u--image :showLoading="true" src="/static/bt.png" width="20px" height="20px"></u--image>
|
<text>垫付金额:</text>
|
</view>
|
|
<!-- <uni-number-box v-model="form.actualFeeAmount" @change="changeValue" :max="9999999" :min="0" /> -->
|
|
<u-number-box v-model="form.actualFeeAmount" style="width: 45%;margin-left: 2%;" :min="0" :step="1"
|
button-size="28" color="#1e1e1e" bg-color="#ebecee" integer>
|
<view slot="minus" class="minus">
|
<div
|
style="width: 30rpx;height: 28rpx;background-color: #ebecee;display: flex;justify-content: center;align-items: center;border-radius: 4rpx;">
|
<u-icon name="minus" color="#1e1e1e" size="12"></u-icon>
|
</div>
|
</view>
|
<div style="margin-left: 5rpx;margin-right: 5rpx;width: 70%;" slot="input" class="input">
|
<u--input placeholder="请输入垫付金额" type="number"
|
style="background-color: #ebecee;border-radius: 4rpx;height: 28rpx;font-size: 14px;" border="surround"
|
inputAlign="center" v-model="form.actualFeeAmount"></u--input>
|
</div>
|
<view slot="plus" class="plus">
|
<div
|
style="width: 30rpx;height: 28rpx;background-color: #ebecee;display: flex;justify-content: center;align-items: center;border-radius: 4rpx;">
|
<u-icon name="plus" color="#1e1e1e" size="12"></u-icon>
|
</div>
|
</view>
|
</u-number-box>
|
|
</view>
|
</u-form-item>
|
|
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="" :borderBottom="false">
|
<view style="display: flex;align-items: center;"><u--image :showLoading="true" src="/static/bt.png"
|
width="20px" height="20px"></u--image>垫付凭证<span
|
style="color: #c6c0ba;margin-left: 10px;display: inline-block;"></span></view>
|
</u-form-item>
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="fileList" :borderBottom="false">
|
<view style="margin-right: 10px;"></view>
|
<u-upload :fileList="fileList" name="file" multiple :maxCount="6" :maxSize="2 * 1024 * 1024"
|
@afterRead="afterRead" :previewFullImage="true" @delete="deletePic" @oversize="overSize">
|
</u-upload>
|
|
</u-form-item>
|
|
|
|
|
|
|
</u--form>
|
<view class="bottom-btn-group">
|
<u-button class="btn-list" @click="goThistory" text="行程历史"></u-button>
|
<u-button class="btn-list" @click="goToAdvanceList" text="垫付列表"></u-button>
|
<!-- <u-button class="btn-budget" @click="goToAdvanceBudget" type="success" text="垫付预算"></u-button> -->
|
<u-button class="btn-submit" @click="submitForm" type="primary" text="提交"></u-button>
|
</view>
|
|
|
</view>
|
|
|
<view class="bottom-btn-group" v-if="!ishowDisplay">
|
<u-button class="btn-list" @click="goThistory" text="行程历史"></u-button>
|
<!-- <u-button class="btn-budget" @click="goToAdvanceBudget" type="success" text="垫付预算"></u-button> -->
|
<u-button class="btn-list" @click="goToAdvanceList" text="垫付列表"></u-button>
|
|
</view>
|
|
|
<view class="popup-mask" v-if="showPopup" @click="showPopup = false"></view>
|
<view class="popup-container" v-if="showPopup" :class="{ 'popup-show': showPopup }">
|
<view class="popup-title">仪表里程填写</view>
|
<u--form ref="uForm" :rules="rules" :model="form" labelPosition="left">
|
<u-form-item ref="item1" borderBottom label=" " labelWidth="0" prop="odometer">
|
<view style="display: flex; align-items: center; width: 100%;">
|
<view style="display: flex; align-items: center; flex-shrink: 0; margin-right: 10px;">
|
<u--image :showLoading="true" src="/static/bt.png" width="20px" height="20px"></u--image>
|
<text>仪表里程(km):</text>
|
</view>
|
|
<u-number-box v-model="form.odometer" style="width: 45%;margin-left: 2%;" :min="0" :step="1"
|
button-size="28" color="#1e1e1e" bg-color="#ebecee" integer>
|
<view slot="minus" class="minus">
|
<div
|
style="width: 30rpx;height: 28rpx;background-color: #ebecee;display: flex;justify-content: center;align-items: center;border-radius: 4rpx;">
|
<u-icon name="minus" color="#1e1e1e" size="12"></u-icon>
|
</div>
|
</view>
|
<div style="margin-left: 5rpx;margin-right: 5rpx;width: 70%;" slot="input" class="input">
|
<u--input placeholder="请输入仪表里程" type="number"
|
style="background-color: #ebecee;border-radius: 4rpx;height: 28rpx;font-size: 14px;" border="surround"
|
inputAlign="center" v-model="form.odometer"></u--input>
|
</div>
|
<view slot="plus" class="plus">
|
<div
|
style="width: 30rpx;height: 28rpx;background-color: #ebecee;display: flex;justify-content: center;align-items: center;border-radius: 4rpx;">
|
<u-icon name="plus" color="#1e1e1e" size="12"></u-icon>
|
</div>
|
</view>
|
</u-number-box>
|
|
|
</view>
|
|
|
</u-form-item>
|
</u--form>
|
|
|
<!-- 底部按钮 -->
|
<view class="btn-group">
|
<u-button class="cancel-btn" @click="showPopup = false" type="info" plain>
|
取消
|
</u-button>
|
<u-button class="submit-btn" @click="handleSubmit" type="primary">
|
提交
|
</u-button>
|
</view>
|
</view>
|
<u-popup :show="show" round="10" mode="center" :closeable="true" @close="closeAction" ref="popup">
|
<view class="popup-const">
|
<text class="popup-const-title">该节点已提交过数据,无法重复添加</text>
|
<view class="df">
|
<text class="label-left">提交时间: </text>
|
<text>{{ activeActive.createTime }}</text>
|
|
</view>
|
<view class="df">
|
<text class="label-left">提交地址</text>
|
<text>{{ activeActive.address }}</text>
|
</view>
|
<view class="df">
|
<text class="label-left">提交凭证</text>
|
<view class="voucher-grid">
|
<view class="voucher-item" v-for="(img, imgIndex) in activeActive.feeVoucherUrl" :key="imgIndex">
|
<image class="voucher-img" :src="img" mode="aspectFill"></image>
|
</view>
|
<!-- 当没有图片时显示提示 -->
|
<view v-if="!activeActive.feeVoucherUrl || activeActive.feeVoucherUrl.length === 0" class="no-voucher">
|
暂无凭证
|
</view>
|
</view>
|
</view>
|
|
</view>
|
|
</u-popup>
|
</view>
|
</template>
|
|
<script>
|
function groupBy(array, key){
|
return array.reduce((acc, item) => {
|
const groupKey = String(item[key]);
|
(acc[groupKey] ||= []).push(item);
|
return acc;
|
}, {});
|
}
|
|
import { getcarDispatch, getcarType, carUploadTrip, carUploadFinance,getAssignedItineraryLogList,tmsTripList } from "@/common/examine";
|
import config from '@/config'
|
import amap from '@/common/amap-wx.130.js'
|
import store from '@/store'
|
export default {
|
data() {
|
return {
|
show: false,
|
showOdometerPopup: false,
|
showPopup: false,
|
activeTab: 'upload',
|
formData: {
|
name: '',
|
router: '',
|
id: '',
|
tripTime: '',
|
},
|
uploadAreas: [
|
{ name: '血压酒精', imageUrl: '' ,required: true},
|
{ name: '登记表', imageUrl: '' ,required: true},
|
],
|
mapApiKey: 'fdb2d2e64ffc9254045935d3227d5cd9', // <-- 替换成你的 API Key
|
amapPlugin: null,
|
fileList: [],
|
range: [
|
|
],
|
historyList:[],
|
currencyRange: [],
|
feeTypeList: [],
|
currencyList: [],
|
ishowDisplay: false,
|
emptyNameStr: '',
|
cleanedForm: {},
|
newForm: {},
|
selectedAction: '',
|
infoList: [
|
{ label: '调度单号', value: '' },
|
{ label: '运输工具号码', value: '' },
|
{ label: '路线', value: '' },
|
{ label: '客户', value: '' },
|
{ label: '当前状态', value: '待发车', status: true },
|
{ label: '要求最晚发车时间', value: '' }
|
],
|
|
actionButtonRows: [
|
|
],
|
actionButtonArray: [
|
|
],
|
tmsTripTables:[],
|
form: {
|
address: '',
|
tripTime: '',
|
odometer: 0,
|
tripType: '',
|
},
|
rules: {
|
|
address: [{ required: true, message: '请输入地址', trigger: 'blur' }],
|
tripTime: [{ required: true, message: '请选择时间', trigger: 'change' }], // 修改这里
|
feeType: [{ required: true, message: '请选择费用类型', trigger: 'change' }],
|
currency: [{ required: true, message: '请选择币制', trigger: 'change' }],
|
|
|
// voucher: [{ required: true, message: '请上传凭证', trigger: 'blur' }]
|
},
|
mapList: {},
|
activeActive: {},
|
|
|
};
|
},
|
onLoad(options) {
|
this.formData = options;
|
//"查看行程历史" "上传行程"
|
if (options.name == '查看行程历史') {
|
this.ishowDisplay = false;
|
} else if (options.name == '上传行程') {
|
this.ishowDisplay = true;
|
}
|
this.amapPlugin = new amap.AMapWX({
|
key: this.mapApiKey
|
});
|
// 获取 URL 参数
|
if (options.id) {
|
//this.getList();
|
this.getDispatch();
|
this.getDictList();
|
this.form.tripTime = this.getCurrentDateTime();
|
|
}
|
},
|
created() {
|
// this.getList();
|
},
|
methods: {
|
getBtnDisabled(row){
|
// 身体检查
|
if (row.dictValue == 1 && row.count > 0){
|
return true;
|
}else if (row.dictValue == 0 ){
|
// 发车
|
if (this.mapList['1']&& this.mapList['1'].length == 0){
|
return true;
|
}else if (row.count > 0){
|
return true;
|
}
|
}else {
|
if (this.mapList['0']&& this.mapList['0'].length == 0){
|
return true
|
}
|
}
|
return false;
|
|
},
|
getBtnSuccess(row){
|
// 身体检查
|
if (row.dictValue == 1 && row.count > 0){
|
return true;
|
}else if (row.dictValue == 0 && row.count > 0){
|
// 发车
|
return true;
|
}else if (row.dictValue == 4 && row.count > 0) {
|
//到达清关场地
|
return true;
|
}else if (row.dictValue == 5 && row.count > 0) {
|
//离开清关场地
|
return true;
|
}else if (row.dictValue == 8 && row.count > 0) {
|
//回场
|
return true;
|
}else if (row.dictValue == 100 && row.count > 0) {
|
//放空
|
return true;
|
}
|
return false;
|
|
},
|
|
async getDictList(){
|
|
const fee_type_res = await getcarType('fee_type');
|
this.range = fee_type_res.map(item => ({
|
value: item.dictValue,
|
text: item.dictLabel
|
}));
|
const sys_currency_res = await getcarType('sys_currency');
|
this.currencyRange = sys_currency_res.map(item => ({
|
value: item.dictValue,
|
text: item.dictLabel
|
}));
|
|
const trip_type_res = await getcarType('trip_type');
|
this.actionButtonRows = trip_type_res || [];
|
|
const tmsTripListRes = await tmsTripList(this.formData.id) || [];
|
let tripTypeGropList = groupBy(tmsTripListRes, 'tripType');
|
|
this.actionButtonRows.forEach(item =>{
|
item.count = tripTypeGropList[item.dictValue] ? tripTypeGropList[item.dictValue].length : 0;
|
})
|
this.$forceUpdate();
|
this.mapList = tripTypeGropList;
|
this.tmsTripTables = tmsTripListRes;
|
},
|
getDispatch(){
|
let fieldMap = []
|
// 定义字段映射关系
|
if (this.ishowDisplay) {
|
this.infoList = [
|
{ label: '调度单号', value: '' },
|
{ label: '运输工具号码', value: '' },
|
{ label: '路线', value: '' },
|
{ label: '客户', value: '' },
|
{ label: '当前状态', value: '待发车', status: true },
|
{ label: '要求最晚发车时间', value: '' },
|
{ label: '装货地', value: '' },
|
{ label: '卸货地', value: '' },
|
],
|
|
fieldMap = {
|
dispatchNo: '调度单号',
|
licensePlate: '运输工具号码',
|
transportLine: '路线',
|
customerName: '客户',
|
statusStr: '当前状态',
|
latestDeparture: '要求最晚发车时间',
|
shipperAddress: '装货地',
|
receiverAddress: '卸货地',
|
};
|
|
|
} else {
|
this.infoList = [
|
{ label: '调度单号', value: '' },
|
{ label: '运输工具号码', value: '' },
|
{ label: '路线', value: '' },
|
{ label: '客户', value: '' },
|
{ label: '完成时间', value: '' },
|
{ label: '装货地', value: '' },
|
{ label: '卸货地', value: '' },
|
],
|
fieldMap = {
|
dispatchNo: '调度单号',
|
licensePlate: '运输工具号码',
|
transportLine: '路线',
|
customerName: '客户',
|
okTime: '完成时间',
|
shipperAddress: '装货地',
|
receiverAddress: '卸货地',
|
};
|
|
}
|
getcarDispatch(this.formData.id).then((res) => {
|
this.newForm = res;
|
|
// 遍历 infoList,自动更新 value
|
this.infoList = this.infoList.map(item => {
|
const key = Object.keys(fieldMap).find(k => fieldMap[k] === item.label);
|
if (key && res[key] !== undefined) {
|
return { ...item, value: res[key] };
|
}
|
return item;
|
});
|
}).catch(err => {
|
console.error('获取调度信息失败:', err);
|
});
|
|
|
},
|
getCurrentDateTime() {
|
var now = new Date();
|
var year = now.getFullYear();
|
var month = (now.getMonth() + 1).toString().padStart(2, '0');
|
var day = now.getDate().toString().padStart(2, '0');
|
var hour = now.getHours().toString().padStart(2, '0');
|
var minute = now.getMinutes().toString().padStart(2, '0');
|
var second = now.getSeconds().toString().padStart(2, '0');
|
return year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second;
|
},
|
goThistory() {
|
setTimeout(() => {
|
uni.$u.route('/pages/travelItinerary/index?id=' + this.formData.id + '&name=' + '行程历史' + '&statusStr=' + this.formData.statusStr + '&router=' + '/pages/examine/index');
|
}, 1000);
|
|
},
|
getList() {
|
|
getcarType('trip_type').then((res) => {
|
this.actionButtonRows = res;
|
if (res.length > 0) {
|
tmsTripList(this.formData.id).then((res1) => {
|
this.historyList = res1;
|
console.log( this.historyList,'this.historyList');
|
this.historyList.forEach(item => {
|
// 查找匹配的dictLabel
|
const matchedDict = this.actionButtonArray.find(dictItem => dictItem.dictValue == item.tripType);
|
item.statusStr = matchedDict ? matchedDict.dictLabel : '';
|
});
|
|
}).catch(err => {
|
console.error('获取调度信息失败:', err);
|
});
|
}
|
|
|
}).catch(err => {
|
});
|
getcarType('fee_type').then((res) => {
|
this.feeTypeList = res
|
this.range = res.map(item => ({
|
value: item.dictValue,
|
text: item.dictLabel
|
}));
|
|
}).catch(err => {
|
});
|
getcarType('sys_currency').then((res) => {
|
this.currencyList = res
|
this.currencyRange = res.map(item => ({
|
value: item.dictValue,
|
text: item.dictLabel
|
}));
|
|
}).catch(err => {
|
});
|
},
|
// 获取经纬度
|
getLocation() {
|
wx.getLocation({
|
type: 'gcj02',
|
success: (res) => {
|
const latitude = res.latitude;
|
const longitude = res.longitude;
|
this.getAddress(latitude, longitude);
|
},
|
fail: (err) => {
|
console.error('获取位置失败:', err);
|
wx.showToast({ title: '获取位置失败'+err, icon: 'none' });
|
}
|
});
|
},
|
|
getAddress(latitude, longitude) {
|
this.amapPlugin.getRegeo({
|
location:`${longitude},${latitude}`,
|
success: (data) => {
|
this.form.address = data[0].name;
|
},
|
fail: (err) => {
|
console.error("SDK调用失败:", err);
|
wx.showToast({ title: '地址解析失败'+JSON.stringify(err) + latitude+ longitude, icon: 'none' });
|
}
|
});
|
|
},
|
switchTab(tab) {
|
this.activeTab = tab;
|
this.form = {
|
address: '',
|
tripTime: '',
|
odometer: 0,
|
tripType: '',
|
actualFeeAmount: 0
|
}
|
this.fileList = []
|
this.selectedAction = ''
|
|
},
|
closeAction(){
|
this.show = false;
|
|
},
|
selectAction(row) {
|
|
if (this.getBtnSuccess(row)){
|
this.activeActive = this.mapList[row.dictValue][0];
|
if (this.activeActive.voucherUrl) {
|
this.activeActive.feeVoucherUrl = this.activeActive.voucherUrl.split(',').filter(url => url.trim() !== '');
|
} else {
|
this.activeActive.feeVoucherUrl = [];
|
}
|
// 已经完成
|
this.show = true;
|
return;
|
}
|
if(this.getBtnDisabled(row)){
|
return;
|
}
|
const type = row.dictValue;
|
// 设置选中的操作类型
|
this.selectedAction = type;
|
console.log(type);
|
|
if (type == '0') {
|
this.uploadAreas = [
|
{ name: '仪表盘', imageUrl: '' ,required: true},
|
{ name: '左前方', imageUrl: '' ,required: true},
|
{ name: '右前方', imageUrl: '' ,required: true},
|
{ name: '后方', imageUrl: '' ,required: true},
|
{ name: '开箱检查', imageUrl: '' ,required: true},
|
|
]
|
} else if (type == '1') {
|
this.uploadAreas = [
|
{ name: '血压酒精', imageUrl: '' ,required: true},
|
{ name: '登记表', imageUrl: '',required: true },
|
]
|
}
|
|
else if (type == '2'||type == '6'){ // 到达装货点 到达卸货点
|
this.uploadAreas = [
|
{ name: '车头', imageUrl: '',required: true },
|
{ name: '车尾(非必填)', imageUrl: '',required: false },
|
{ name: '仪表盘(非必填)', imageUrl: '',required: false },
|
|
|
]
|
}
|
else if (type == '3'||type == '7'){// 装货离场 卸货离场
|
this.uploadAreas = [
|
{ name: '车头', imageUrl: '',required: true },
|
{ name: '车尾', imageUrl: '',required: true },
|
{ name: '仪表盘(非必填)', imageUrl: '',required: false },
|
]
|
}else if (type == '4'||type == '5'){// 到达清关场地 离开清关场地
|
this.uploadAreas = [
|
{ name: '仪表盘(非必填)', imageUrl: '',required: false },
|
{ name: '车头(非必填)', imageUrl: '',required: false },
|
{ name: '车尾(非必填)', imageUrl: '',required: false },
|
]
|
}else{
|
this.uploadAreas = [
|
{ name: '车头', imageUrl: '',required: true },
|
{ name: '仪表盘', imageUrl: '',required: true },
|
|
{ name: '车尾', imageUrl: '',required: true },
|
]
|
}
|
// 同时更新表单中的 tripType 字段
|
this.form.tripType = type;
|
|
if(type !== '1'){
|
if (['3','5','7'].includes(type)){
|
let item = this.tmsTripTables[0] || {};
|
this.form.odometer = item.odometer;
|
}else{
|
this.form.odometer = 0
|
}
|
|
|
this.$nextTick(() => {
|
this.showPopup = true;
|
});
|
}
|
// wx.showToast({
|
// title: `已选择${type}`,
|
// icon: 'none'
|
// });
|
},
|
maskClick() {
|
|
},
|
// 新增图片
|
async afterRead(event) {
|
// 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
|
let lists = [].concat(event.file)
|
let fileListLen = this.fileList.length
|
lists.map((item) => {
|
this.fileList.push({
|
...item,
|
status: 'success',
|
message: '上传中'
|
})
|
})
|
for (let i = 0; i < lists.length; i++) {
|
|
const result = await this.uploadFilePromise(lists[i].url)
|
let item = this.fileList[fileListLen]
|
this.fileList.splice(fileListLen, 1, Object.assign(item, {
|
status: result.status,
|
message: result.status == 'success' ? '上传成功' : '上传失败',
|
urls: result.url
|
}))
|
fileListLen++
|
}
|
},
|
|
uploadFilePromise(url) {
|
const param = {
|
filePath: url,
|
type: 'images'
|
}
|
return new Promise((resolve, reject) => {
|
uni.uploadFile({
|
url: config.host + `app/car/uploadImg`, // 仅为示例,非真实的接口地址
|
filePath: url,
|
name: 'file',
|
header: {
|
"Authorization": store.state.sso_user_token
|
},
|
success: (res) => {
|
console.log(res)
|
if (res.statusCode == 200) {
|
const dataObject = JSON.parse(res.data);
|
// 修复返回的URL路径
|
let imageUrl = '';
|
if (dataObject.fileName.startsWith('http')) {
|
imageUrl = dataObject.fileName;
|
} else if (dataObject.url) {
|
imageUrl = dataObject.url; // 如果返回的数据中有url字段直接使用
|
} else {
|
imageUrl = config.host.replace('/cwgltest-api/', '') + dataObject.fileName;
|
}
|
|
resolve({
|
url: imageUrl,
|
status: 'success'
|
})
|
} else {
|
resolve({
|
status: 'failed',msg: JSON.stringify(res)
|
})
|
}
|
},
|
fail: (err) => {
|
reject({ status: 'failed',msg: JSON.stringify(err) });
|
}
|
});
|
})
|
},
|
// 图片大小超出最大允许大小
|
overSize(e) {
|
uni.$u.toast('上传图片大小不能超过2MB!')
|
},
|
// 删除图片
|
deletePic(event) {
|
this.fileList.splice(event.index, 1)
|
},
|
onDateTimeChange(event) {
|
// this.form.workTime = event.detail.value;
|
},
|
|
changeValue(e) {
|
this.form.odometer = e
|
},
|
cleanFormData(formData) {
|
const cleanedData = {};
|
for (const key in formData) {
|
if (formData[key] !== '' && formData[key] !== null && formData[key] !== undefined) {
|
cleanedData[key] = formData[key];
|
}
|
}
|
return cleanedData;
|
},
|
goToAdvanceList() {
|
// 使用箭头函数保持 this 上下文
|
setTimeout(() => {
|
uni.$u.route('/pages/paymentList/index?name=' + '垫付列表' + '&router=' + '/pages/examine/index' + '&id=' + this.formData.id);
|
}, 1000);
|
},
|
|
|
/* 上传 */
|
chooseAreaPic(index) {
|
// 调用uview的上传组件方法(或原生uni.chooseImage)
|
uni.chooseImage({
|
count: 1, // 每次只能选1张
|
sizeType: ['original', 'compressed'],
|
sourceType: ['album', 'camera'],
|
success: (res) => {
|
|
const tempFilePath = res.tempFilePaths[0];
|
// 上传图片到服务器
|
this.uploadAreaPic(tempFilePath, index);
|
}
|
});
|
},
|
|
// 上传图片到服务器并更新对应区域
|
async uploadAreaPic(tempFilePath, index) {
|
try {
|
const result = await this.uploadFilePromise(tempFilePath);
|
if (result.status === 'success') {
|
// 修复这一行,移除对result.tempFilePaths的引用
|
this.uploadAreas[index].imageUrl = result.url;
|
} else {
|
uni.showToast({ title: '上传失败'+result.msg, icon: 'none' });
|
}
|
} catch (err) {
|
|
uni.showToast({ title: '上传失败'+err.msg, icon: 'none' });
|
}
|
},
|
|
// 删除指定区域的图片
|
deleteAreaPic(index) {
|
uni.showModal({
|
title: '提示',
|
content: '确定要删除这张图片吗?',
|
success: (res) => {
|
if (res.confirm) {
|
this.uploadAreas[index].imageUrl = '';
|
}
|
}
|
});
|
},
|
|
// 表单提交时验证图片是否完整(根据需求调整必填项)
|
submitForm() {
|
|
|
// 根据当前激活的标签页执行不同的提交逻辑
|
if (this.activeTab == 'upload') {
|
// 检查行程上传表单
|
if (this.form.tripType == '') {
|
uni.$u.toast('请选择行程类型')
|
return
|
}
|
|
this.emptyNameStr = this.uploadAreas
|
.filter(item => item.imageUrl === '' && item.required) // 只筛选 imageUrl 为空的项
|
.map(item => item.name) // 提取 name
|
.join(','); // 逗号拼接
|
|
if (this.emptyNameStr) {
|
wx.showToast({
|
title: `未上传:${this.emptyNameStr}`,
|
icon: 'none',
|
duration: 3000
|
});
|
} else {
|
// 验证是否至少上传了一张图片
|
// 收集所有上传的图片地址(用逗号分隔)
|
|
const voucherUrls = this.uploadAreas.filter(item => item.imageUrl!=='').map(item => item.imageUrl).join(',');
|
this.form.voucherUrl = voucherUrls;
|
|
this.$refs.uForm.validate().then(res => {
|
if (res) {
|
this.form.dispatchOrderId = this.newForm.dispatchId
|
this.form.driverId = this.newForm.driverId
|
/* 跳转 */
|
if (this.form.tripType == 1) {
|
/*设置 */
|
// console.log(this.form);
|
|
uni.setStorageSync("signContractForm", this.form);
|
setTimeout(() => {
|
uni.$u.route('/pages/signContract/index');
|
}, 1000);
|
} else {
|
/* 上传行程发车 */
|
carUploadTrip(this.form).then((res) => {
|
if (res == 1) {
|
uni.$u.toast('操作成功')
|
// 重置表单
|
this.form = {
|
address: '',
|
tripTime: '',
|
odometer: 0,
|
tripType: ''
|
}
|
// 重置上传区域
|
this.uploadAreas = this.uploadAreas.map(area => ({
|
...area,
|
imageUrl: ''
|
}))
|
this.selectedAction = '';
|
this.getDictList()
|
}
|
}).catch(err => {
|
uni.$u.toast('提交失败')
|
})
|
}
|
|
}
|
}).catch(errors => {
|
uni.$u.toast('校验失败')
|
})
|
|
|
|
// wx.showToast({ title: '所有区域均已上传', icon: 'success' });
|
}
|
|
|
|
|
} else if (this.activeTab == 'advance') {
|
// 检查垫付上传表单
|
if (this.fileList.length == 0) {
|
uni.$u.toast('图片上传不能为空')
|
return
|
}
|
|
this.$refs.uForm.validate().then(res => {
|
if (res) {
|
var urls = this.fileList.map(item => item.urls).join(',');
|
this.form.feeVoucherUrl = urls
|
this.form.dispatchOrderId = this.newForm.dispatchId
|
this.form.driverId = this.newForm.driverId
|
this.form.dispatchNo = this.newForm.dispatchNo
|
this.form.licensePlate = this.newForm.licensePlate
|
this.form.transportLine = this.newForm.transportLine
|
this.form.customerName = this.newForm.customerName
|
|
this.cleanedForm = this.cleanFormData({ ...this.form })
|
carUploadFinance(this.cleanedForm).then((res) => {
|
if (res == 1) {
|
uni.$u.toast('操作成功')
|
// 重置表单
|
this.form = {
|
address: '',
|
tripTime: '',
|
odometer: 0,
|
tripType: ''
|
}
|
this.cleanedForm = {}
|
this.fileList = []
|
this.selectedAction = ''
|
}
|
}).catch(err => {
|
uni.$u.toast('提交失败')
|
})
|
}
|
}).catch(errors => {
|
uni.$u.toast('校验失败')
|
})
|
}
|
|
// this.$forceUpdate();
|
},
|
|
|
|
handleSubmit() {
|
// 简单校验:里程不能为负数
|
if (this.form.odometer < 0) {
|
uni.$u.toast('仪表里程不能为负数');
|
return;
|
}
|
this.getLocation()
|
this.form.tripTime = this.getCurrentDateTime();
|
this.showPopup = false;
|
}
|
|
}
|
};
|
</script>
|
|
<style scoped>
|
.container {
|
display: flex;
|
flex-direction: column;
|
height: 100vh;
|
background-color: #f7f7f7;
|
}
|
|
.info-section {
|
background-color: #fff;
|
margin: 20rpx;
|
border-radius: 12rpx;
|
//overflow: hidden;
|
}
|
|
.info-item {
|
display: flex;
|
padding: 20rpx;
|
border-bottom: 1rpx solid #eee;
|
}
|
|
.info-item:last-child {
|
border-bottom: none;
|
}
|
|
.item-label {
|
width: 180rpx;
|
color: #666;
|
font-size: 28rpx;
|
}
|
|
.item-value {
|
flex: 1;
|
color: #333;
|
font-size: 28rpx;
|
}
|
|
.item-value.status {
|
color: #ff6b6b;
|
font-weight: 500;
|
}
|
|
.tab-bar {
|
display: flex;
|
height: 80rpx;
|
background-color: #fff;
|
border-bottom: 1rpx solid #eee;
|
}
|
|
.tab-item {
|
flex: 1;
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
font-size: 28rpx;
|
color: #666;
|
position: relative;
|
height: 80rpx;
|
/* 确保高度 */
|
z-index: 1;
|
/* 确保层级 */
|
}
|
|
.tab-item.active {
|
color: #4285f4;
|
font-weight: 500;
|
}
|
|
.tab-item.active::after {
|
content: '';
|
position: absolute;
|
bottom: 0;
|
left: 50%;
|
transform: translateX(-50%);
|
width: 60rpx;
|
height: 6rpx;
|
background-color: #4285f4;
|
border-radius: 3rpx;
|
}
|
|
.form-section {
|
padding: 20rpx;
|
background-color: #fff;
|
border-radius: 12rpx;
|
box-shadow: 0 2rpx 10rpx rgba(0, 0, 0, 0.05);
|
overflow-y: auto;
|
}
|
|
/* 上传行程-单选操作按钮组(自适应换行样式) */
|
.action-buttons-container {
|
margin-bottom: 30rpx;
|
}
|
|
.action-buttons-row {
|
gap: 20rpx;
|
/* margin-bottom: 20rpx; */
|
display: grid;
|
grid-template-columns: repeat(auto-fill, 150rpx);
|
grid-gap: 20rpx;
|
min-width: 100%;
|
}
|
|
.action-btn {
|
width: 150rpx;
|
height: 80rpx;
|
line-height: 80rpx;
|
text-align: center;
|
font-size: 25rpx;
|
border-radius: 8rpx;
|
background-color: #fff;
|
border: 1rpx solid #eee;
|
color: #333;
|
transition: all 0.2s ease;
|
/* 使用 flex 布局确保一致性 */
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
/* 关键:设置文本溢出处理 */
|
overflow: hidden;
|
white-space: nowrap;
|
text-overflow: ellipsis;
|
}
|
|
/* 选中状态样式 */
|
.action-btn.selected {
|
background-color: #e8f4f8;
|
border-color: #4285f4;
|
color: #4285f4;
|
font-weight: 500;
|
}
|
|
.action-btn::after {
|
border: none;
|
}
|
|
/* 选中按钮按压反馈 */
|
.action-btn.selected:active {
|
background-color: #d1e7fd;
|
}
|
|
/* 未选中按钮按压反馈 */
|
.action-btn:not(.selected):active {
|
background-color: #f5f5f5;
|
}
|
|
.form-item {
|
margin-bottom: 30rpx;
|
}
|
|
.form-label {
|
font-size: 28rpx;
|
color: #333;
|
margin-bottom: 16rpx;
|
display: flex;
|
align-items: center;
|
}
|
|
.required-tag {
|
display: inline-block;
|
width: 24rpx;
|
height: 24rpx;
|
line-height: 24rpx;
|
text-align: center;
|
background-color: #e53e3e;
|
color: #fff;
|
font-size: 20rpx;
|
border-radius: 50%;
|
margin-left: 8rpx;
|
}
|
|
.form-control {
|
display: flex;
|
align-items: center;
|
border: 1rpx solid #eee;
|
border-radius: 8rpx;
|
padding: 16rpx;
|
background-color: #f9f9f9;
|
}
|
|
.form-control input {
|
flex: 1;
|
font-size: 28rpx;
|
}
|
|
.icon {
|
width: 32rpx;
|
height: 32rpx;
|
margin-left: 16rpx;
|
}
|
|
.form-control input[disabled] {
|
background-color: #f9f9f9;
|
color: #999;
|
}
|
|
.picker-value {
|
flex: 1;
|
font-size: 28rpx;
|
color: #333;
|
}
|
|
.bottom-buttons {
|
display: flex;
|
gap: 20rpx;
|
margin-top: 40rpx;
|
}
|
|
.bottom-btn {
|
flex: 1;
|
height: 80rpx;
|
line-height: 80rpx;
|
text-align: center;
|
font-size: 28rpx;
|
border-radius: 8rpx;
|
background-color: #fff;
|
border: 1rpx solid #eee;
|
color: #333;
|
}
|
|
.bottom-btn.primary {
|
background-color: #4285f4;
|
color: #fff;
|
border: none;
|
}
|
|
.bottom-btn::after {
|
border: none;
|
}
|
|
/* 按钮 */
|
.bottom-btn-group {
|
display: flex;
|
gap: 20rpx;
|
padding: 30rpx;
|
}
|
|
|
/* 上传区域网格容器 */
|
.upload-grid {
|
display: grid;
|
grid-template-columns: repeat(3, 1fr);
|
/* 3列布局 */
|
gap: 20rpx;
|
/* 间距 */
|
padding: 10rpx 0;
|
}
|
|
/* 单个上传项 */
|
.upload-item {
|
width: 100%;
|
height: 200rpx;
|
/* 固定高度 */
|
position: relative;
|
}
|
|
/* 未上传时的占位框 */
|
.upload-placeholder {
|
width: 100%;
|
height: 100%;
|
border: 2rpx dashed #ddd;
|
/* 虚线边框 */
|
border-radius: 8rpx;
|
display: flex;
|
flex-direction: column;
|
justify-content: center;
|
align-items: center;
|
background-color: #f9f9f9;
|
cursor: pointer;
|
}
|
|
/* 区域名称文本 */
|
.area-name {
|
font-size: 24rpx;
|
color: #666;
|
margin-top: 16rpx;
|
}
|
|
/* 已上传图片的预览 */
|
.upload-img-preview {
|
width: 100%;
|
height: 100%;
|
border-radius: 8rpx;
|
overflow: hidden;
|
position: relative;
|
}
|
|
.upload-img-preview image {
|
width: 100%;
|
height: 100%;
|
object-fit: cover;
|
/* 保持比例填充 */
|
}
|
|
/* 删除按钮 */
|
.delete-btn {
|
position: absolute;
|
top: -10rpx;
|
right: -10rpx;
|
width: 40rpx;
|
height: 40rpx;
|
border-radius: 50%;
|
background-color: rgba(0, 0, 0, 0.5);
|
display: flex;
|
justify-content: center;
|
align-items: center;
|
z-index: 10;
|
}
|
|
/* 文本框样式优化:内边距+占位符 */
|
::v-deep .custom-textarea {
|
padding: 16rpx 50rpx 16rpx 16rpx !important;
|
/* 上下内边距稍大,右侧留图标位置 */
|
min-height: 80rpx;
|
}
|
|
/* 占位符样式:灰色,和图片一致 */
|
::v-deep .custom-textarea textarea::placeholder {
|
color: #c6c0ba !important;
|
/* 浅灰色占位符 */
|
font-size: 28rpx;
|
}
|
|
/* 确保文本框边框不被覆盖 */
|
::v-deep .custom-textarea .uni-textarea {
|
border: none !important;
|
/* 去掉组件自带边框,用外层自定义边框 */
|
}
|
/* ========== 新增:里程弹窗样式 ========== */
|
.popup-mask {
|
position: fixed;
|
top: 0;
|
left: 0;
|
right: 0;
|
bottom: 0;
|
background-color: rgba(0, 0, 0, 0.5);
|
z-index: 998;
|
transition: opacity 0.3s;
|
}
|
|
.popup-container {
|
position: fixed;
|
top: 50%;
|
left: 50%;
|
transform: translate(-50%, -50%) scale(0.8);
|
background-color: #ffffff;
|
border-radius: 20rpx;
|
z-index: 999;
|
padding: 30rpx;
|
box-sizing: border-box;
|
width: 90%;
|
max-width: 500px;
|
transition: transform 0.3s ease-out, opacity 0.3s ease-out;
|
opacity: 0;
|
}
|
|
.popup-show {
|
transform: translate(-50%, -50%) scale(1);
|
opacity: 1;
|
}
|
|
.popup-title {
|
font-size: 34rpx;
|
color: #333333;
|
font-weight: 600;
|
text-align: center;
|
margin-bottom: 40rpx;
|
padding-bottom: 20rpx;
|
border-bottom: 1rpx solid #f0f0f0;
|
}
|
|
/* 底部按钮 */
|
.btn-group {
|
display: flex;
|
gap: 20rpx;
|
margin-top: 40rpx;
|
}
|
|
.cancel-btn,
|
.submit-btn {
|
flex: 1;
|
height: 90rpx;
|
line-height: 90rpx;
|
font-size: 32rpx;
|
}
|
|
.disabled{
|
background-color: #f7f7f7;
|
color: rgba(0,0,0,.3);
|
}
|
.success{
|
background-color: rgba(202, 249, 130, 0.52);
|
color: rgba(0,0,0,.3);
|
}
|
.popup-const{
|
width: 80%;
|
background-color: #ffffff;
|
margin: 0 auto;
|
border-radius: 5px;
|
box-sizing:border-box;
|
|
|
}
|
.popup-const-title{
|
font-weight: bold;
|
line-height: 58px;
|
text-align: center;
|
}
|
.df{
|
display: flex;
|
margin-bottom: 10px;
|
|
}
|
.label-left{
|
width: 80px;
|
flex: 0 0 80px;
|
}
|
/* 凭证网格 */
|
.voucher-grid {
|
display: flex;
|
flex-wrap: wrap; /* 允许换行 */
|
gap: 10rpx;
|
}
|
|
/* 凭证项 */
|
.voucher-item {
|
width: 120rpx;
|
height: 120rpx;
|
position: relative;
|
border: 1rpx solid #eee;
|
border-radius: 6rpx;
|
overflow: hidden;
|
flex-shrink: 0; /* 防止压缩 */
|
}
|
|
/* 凭证图片 */
|
.voucher-img {
|
width: 100%;
|
height: 100%;
|
position: absolute;
|
top: 0;
|
left: 0;
|
}
|
/* 添加无凭证提示样式 */
|
.no-voucher {
|
color: #999;
|
font-size: 28rpx;
|
}
|
.badge{
|
position: absolute;
|
right: 0;
|
top: -5px;
|
font-size: 10px;
|
background: blue;
|
color: #fff;
|
padding: 2px;
|
z-index: 999;
|
}
|
</style>
|