sen
2026-03-31 cc41746818af3b619167947ecb4401ccdfbec2d8
ui/car_wx_app/pages/examine/index.vue
@@ -1,1616 +1,47 @@
<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" v-if="uploadAreas.length > 0">
          <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 :loading="loading" 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 :loading="loading" 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>
          <view v-if="form.tripType == '5'"  style="display: flex; align-items: center; width: 100%; margin-top: 15px">
            <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>
              <u-radio-group
                  v-model="form.iscc"  iconPlacement="right"
                  placement="row">
                <u-radio  label="是" name="0" style="margin-right: 20px"></u-radio>
                <u-radio  label="否" name="1"></u-radio>
              </u-radio-group>
          </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 class="redirect-container">
    <u-loading-icon text="加载中..." />
  </view>
</template>
<script>
import {uploadImage} from "@/common/upload";
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'
/**
 * 路由分发页面
 * 根据参数自动跳转到 detail(详情页)或 operate(操作页)
 * 保持向后兼容
 */
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: {},
      isHk:false,
      loading: false
    };
  },
  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
    });
    const { id, name, ...rest } = options
    // 获取 URL 参数
    if (options.id) {
      //this.getList();
      this.getDispatch();
      this.getDictList();
      this.form.tripTime = this.getCurrentDateTime();
    // 构建查询参数
    const query = Object.entries({ id, ...rest })
      .filter(([_, v]) => v !== undefined && v !== null)
      .map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
      .join('&')
    // 根据 name 参数判断跳转目标
    let targetPage = '/pages/examine/detail'
    if (name === '上传行程') {
      targetPage = '/pages/examine/operate'
    } else if (name === '查看行程历史' || name === '调度详情' || !name) {
      targetPage = '/pages/examine/detail'
    }
    this.getLocation();
  },
  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.form.longitude =longitude;
          this.form.latitude =latitude;
          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) => {
          let datum = data[0];
          if (datum.regeocodeData){
            if (datum.regeocodeData.addressComponent){
              let province = datum.regeocodeData.addressComponent.province;
              this.isHk = province.indexOf("香港") != -1;
            }
          }
          this.form.address  = datum.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 if (type == '8'){
        this.uploadAreas = [
          { name: '车头', imageUrl: '',required: true },
          { name: '仪表盘', imageUrl: '',required: true },
          { name: '车尾', imageUrl: '',required: true },
          { 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;
          this.form.iscc = "1";
        }else{
          this.form.odometer = 0
        }
        this.$nextTick(() => {
          this.showPopup = true;
        });
      }
      // wx.showToast({
      //   title: `已选择${type}`,
      //   icon: 'none'
      // });
    },
    maskClick() {
    },
    // 新增图片
    async afterRead(event) {
      // 当设置 multiple 为 true 时, file 为数组格式,否则为对象格式
      uploadImage(event.file[0].url,this.isHk).then(res=>{
        console.log(res)
        this.fileList.push(res);
      })
      // 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 tempFilePaths = res.tempFilePaths;
          const imgUrl = tempFilePaths[0];
          uploadImage(imgUrl,this.isHk).then(res2=>{
            this.uploadAreas[index].imageUrl = res2.url;
            // 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.loading){
         return;
      }
      // 根据当前激活的标签页执行不同的提交逻辑
      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 {
          // 验证是否至少上传了一张图片
          // 收集所有上传的图片地址(用逗号分隔)
         this.loading = true;
          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);
         setTimeout(()=>{
                     this.loading = false
                  },2000)
                uni.setStorageSync("signContractForm", this.form);
                setTimeout(() => {
                  uni.$u.route('/pages/signContract/index');
                }, 1000);
              } else {
                /* 上传行程发车 */
                carUploadTrip(this.form).then((res) => {
                  if (res == 1) {
                 setTimeout(()=>{
                    this.loading = false
                 },2000)
                    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('提交失败')
              setTimeout(()=>{
                 this.loading = false
              },2000)
                })
              }
            }
          }).catch(errors => {
            uni.$u.toast('校验失败')
         setTimeout(()=>{
            this.loading = false
         },2000)
          })
          // 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.url).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) {
              setTimeout(()=>{
                 this.loading = false
              },2000)
                uni.$u.toast('操作成功')
                // 重置表单
                this.form = {
                  address: '',
                  tripTime: '',
                  odometer: 0,
                  tripType: ''
                }
                this.cleanedForm = {}
                this.fileList = []
                this.selectedAction = ''
              }
            }).catch(err => {
              uni.$u.toast('提交失败')
           setTimeout(()=>{
              this.loading = false
           },2000)
            })
          }
        }).catch(errors => {
          uni.$u.toast('校验失败')
        setTimeout(()=>{
           this.loading = false
        },2000)
        })
      }
      // this.$forceUpdate();
    },
    handleSubmit() {
      // 简单校验:里程不能为负数
      if (this.form.odometer < 0) {
        uni.$u.toast('仪表里程不能为负数');
        return;
      }
      this.getLocation()
       this.form.tripTime = this.getCurrentDateTime();
      this.showPopup = false;
    }
    // 使用 redirectTo 替换当前页面,避免返回到这个中转页
    const url = query ? `${targetPage}?${query}` : targetPage
    uni.redirectTo({ url })
  }
};
}
</script>
<style scoped>
.container {
.redirect-container {
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  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>
<style lang="scss" scoped>
::v-deep .u-radio{
  margin-right: 20px;
}
::v-deep .u-radio__icon-wrap{
  margin-left: 10px;
}
</style>