tms/src/main/java/com/ruoyi/tms/service/impl/TmsArBillServiceImpl.java
@@ -21,6 +21,7 @@ import java.math.BigDecimal; import java.math.RoundingMode; import java.util.*; import java.util.stream.Collectors; import org.springframework.transaction.annotation.Transactional; import org.springframework.stereotype.Service; @@ -570,8 +571,8 @@ String rateStr = sysConfigService.selectConfigByKey("sys.hk.rmb.rate"); BigDecimal exchangeRate = new BigDecimal(rateStr); // 收集所有费用名称,用于动态生成列 Set<String> feeNames = new HashSet<>(); // 收集所有费用名称和对应的货币,用于动态生成列 Map<String, String> feeCurrencyMap = new HashMap<>(); for (TmsArBillItem item : bill.getItems()) { // 应收费用ID @@ -580,15 +581,33 @@ List<TmsReceivableFeeItem> tmsReceivableFeeItems = tmsReceivableFeeItemMapper.selectTmsReceivableFeeItemList(new TmsReceivableFeeItem() {{ setHeadId(arFeeId); }}); // 从应收费用明细中收集费用名称 // 从应收费用明细中收集费用名称和货币 for (TmsReceivableFeeItem feeItem : tmsReceivableFeeItems) { feeNames.add(feeItem.getFeeName()); feeCurrencyMap.put(feeItem.getFeeName(), feeItem.getCurrency()); } } // 将费用名称转换为列表,保持顺序 List<String> feeNameList = new ArrayList<>(feeNames); // 将费用名称转换为列表,并按要求排序:运费放在最前面,杂费放在最后面 List<String> feeNameList = new ArrayList<>(); List<String> otherFees = new ArrayList<>(); for (String feeName : feeCurrencyMap.keySet()) { if ("运费".equals(feeName)) { feeNameList.add(feeName); } else if ("杂费".equals(feeName)) { otherFees.add(feeName); } else { otherFees.add(feeName); } } // 添加其他费用 feeNameList.addAll(otherFees.stream().filter(fee -> !"杂费".equals(fee)).collect(Collectors.toList())); // 添加杂费到最后 if (feeCurrencyMap.containsKey("杂费")) { feeNameList.add("杂费"); } // 基础列数(序号、装货日期、装货点、卸货点、车牌、型号) int baseColumns = 6; @@ -614,7 +633,7 @@ createTitleArea(sheet, styles,bill); // 表头 createDynamicTableHeader(sheet, styles, feeNameList, baseColumns, remarkColumn); createDynamicTableHeader(sheet, styles, feeNameList, feeCurrencyMap, baseColumns, remarkColumn); // 数据区域 int startRow = 5; @@ -687,12 +706,8 @@ }}); // 处理应收费用明细 for (TmsReceivableFeeItem feeItem : tmsReceivableFeeItems) { BigDecimal amount = feeItem.getRegisterAmount(); // 如果是港币,转换为人民币 if ("HKD".equals(feeItem.getCurrency()) || "港币".equals(feeItem.getCurrency())) { amount = amount.multiply(exchangeRate).setScale(2, RoundingMode.HALF_UP); } feeMap.put(feeItem.getFeeName(), amount); // 保持原始金额,不进行币种转换 feeMap.put(feeItem.getFeeName(), feeItem.getRegisterAmount()); } // 填充费用列 @@ -707,9 +722,9 @@ feeTotals.put(feeName, feeTotals.get(feeName).add(feeAmount)); } // 备注 // 备注 - 为空 Cell remarkCell = row.createCell(remarkColumn); remarkCell.setCellValue("" + (fee.getDispatchNo() != null ? fee.getDispatchNo() : "")); remarkCell.setCellValue(""); remarkCell.setCellStyle(styles.get("data")); rowIndex++; @@ -746,13 +761,24 @@ if (i == 0) { cell.setCellValue("合计(RMB)"); } // 合计行的备注设置汇率 if (i == remarkColumn) { cell.setCellValue("汇率: " + exchangeRate); } cell.setCellStyle(styles.get("total")); } sheet.addMergedRegion(new CellRangeAddress(totalRow, totalRow, 0, 5)); // 计算所有费用的合计 // 计算所有费用的合计(转换为人民币) BigDecimal grandTotal = BigDecimal.ZERO; for (BigDecimal amount : feeTotals.values()) { for (String feeName : feeTotals.keySet()) { BigDecimal amount = feeTotals.get(feeName); // 获取该费用的币种 String currency = feeCurrencyMap.get(feeName); // 如果是港币,转换为人民币 if ("HKD".equals(currency) || "港币".equals(currency)) { amount = amount.multiply(exchangeRate).setScale(2, RoundingMode.HALF_UP); } grandTotal = grandTotal.add(amount); } @@ -898,7 +924,6 @@ * * @param sheet 工作表 * @param styles 样式映射 * @param tmsReceivableFee 应收费用查询条件 */ private void createTitleArea(SXSSFSheet sheet, Map<String, CellStyle> styles, TmsArBill tmsArBill) { // 标题行(无边框,居中) @@ -964,10 +989,11 @@ * @param sheet 工作表 * @param styles 样式映射 * @param feeNameList 费用名称列表 * @param feeCurrencyMap 费用名称到货币的映射 * @param baseColumns 基础列数 * @param remarkColumn 备注列位置 */ private void createDynamicTableHeader(SXSSFSheet sheet, Map<String, CellStyle> styles, List<String> feeNameList, int baseColumns, int remarkColumn) { private void createDynamicTableHeader(SXSSFSheet sheet, Map<String, CellStyle> styles, List<String> feeNameList, Map<String, String> feeCurrencyMap, int baseColumns, int remarkColumn) { Row headerRow = sheet.createRow(4); headerRow.setHeightInPoints(25); @@ -982,7 +1008,10 @@ // 费用列 for (int i = 0; i < feeNameList.size(); i++) { Cell cell = headerRow.createCell(baseColumns + i); cell.setCellValue(feeNameList.get(i) + "(人民币)"); String feeName = feeNameList.get(i); String currency = feeCurrencyMap.get(feeName); cell.setCellValue(feeName + "(" + currency + ")"); cell.setCellStyle(styles.get("header")); } tms/src/main/java/com/ruoyi/tms/service/impl/TmsDispatchOrderServiceImpl.java
@@ -1207,6 +1207,7 @@ // 2、 获取实报实销费用 List<TmsFinanceDetail> tmsFinanceDetails = tmsFinanceDetailService.selectTmsFinanceDetailList(new TmsFinanceDetail() {{ setDispatchOrderId(tmsDispatchOrder.getId()); setStatus(0); }}); if (tmsFinanceDetails != null && !tmsFinanceDetails.isEmpty()){ @@ -1326,6 +1327,7 @@ // 2、 获取实报实销费用 List<TmsFinanceDetail> tmsFinanceDetails = tmsFinanceDetailService.selectTmsFinanceDetailList(new TmsFinanceDetail() {{ setDispatchOrderId(tmsDispatchOrder.getId()); setStatus(0); setIsYF(1); }}); ui/admin-ui3/src/views/tms/tmsDispatchOrder/index.vue
@@ -202,7 +202,7 @@ </el-link> </el-tooltip> <!-- <!-- <el-tooltip content="完成行程" placement="top"> <el-link size="small" type="primary" v-if="[2].includes(row.status)" @click="handleOk(row)" class="link-btn" v-hasPermi="['tms:tmsDispatchOrder:okOrder']" underline="never" icon="el-icon-circle-check"> @@ -319,7 +319,7 @@ </div> <div v-if="optionType == 'loading'"> <el-descriptions v-if="optionNum == 'radio'" style="margin-bottom: 20px" :column="2" border> <el-descriptions v-if="optionNum == 'radio'" style="margin-bottom: 20px" :column="2" border> <el-descriptions-item label="调度单号">{{ form.dispatchNo }}</el-descriptions-item> <el-descriptions-item label="客户">{{ form.customerName }}</el-descriptions-item> <el-descriptions-item label="项目名称">{{ form.projectName }}</el-descriptions-item> @@ -728,6 +728,7 @@ const boxFormRef = ref(); const goodsCrudRef = ref(); const actualFormRef = ref(); const isAutoSettingVehicle = ref(false); /** * 字典公共转换函数 */ @@ -1356,38 +1357,52 @@ message: "主驾驶员不能为空", trigger: "change" } ], change: (val: any) => { // 防止重复执行 // 在 mainDriverId 的 change 事件中 change: async (val: any) => { if (data.isChanging) return; data.isChanging = true; isAutoSettingVehicle.value = true; const table = crudRef.value?.getPropRef?.('mainDriverId')?.$refs?.temp; if (!table) { data.isChanging = false; isAutoSettingVehicle.value = false; return; } let active = table.active; if (Array.isArray(active)) active = active[0]; console.log('自动填充成功:', active); if (active && active.driverName) { try { if (active) { Object.assign(form.value, { mainDriverId: active.id, mainDriverName: active.driverName, }); await nextTick(); // 等待清空生效 const res = await getLastLicensePlate(active.driverName); // 获取车牌号并赋值 getLastLicensePlate(active.driverName).then(res => { if (res.code == 200) { form.value.licensePlate = res.data.licensePlate; form.value.vehicleId = res.data.vehicleId form.value.actualVehicleType = res.data.vehicleType; if (res.code === 200 && res.data) { const vehicleData = res.data; nextTick(() => { Object.assign(form.value, { licensePlate: vehicleData.licensePlate, vehicleId: vehicleData.vehicleId, actualVehicleType: vehicleData.actualVehicleType, driverName: vehicleData.driverName, }); }) await nextTick(); console.log('自动填充成功:', form.value); } }).finally(() => { } catch (e) { console.error("自动获取车牌失败", e); } finally { data.isChanging = false; }); setTimeout(() => { // isAutoSettingVehicle.value = false; }, 500); // 稍微延长一点时间,防止 vehicleId 的 change 事件误触 } } else { data.isChanging = false; // isAutoSettingVehicle.value = false; } }, // change: (val: any) => { @@ -1403,7 +1418,7 @@ // mainDriverName: active.driverName, // }); // console.log(active.driverName,'44'); // getLastLicensePlate(active.driverName).then(res => { // getLastLicensePlate(active.driverName).then(res => { // console.log(res); // }) @@ -1415,7 +1430,7 @@ searchMenuSpan: 5, column: { vehicleProviderName: { label: '车辆服务商1', minWidth: 130, label: '车辆服务商', minWidth: 130, search: true, }, driverName: { @@ -1506,6 +1521,8 @@ if (Array.isArray(value)) { id = value[0] } console.log(98521); getTmsDriver(id).then(res => { return callback(res.data || {}) }) @@ -1534,11 +1551,19 @@ message: "车牌号不能为空", trigger: "change" } ], // vehicleId 配置中的 change change: (val: any) => { // 如果是自动填充触发的,直接返回,不执行后续逻辑 if (isAutoSettingVehicle.value) { return; } const table = crudRef.value?.getPropRef?.('vehicleId')?.$refs?.temp; if (!table) return; let active = table.active; if (Array.isArray(active)) active = active[0]; console.log(9852); if (active) { Object.assign(form.value, { vehicleId: active.id, @@ -1592,10 +1617,14 @@ if (Array.isArray(value)) { id = value[0] } console.log(555, 'xq1'); getTmsVehicle(id).then(res => { return callback(res.data || {}) }) } else { console.log(444, 'xq1'); listTmsVehicle({ pageSize: page.pageSize, pageNum: page.currentPage, ...data, @@ -2615,10 +2644,14 @@ if (Array.isArray(value)) { id = value[0] } console.log(998, 'xq1'); getTmsVehicle(id).then(res => { return callback(res.data || {}) }) } else { console.log(669, 'xq2'); listTmsVehicle({ pageSize: page.pageSize, pageNum: page.currentPage, ...data }).then(res => { return callback({ total: res.total, @@ -3563,7 +3596,7 @@ customsServiceProviderName: form.value.customsServiceProviderName }; }); }else if (optionNum.value == 'radio') { } else if (optionNum.value == 'radio') { result = [{ id: form.value.id, customsServiceProviderId: form.value.customsServiceProviderId, @@ -3583,7 +3616,7 @@ }) } else if (optionType.value === 'loading') { let result = <any>[]; let result = <any>[]; if (optionNum.value == 'checkbox') { result = clearanceList.value.map(item => { return { @@ -3592,7 +3625,7 @@ loadingServiceProviderName: form.value.loadingServiceProviderName }; }); }else if (optionNum.value == 'radio') { } else if (optionNum.value == 'radio') { result = [{ id: form.value.id, loadingServiceProviderId: form.value.loadingServiceProviderId, @@ -4247,7 +4280,7 @@ const handleCustomsAdd = (row) => { title.value = '补充委托装卸信息'; clearanceList.value = []; clearanceList.value = []; // 2. 清除表格视觉上的选中状态 if (crudRef.value) { crudRef.value.clearSelection();