| | |
| | | <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 class="redirect-container"> |
| | | <u-loading-icon text="加载中..." /> |
| | | </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' |
| | | /** |
| | | * 路由分发页面 |
| | | * 根据参数自动跳转到 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: {}, |
| | | |
| | | |
| | | }; |
| | | }, |
| | | 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(); |
| | | const { id, name, ...rest } = options |
| | | |
| | | } |
| | | }, |
| | | 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; |
| | | // 构建查询参数 |
| | | const query = Object.entries({ id, ...rest }) |
| | | .filter(([_, v]) => v !== undefined && v !== null) |
| | | .map(([k, v]) => `${k}=${encodeURIComponent(v)}`) |
| | | .join('&') |
| | | |
| | | }, |
| | | 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; |
| | | // 根据 name 参数判断跳转目标 |
| | | let targetPage = '/pages/examine/detail' |
| | | |
| | | }, |
| | | |
| | | 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; |
| | | if (name === '上传行程') { |
| | | targetPage = '/pages/examine/operate' |
| | | } else if (name === '查看行程历史' || name === '调度详情' || !name) { |
| | | targetPage = '/pages/examine/detail' |
| | | } |
| | | |
| | | // 使用 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> |