| | |
| | | </el-select> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="是否存在应付报价"> |
| | | <span :style="{ color: row.isCZYF == 0 ? 'red' : '' }">{{ row.isCZYF == 0 ? '否' : row.isCZYF == 1 ? '是' : |
| | | ''}}</span> |
| | | <span :style="{ color: row.isCZYF == 0 ? 'red' : '' }">{{ row.isCZYF == 0 ? '否' : row.isCZYF == 1 ? '是' |
| | | : |
| | | '' }}</span> |
| | | |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="计费金额"> |
| | |
| | | <el-descriptions-item label="币制"> |
| | | <el-radio-group v-model="row.yfCurrency"> |
| | | <el-radio v-for="dict in sys_currency" :key="dict.value" :label="dict.value">{{ dict.label |
| | | }}</el-radio> |
| | | }}</el-radio> |
| | | </el-radio-group> |
| | | </el-descriptions-item> |
| | | <el-descriptions-item label="计费数量"> |
| | |
| | | <div v-if="active === 'tab2'"> |
| | | <h2>实报实销费用</h2> |
| | | <avue-form v-model="boxForm" ref="boxFormRef" :option="boxFormOption"> |
| | | <template #voucherUrl="{ row }"> |
| | | <el-upload class="upload-demo" ref="uploadRef" :limit="1" drag :action="urlApi + '/common/upload2'" multiple |
| | | :show-file-list="true" :on-success="(res) => handleUploadAfter(res, row)" |
| | | :on-exceed="(files) => handleExceed(files, row)"> |
| | | <el-icon class="el-icon--upload"><upload-filled /></el-icon> |
| | | <div class="el-upload__text"> |
| | | 点击或将图片拖拽到此区域上传 |
| | | </div> |
| | | |
| | | </el-upload> |
| | | </template> |
| | | </avue-form> |
| | | <avue-crud :option="boxTableOption" :data="boxTableData"> |
| | | <avue-crud :option="boxTableOption" :data="boxTableData" @selection-change="boxSelectionChange"> |
| | | <template #menu-left> |
| | | <el-button type="danger" plain icon="Delete" |
| | | :disabled="!(boxSelectionList.length === 1 && boxSelectionList[0]?.status === 0)" |
| | | @click="handleBatchBoxDel"> |
| | | 作废 |
| | | </el-button> |
| | | </template> |
| | | <template #isYF="{ row }"> |
| | | <el-checkbox v-model="row.isYF" :true-value="1" :false-value="0" |
| | | <el-checkbox v-model="row.isYF" :disabled="row.status == 1" :true-value="1" :false-value="0" |
| | | @change="(e: number) => isYFChange(e, row)"></el-checkbox> |
| | | </template> |
| | | <template #yfServiceProviderId="{ row }"> |
| | | <el-select v-model="row.yfServiceProviderIdType" placeholder="请选择服务商" |
| | | <el-select :disabled="row.status == 1" v-model="row.yfServiceProviderIdType" placeholder="请选择服务商" |
| | | @change="(e: any) => ysServiceProviderChange(e, row)" :filterable="true"> |
| | | <el-option v-for="item in serviceProviderList" |
| | | :key="item.serviceProviderId + '_' + item.serviceProviderType" :label="item.serviceProviderName" |
| | |
| | | </el-select> |
| | | </template> |
| | | <template #yfPrice="{ row }"> |
| | | <el-input v-model="row.yfPrice" :min="1" type="number" placeholder="请输入金额"></el-input> |
| | | <el-input :disabled="row.status == 1" v-model="row.yfPrice" :min="1" type="number" |
| | | placeholder="请输入金额"></el-input> |
| | | </template> |
| | | <template #yfCurrency="{ row }"> |
| | | <el-radio-group v-model="row.yfCurrency"> |
| | | <el-radio-group v-model="row.yfCurrency" :disabled="row.status == 1"> |
| | | <el-radio v-for="dict in sys_currency" :key="dict.value" :label="dict.value">{{ dict.label }}</el-radio> |
| | | </el-radio-group> |
| | | </template> |
| | |
| | | updateTmsDispatchOrder, |
| | | generateTmsDispatchOrder, initGenerate, initYSGenerate, |
| | | ysGenerateTmsDispatchOrder, initYFGenerate, yfGenerateTmsDispatchOrder, |
| | | getServiceProvider, checkCloseOrder, closeOrder |
| | | getServiceProvider, checkCloseOrder, closeOrder, tmsFinanceDetail |
| | | } from "@/api/tms/tmsDispatchOrder"; |
| | | import useCurrentInstance from "@/utils/useCurrentInstance"; |
| | | import { computed, onMounted, reactive, ref, toRefs, watch, getCurrentInstance, nextTick } from "vue"; |
| | |
| | | import { listTmsLoadingServiceProvider } from "@/api/tms/tmsLoadingServiceProvider"; |
| | | import { selectPaymentTmsQuotePlan } from "@/api/tms/tmsQuotePlan"; |
| | | import { addTmsQuoteFee, listTmsQuoteFee, pushTmsQuoteFee } from "@/api/tms/tmsQuoteFee"; |
| | | import { status } from "nprogress"; |
| | | |
| | | |
| | | |
| | |
| | | }; |
| | | const data = reactive({ |
| | | form: <TmsDispatchOrderI>{}, |
| | | selectionList2: <any>[], |
| | | boxSelectionList: <any>[], |
| | | queryParams: <TmsDispatchOrderI & PageQueryInterface>{}, |
| | | page: <PagesInterface>{ |
| | | pageSize: 10, |
| | |
| | | open: false, |
| | | open2: false, |
| | | goodsTableData: <any>[], |
| | | selectionList2: <any>[], |
| | | goodsForm: <any>{}, |
| | | open3: false, |
| | | actualForm: <any>{}, |
| | |
| | | }) |
| | | const { |
| | | queryParams, form, page, selectionList, |
| | | boxTableData, optionType, open, open5, |
| | | boxTableData, optionType, open, open5, boxSelectionList, |
| | | boxFormOption, boxForm, boxTableOption, boxItemTableOption, selectionList2, isCustoms, isLoad, active, quotationItems, serviceProviderList |
| | | } = toRefs(data); |
| | | const option = ref({ |
| | |
| | | display: true, |
| | | }, |
| | | voucherUrl: { |
| | | label: '行程凭证', |
| | | label: '行程凭证3', |
| | | display: true, |
| | | span: 24, dataType: 'string', |
| | | type: 'upload', |
| | |
| | | display: true, |
| | | accept: 'string', dataType: 'string', |
| | | type: 'upload', |
| | | action: '/common/upload2', |
| | | |
| | | // action: '/common/upload2', |
| | | slot: true, |
| | | }, |
| | | remark: { |
| | | label: '备注', span: 24, |
| | |
| | | const financeTableOption = ref({ |
| | | menu: false, |
| | | addBtn: false, |
| | | header: false, selection: false, |
| | | header: true, |
| | | selection: true, |
| | | title: '历史垫付费用', |
| | | column: { |
| | | dataSource: { |
| | |
| | | yfCurrency: { |
| | | label: '应付币制', |
| | | display: true, |
| | | |
| | | } |
| | | |
| | | }, |
| | | status: { |
| | | label: '状态', |
| | | display: true, |
| | | type: 'select', dicUrl: '/system/dict/data/type/sys_cancel_word', dataType: 'string', |
| | | }, |
| | | } |
| | | }) |
| | | |
| | |
| | | console.log(pageF.single) |
| | | }, |
| | | |
| | | |
| | | getBeginListFunc: (params = {}) => { |
| | | // 1. 日期转换 |
| | | let newParams = <any>{ ...params }; |
| | | if (newParams) { |
| | | // 1. 定义日期字段映射 (数组名 : 接口需要的前缀) |
| | | // 这样写的好处是:如果你有多个日期,直接在这里添加一行即可 |
| | | const dateMap = { |
| | | createTimeRange: 'createTime', |
| | | updateTimeRange: 'updateTime', |
| | | confirmTimeRange: 'confirmTime', |
| | | okTimeRange: 'okTime', |
| | | // 1. 使用浅拷贝,不影响原始查询对象 |
| | | // 关键点:从原始 queryParams.value 取值,确保分页时依然能拿到数组 |
| | | let newParams = { ...queryParams.value, ...params }; |
| | | |
| | | }; |
| | | // 2. 定义日期字段映射 (数组名 : 接口需要的前缀) |
| | | const dateMap = { |
| | | createTimeRange: 'createTime', |
| | | updateTimeRange: 'updateTime', |
| | | confirmTimeRange: 'confirmTime', |
| | | okTimeRange: 'okTime', |
| | | }; |
| | | |
| | | // 2. 遍历处理日期 |
| | | Object.keys(dateMap).forEach(arrayKey => { |
| | | const prefix = dateMap[arrayKey]; |
| | | const range = newParams[arrayKey]; |
| | | // 3. 遍历处理日期 |
| | | Object.keys(dateMap).forEach(arrayKey => { |
| | | const prefix = dateMap[arrayKey]; |
| | | const range = newParams[arrayKey]; |
| | | |
| | | if (Array.isArray(range) && range.length > 0) { |
| | | // 赋值 Begin 和 End |
| | | newParams[`${prefix}Begin`] = range[0]; |
| | | newParams[`${prefix}End`] = range[1]; |
| | | } |
| | | if (Array.isArray(range) && range.length === 2) { |
| | | // 赋值接口需要的 Begin 和 End |
| | | newParams[`${prefix}Begin`] = range[0]; |
| | | newParams[`${prefix}End`] = range[1]; |
| | | } |
| | | |
| | | // 【核心改动】:无论是否有值,处理完后都把原始的 Array 字段删掉 |
| | | // 这样请求里就不会出现 confirmTimeRangeArray: [...] |
| | | delete newParams[arrayKey]; |
| | | }); |
| | | // 只在给接口的参数中删除数组,不影响页面显示的 queryParams |
| | | delete newParams[arrayKey]; |
| | | }); |
| | | |
| | | // 3. 通用清洗:删除所有空字符串、null 或 undefined 的其他字段 |
| | | Object.keys(newParams).forEach(key => { |
| | | const val = newParams[key]; |
| | | if (val === '' || val === null || val === undefined) { |
| | | delete newParams[key]; |
| | | } |
| | | }); |
| | | // 4. 清洗参数:过滤空值 |
| | | const finalParams = {}; |
| | | Object.keys(newParams).forEach(key => { |
| | | const val = newParams[key]; |
| | | if (val !== '' && val !== null && val !== undefined) { |
| | | finalParams[key] = val; |
| | | } |
| | | }); |
| | | |
| | | } else { |
| | | newParams = {}; |
| | | } |
| | | console.log('发送给接口的最终参数:', finalParams); |
| | | |
| | | return newParams; |
| | | |
| | | // 【核心修改】:直接返回,不要赋值给 queryParams.value |
| | | return finalParams; |
| | | }, |
| | | |
| | | }) |
| | |
| | | |
| | | const submitForm = () => { |
| | | if (active.value === 'tab1') { |
| | | console.log() |
| | | pushTmsQuoteFee({ |
| | | ...form.value, |
| | | quoteFeeItems: selectionList2.value |
| | |
| | | if (Array.isArray(boxForm.value.feeVoucherUrl)) { |
| | | boxForm.value.feeVoucherUrl = boxForm.value.feeVoucherUrl.toString(); |
| | | } |
| | | |
| | | boxForm.value.rowItems = boxTableData.value; |
| | | saveTmsFinanceDetail(boxForm.value).then(res => { |
| | | ElMessage({ |
| | |
| | | type: 'success' |
| | | }) |
| | | boxFormRef.value?.resetFields(); |
| | | uploadRef.value?.clearFiles(); |
| | | getTab2Data(); |
| | | }) |
| | | } |
| | |
| | | const quotePlanItemRes2 = await listTmsQuoteItem({ quotePlanId: form.value.quotePlanId, pageNum: 1, pageSize: 999 }); |
| | | let list = quotePlanItemRes2.rows || []; |
| | | let quotePlanItemRes = await getDicts("sys_quotation_items"); |
| | | console.log(quotePlanItemRes) |
| | | let items = quotePlanItemRes.data || []; |
| | | let res = await listTmsQuoteFee({ dispatchId: form.value.id, pageNum: 1, pageSize: 999 }); |
| | | let rowsData = res.rows || []; |
| | |
| | | if (value == 1) { |
| | | let find: any = quotationItems.value.find((item: any) => item.dictLabel === row.feeType); |
| | | if (find) { |
| | | console.log(find, "find") |
| | | let opt = find.remark; |
| | | row.serviceProviderType = opt; |
| | | if (opt == 0) { |
| | |
| | | let receivableAmountHKD = items.filter((cItem: any) => cItem.currency == 'HKD').reduce((pre: any, cur: any) => { |
| | | return pre + Number(cur.registerAmount) |
| | | }, 0); |
| | | console.log(receivableAmountRMB, receivableAmountHKD) |
| | | item.receivableAmountRMB = receivableAmountRMB; |
| | | item.receivableAmountHKD = receivableAmountHKD; |
| | | |
| | |
| | | } |
| | | const submitForm5 = () => { |
| | | boxFormRef.value.validate((valid: boolean, done: any) => { |
| | | console.log(valid) |
| | | if (valid) { |
| | | boxForm.value.id = form.value.id; |
| | | closeOrder(boxForm.value).then(res => { |
| | |
| | | } |
| | | }) |
| | | } |
| | | const uploadRef = ref<any>() |
| | | const urlApi = ref(import.meta.env.VITE_APP_BASE_API) |
| | | // 在 script 部分修改 handleUploadAfter 函数 |
| | | const handleUploadAfter = (res: any, row: any) => { |
| | | if (res.code === 200) { |
| | | // 确保 res.data.url 存在 |
| | | const url = res.data?.url || res.url; |
| | | if (url) { |
| | | boxForm.value.feeVoucherUrl = url |
| | | } else { |
| | | ElMessage.error('未获取到上传文件 URL'); |
| | | } |
| | | } else { |
| | | ElMessage.error(res.msg || '上传失败'); |
| | | } |
| | | }; |
| | | |
| | | // 同时修改 handleExceed 函数 |
| | | const handleExceed = (files: any, row: any) => { |
| | | if (!row) { |
| | | ElMessage.error('行数据为空'); |
| | | return; |
| | | } |
| | | |
| | | uploadRef.value?.clearFiles(); |
| | | const file = files[0]; |
| | | uploadRef.value?.handleStart(file); |
| | | uploadRef.value?.submit(); |
| | | }; |
| | | |
| | | const boxSelectionChange = (selection: any[]) => { |
| | | boxSelectionList.value = selection; |
| | | } |
| | | /** |
| | | * 批量作废费用明细 |
| | | */ |
| | | const handleBatchBoxDel = () => { |
| | | if (boxSelectionList.value.length === 0) { |
| | | ElMessage.warning('请选择要作废的费用明细'); |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm(`确认要作废选中的 ${boxSelectionList.value.length} 条费用明细吗?`, '警告', { |
| | | confirmButtonText: '确定', |
| | | cancelButtonText: '取消', |
| | | type: 'warning' |
| | | }).then(() => { |
| | | // 从 boxTableData 中移除选中的项 |
| | | // const ids = boxSelectionList.value.map((item: any) => item.id).join(','); |
| | | let data = { |
| | | id: boxSelectionList.value[0].id, |
| | | status: 1 |
| | | } |
| | | tmsFinanceDetail(data).then(res => { |
| | | ElMessage.success('作废成功'); |
| | | getTab2Data(); // 刷新数据 |
| | | }).catch(err => { |
| | | ElMessage.error('作废失败'); |
| | | }); |
| | | // ElMessage.success('作废成功'); |
| | | // boxSelectionList.value = []; // 清空选择 |
| | | }).catch(() => { |
| | | // 取消操作 |
| | | }); |
| | | } |
| | | </script> |