Showing
8 changed files
with
188 additions
and
17 deletions
| ... | @@ -31,7 +31,8 @@ public class InvoiceAddReq { | ... | @@ -31,7 +31,8 @@ public class InvoiceAddReq { |
| 31 | @Schema(description = "关联订单编号", required = true) | 31 | @Schema(description = "关联订单编号", required = true) |
| 32 | private String orderNo; | 32 | private String orderNo; |
| 33 | 33 | ||
| 34 | - @Schema(description = "关联出库单编号") | 34 | + @NotBlank(message = "关联出库单编号不能为空") |
| 35 | + @Schema(description = "关联出库单编号", required = true) | ||
| 35 | private String deliveryNo; | 36 | private String deliveryNo; |
| 36 | 37 | ||
| 37 | @NotBlank(message = "经销商编码不能为空") | 38 | @NotBlank(message = "经销商编码不能为空") | ... | ... |
| ... | @@ -35,7 +35,8 @@ public class InvoiceUpdateReq { | ... | @@ -35,7 +35,8 @@ public class InvoiceUpdateReq { |
| 35 | @Schema(description = "关联订单编号", required = true) | 35 | @Schema(description = "关联订单编号", required = true) |
| 36 | private String orderNo; | 36 | private String orderNo; |
| 37 | 37 | ||
| 38 | - @Schema(description = "关联出库单编号") | 38 | + @NotBlank(message = "关联出库单编号不能为空") |
| 39 | + @Schema(description = "关联出库单编号", required = true) | ||
| 39 | private String deliveryNo; | 40 | private String deliveryNo; |
| 40 | 41 | ||
| 41 | @NotBlank(message = "经销商编码不能为空") | 42 | @NotBlank(message = "经销商编码不能为空") | ... | ... |
| ... | @@ -2,11 +2,13 @@ package com.apple.erp.service.impl; | ... | @@ -2,11 +2,13 @@ package com.apple.erp.service.impl; |
| 2 | 2 | ||
| 3 | import com.apple.erp.dto.*; | 3 | import com.apple.erp.dto.*; |
| 4 | import com.apple.erp.entity.DeliveryItem; | 4 | import com.apple.erp.entity.DeliveryItem; |
| 5 | +import com.apple.erp.entity.OrderItem; | ||
| 5 | import com.apple.erp.entity.OrderMain; | 6 | import com.apple.erp.entity.OrderMain; |
| 6 | // rebate settlement handled by RebateSettlementService | 7 | // rebate settlement handled by RebateSettlementService |
| 7 | import com.apple.erp.service.RebateSettlementService; | 8 | import com.apple.erp.service.RebateSettlementService; |
| 8 | import com.apple.erp.mapper.DeliveryItemMapper; | 9 | import com.apple.erp.mapper.DeliveryItemMapper; |
| 9 | import com.apple.erp.mapper.OrderMainMapper; | 10 | import com.apple.erp.mapper.OrderMainMapper; |
| 11 | +import com.apple.erp.mapper.OrderItemMapper; | ||
| 10 | // removed unused mapper imports after delegating settlement logic | 12 | // removed unused mapper imports after delegating settlement logic |
| 11 | import com.apple.erp.util.TimingValidationUtil; | 13 | import com.apple.erp.util.TimingValidationUtil; |
| 12 | import com.apple.erp.exception.DealerMismatchException; | 14 | import com.apple.erp.exception.DealerMismatchException; |
| ... | @@ -48,6 +50,9 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del | ... | @@ -48,6 +50,9 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del |
| 48 | private OrderMainMapper orderMainMapper; | 50 | private OrderMainMapper orderMainMapper; |
| 49 | 51 | ||
| 50 | @Autowired | 52 | @Autowired |
| 53 | + private OrderItemMapper orderItemMapper; | ||
| 54 | + | ||
| 55 | + @Autowired | ||
| 51 | private TimingValidationUtil timingValidationUtil; | 56 | private TimingValidationUtil timingValidationUtil; |
| 52 | 57 | ||
| 53 | // rebate settlement is delegated; no local mapper usage required | 58 | // rebate settlement is delegated; no local mapper usage required |
| ... | @@ -157,6 +162,11 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del | ... | @@ -157,6 +162,11 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del |
| 157 | } | 162 | } |
| 158 | } | 163 | } |
| 159 | 164 | ||
| 165 | + // 业务校验:出库明细需与关联订单的商品至少部分匹配 | ||
| 166 | + validateAtLeastOneItemMatchesOrder(addReq.getOrderNo(), | ||
| 167 | + addReq.getDeliveryItems() == null ? new ArrayList<>() : | ||
| 168 | + addReq.getDeliveryItems().stream().map(DeliveryItemAddReq::getProductCode).collect(Collectors.toList())); | ||
| 169 | + | ||
| 160 | DeliveryMain deliveryMain = new DeliveryMain(); | 170 | DeliveryMain deliveryMain = new DeliveryMain(); |
| 161 | BeanUtils.copyProperties(addReq, deliveryMain); | 171 | BeanUtils.copyProperties(addReq, deliveryMain); |
| 162 | deliveryMain.setCreateTime(LocalDateTime.now()); | 172 | deliveryMain.setCreateTime(LocalDateTime.now()); |
| ... | @@ -230,6 +240,11 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del | ... | @@ -230,6 +240,11 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del |
| 230 | } | 240 | } |
| 231 | } | 241 | } |
| 232 | 242 | ||
| 243 | + // 业务校验:出库明细需与关联订单的商品至少部分匹配 | ||
| 244 | + validateAtLeastOneItemMatchesOrder(updateReq.getOrderNo(), | ||
| 245 | + updateReq.getDeliveryItems() == null ? new ArrayList<>() : | ||
| 246 | + updateReq.getDeliveryItems().stream().map(DeliveryItemUpdateReq::getProductCode).collect(Collectors.toList())); | ||
| 247 | + | ||
| 233 | DeliveryMain deliveryMain = new DeliveryMain(); | 248 | DeliveryMain deliveryMain = new DeliveryMain(); |
| 234 | BeanUtils.copyProperties(updateReq, deliveryMain); | 249 | BeanUtils.copyProperties(updateReq, deliveryMain); |
| 235 | deliveryMain.setUpdateTime(LocalDateTime.now()); | 250 | deliveryMain.setUpdateTime(LocalDateTime.now()); |
| ... | @@ -283,6 +298,39 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del | ... | @@ -283,6 +298,39 @@ public class DeliveryMainServiceImpl extends ServiceImpl<DeliveryMainMapper, Del |
| 283 | } | 298 | } |
| 284 | } | 299 | } |
| 285 | 300 | ||
| 301 | + /** | ||
| 302 | + * 校验至少有一条出库明细与关联订单的商品明细匹配(按产品编码匹配) | ||
| 303 | + * 若完全不匹配则抛出业务异常。 | ||
| 304 | + * | ||
| 305 | + * @param orderNo 订单编号 | ||
| 306 | + * @param deliveryProductCodes 出库明细中的产品编码列表 | ||
| 307 | + */ | ||
| 308 | + private void validateAtLeastOneItemMatchesOrder(String orderNo, List<String> deliveryProductCodes) { | ||
| 309 | + if (deliveryProductCodes == null || deliveryProductCodes.isEmpty()) { | ||
| 310 | + throw new IllegalArgumentException("出库明细不可为空"); | ||
| 311 | + } | ||
| 312 | + | ||
| 313 | + LambdaQueryWrapper<OrderItem> orderItemWrapper = Wrappers.lambdaQuery(OrderItem.class) | ||
| 314 | + .eq(OrderItem::getOrderNo, orderNo) | ||
| 315 | + .eq(OrderItem::getDelFlag, "0"); | ||
| 316 | + List<OrderItem> orderItems = orderItemMapper.selectList(orderItemWrapper); | ||
| 317 | + | ||
| 318 | + if (orderItems == null || orderItems.isEmpty()) { | ||
| 319 | + // 订单无商品时,视为不匹配 | ||
| 320 | + throw new IllegalArgumentException("关联的订单编号,商品明细项为空"); | ||
| 321 | + } | ||
| 322 | + | ||
| 323 | + // 判定是否存在至少一条产品编码匹配 | ||
| 324 | + boolean hasAnyMatch = orderItems.stream() | ||
| 325 | + .map(OrderItem::getProductCode) | ||
| 326 | + .filter(code -> code != null && !code.isEmpty()) | ||
| 327 | + .anyMatch(deliveryProductCodes::contains); | ||
| 328 | + | ||
| 329 | + if (!hasAnyMatch) { | ||
| 330 | + throw new IllegalArgumentException("出库明细必须至少包含一项与关联订单对应的产品明细,请检查后重新提交"); | ||
| 331 | + } | ||
| 332 | + } | ||
| 333 | + | ||
| 286 | // 结转逻辑已抽取到 RebateSettlementService | 334 | // 结转逻辑已抽取到 RebateSettlementService |
| 287 | 335 | ||
| 288 | @Override | 336 | @Override | ... | ... |
| ... | @@ -4,11 +4,15 @@ import com.apple.erp.dto.*; | ... | @@ -4,11 +4,15 @@ import com.apple.erp.dto.*; |
| 4 | import com.apple.erp.entity.InvoiceItem; | 4 | import com.apple.erp.entity.InvoiceItem; |
| 5 | import com.apple.erp.entity.OrderMain; | 5 | import com.apple.erp.entity.OrderMain; |
| 6 | import com.apple.erp.entity.DeliveryMain; | 6 | import com.apple.erp.entity.DeliveryMain; |
| 7 | +import com.apple.erp.entity.OrderItem; | ||
| 8 | +import com.apple.erp.entity.DeliveryItem; | ||
| 7 | // rebate settlement handled by RebateSettlementService | 9 | // rebate settlement handled by RebateSettlementService |
| 8 | import com.apple.erp.service.RebateSettlementService; | 10 | import com.apple.erp.service.RebateSettlementService; |
| 9 | import com.apple.erp.mapper.InvoiceItemMapper; | 11 | import com.apple.erp.mapper.InvoiceItemMapper; |
| 10 | import com.apple.erp.mapper.OrderMainMapper; | 12 | import com.apple.erp.mapper.OrderMainMapper; |
| 11 | import com.apple.erp.mapper.DeliveryMainMapper; | 13 | import com.apple.erp.mapper.DeliveryMainMapper; |
| 14 | +import com.apple.erp.mapper.OrderItemMapper; | ||
| 15 | +import com.apple.erp.mapper.DeliveryItemMapper; | ||
| 12 | // removed unused mapper imports after delegating settlement logic | 16 | // removed unused mapper imports after delegating settlement logic |
| 13 | import com.apple.erp.util.TimingValidationUtil; | 17 | import com.apple.erp.util.TimingValidationUtil; |
| 14 | import com.apple.erp.exception.InvoiceValidationException; | 18 | import com.apple.erp.exception.InvoiceValidationException; |
| ... | @@ -56,6 +60,12 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi | ... | @@ -56,6 +60,12 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi |
| 56 | @Autowired | 60 | @Autowired |
| 57 | private DeliveryMainMapper deliveryMainMapper; | 61 | private DeliveryMainMapper deliveryMainMapper; |
| 58 | 62 | ||
| 63 | + @Autowired | ||
| 64 | + private OrderItemMapper orderItemMapper; | ||
| 65 | + | ||
| 66 | + @Autowired | ||
| 67 | + private DeliveryItemMapper deliveryItemMapper; | ||
| 68 | + | ||
| 59 | // rebate settlement is delegated; no local mapper usage required | 69 | // rebate settlement is delegated; no local mapper usage required |
| 60 | 70 | ||
| 61 | @Autowired | 71 | @Autowired |
| ... | @@ -134,13 +144,23 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi | ... | @@ -134,13 +144,23 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi |
| 134 | throw new IllegalArgumentException("发票编号已存在"); | 144 | throw new IllegalArgumentException("发票编号已存在"); |
| 135 | } | 145 | } |
| 136 | 146 | ||
| 137 | - // 验证关联的订单是否存在且经销商一致 | 147 | + // 关联必填 |
| 138 | - validateOrderConsistency(addReq.getOrderNo(), addReq.getDealerCode()); | 148 | + if (!StringUtils.hasText(addReq.getOrderNo())) { |
| 149 | + throw new IllegalArgumentException("关联订单编号不能为空"); | ||
| 150 | + } | ||
| 151 | + if (!StringUtils.hasText(addReq.getDeliveryNo())) { | ||
| 152 | + throw new IllegalArgumentException("关联出库单编号不能为空"); | ||
| 153 | + } | ||
| 139 | 154 | ||
| 140 | - // 验证关联的出库单是否存在且经销商一致(如果提供了出库单号) | 155 | + // 基础一致性 |
| 141 | - if (StringUtils.hasText(addReq.getDeliveryNo())) { | 156 | + validateOrderConsistency(addReq.getOrderNo(), addReq.getDealerCode()); |
| 142 | validateDeliveryConsistency(addReq.getDeliveryNo(), addReq.getDealerCode()); | 157 | validateDeliveryConsistency(addReq.getDeliveryNo(), addReq.getDealerCode()); |
| 143 | - } | 158 | + |
| 159 | + // 收集发票明细产品编码并进行双重“至少一项匹配”校验 | ||
| 160 | + List<String> invoiceProductCodes = (addReq.getInvoiceItems() == null ? java.util.Collections.emptyList() | ||
| 161 | + : addReq.getInvoiceItems().stream().map(InvoiceItemAddReq::getProductCode).collect(Collectors.toList())); | ||
| 162 | + validateAtLeastOneItemMatchesOrder(addReq.getOrderNo(), invoiceProductCodes); | ||
| 163 | + validateAtLeastOneItemMatchesDelivery(addReq.getDeliveryNo(), invoiceProductCodes); | ||
| 144 | 164 | ||
| 145 | boolean isValid = true; | 165 | boolean isValid = true; |
| 146 | // 时序逻辑验证:开票时间不得早于出库时间 | 166 | // 时序逻辑验证:开票时间不得早于出库时间 |
| ... | @@ -206,13 +226,20 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi | ... | @@ -206,13 +226,20 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi |
| 206 | throw new IllegalArgumentException("发票编号已存在"); | 226 | throw new IllegalArgumentException("发票编号已存在"); |
| 207 | } | 227 | } |
| 208 | 228 | ||
| 209 | - // 验证关联的订单是否存在且经销商一致 | 229 | + if (!StringUtils.hasText(updateReq.getOrderNo())) { |
| 210 | - validateOrderConsistency(updateReq.getOrderNo(), updateReq.getDealerCode()); | 230 | + throw new IllegalArgumentException("关联订单编号不能为空"); |
| 231 | + } | ||
| 232 | + if (!StringUtils.hasText(updateReq.getDeliveryNo())) { | ||
| 233 | + throw new IllegalArgumentException("关联出库单编号不能为空"); | ||
| 234 | + } | ||
| 211 | 235 | ||
| 212 | - // 验证关联的出库单是否存在且经销商一致(如果提供了出库单号) | 236 | + validateOrderConsistency(updateReq.getOrderNo(), updateReq.getDealerCode()); |
| 213 | - if (StringUtils.hasText(updateReq.getDeliveryNo())) { | ||
| 214 | validateDeliveryConsistency(updateReq.getDeliveryNo(), updateReq.getDealerCode()); | 237 | validateDeliveryConsistency(updateReq.getDeliveryNo(), updateReq.getDealerCode()); |
| 215 | - } | 238 | + |
| 239 | + List<String> invoiceProductCodes = (updateReq.getInvoiceItems() == null ? java.util.Collections.emptyList() | ||
| 240 | + : updateReq.getInvoiceItems().stream().map(InvoiceItemUpdateReq::getProductCode).collect(Collectors.toList())); | ||
| 241 | + validateAtLeastOneItemMatchesOrder(updateReq.getOrderNo(), invoiceProductCodes); | ||
| 242 | + validateAtLeastOneItemMatchesDelivery(updateReq.getDeliveryNo(), invoiceProductCodes); | ||
| 216 | 243 | ||
| 217 | boolean isValid = true; | 244 | boolean isValid = true; |
| 218 | // 时序逻辑验证:开票时间不得早于出库时间 | 245 | // 时序逻辑验证:开票时间不得早于出库时间 |
| ... | @@ -292,6 +319,52 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi | ... | @@ -292,6 +319,52 @@ public class InvoiceMainServiceImpl extends ServiceImpl<InvoiceMainMapper, Invoi |
| 292 | } | 319 | } |
| 293 | } | 320 | } |
| 294 | 321 | ||
| 322 | + /** | ||
| 323 | + * 校验发票明细至少包含一项与关联订单对应的产品(按产品编码)。 | ||
| 324 | + */ | ||
| 325 | + private void validateAtLeastOneItemMatchesOrder(String orderNo, List<String> invoiceProductCodes) { | ||
| 326 | + if (invoiceProductCodes == null || invoiceProductCodes.isEmpty()) { | ||
| 327 | + throw new IllegalArgumentException("发票明细必须至少包含一项与关联订单对应的产品明细,请检查后重新提交"); | ||
| 328 | + } | ||
| 329 | + LambdaQueryWrapper<OrderItem> orderItemWrapper = Wrappers.lambdaQuery(OrderItem.class) | ||
| 330 | + .eq(OrderItem::getOrderNo, orderNo) | ||
| 331 | + .eq(OrderItem::getDelFlag, "0"); | ||
| 332 | + List<OrderItem> orderItems = orderItemMapper.selectList(orderItemWrapper); | ||
| 333 | + if (orderItems == null || orderItems.isEmpty()) { | ||
| 334 | + throw new IllegalArgumentException("发票明细必须至少包含一项与关联订单对应的产品明细,请检查后重新提交"); | ||
| 335 | + } | ||
| 336 | + boolean hasAnyMatch = orderItems.stream() | ||
| 337 | + .map(OrderItem::getProductCode) | ||
| 338 | + .filter(code -> code != null && !code.isEmpty()) | ||
| 339 | + .anyMatch(invoiceProductCodes::contains); | ||
| 340 | + if (!hasAnyMatch) { | ||
| 341 | + throw new IllegalArgumentException("发票明细必须至少包含一项与关联订单对应的产品明细,请检查后重新提交"); | ||
| 342 | + } | ||
| 343 | + } | ||
| 344 | + | ||
| 345 | + /** | ||
| 346 | + * 校验发票明细至少包含一项与关联出库单对应的产品(按产品编码)。 | ||
| 347 | + */ | ||
| 348 | + private void validateAtLeastOneItemMatchesDelivery(String deliveryNo, List<String> invoiceProductCodes) { | ||
| 349 | + if (invoiceProductCodes == null || invoiceProductCodes.isEmpty()) { | ||
| 350 | + throw new IllegalArgumentException("发票明细必须至少包含一项与关联出库单对应的产品明细,请检查后重新提交"); | ||
| 351 | + } | ||
| 352 | + LambdaQueryWrapper<DeliveryItem> deliveryItemWrapper = Wrappers.lambdaQuery(DeliveryItem.class) | ||
| 353 | + .eq(DeliveryItem::getDeliveryNo, deliveryNo) | ||
| 354 | + .eq(DeliveryItem::getDelFlag, "0"); | ||
| 355 | + List<DeliveryItem> deliveryItems = deliveryItemMapper.selectList(deliveryItemWrapper); | ||
| 356 | + if (deliveryItems == null || deliveryItems.isEmpty()) { | ||
| 357 | + throw new IllegalArgumentException("发票明细必须至少包含一项与关联出库单对应的产品明细,请检查后重新提交"); | ||
| 358 | + } | ||
| 359 | + boolean hasAnyMatch = deliveryItems.stream() | ||
| 360 | + .map(DeliveryItem::getProductCode) | ||
| 361 | + .filter(code -> code != null && !code.isEmpty()) | ||
| 362 | + .anyMatch(invoiceProductCodes::contains); | ||
| 363 | + if (!hasAnyMatch) { | ||
| 364 | + throw new IllegalArgumentException("发票明细必须至少包含一项与关联出库单对应的产品明细,请检查后重新提交"); | ||
| 365 | + } | ||
| 366 | + } | ||
| 367 | + | ||
| 295 | @Override | 368 | @Override |
| 296 | @Transactional | 369 | @Transactional |
| 297 | public boolean deleteInvoice(Long invoiceId) { | 370 | public boolean deleteInvoice(Long invoiceId) { | ... | ... |
| ... | @@ -1079,7 +1079,23 @@ const handleSubmitAdd = async () => { | ... | @@ -1079,7 +1079,23 @@ const handleSubmitAdd = async () => { |
| 1079 | fetchDeliveries() // 刷新列表 | 1079 | fetchDeliveries() // 刷新列表 |
| 1080 | } catch (error) { | 1080 | } catch (error) { |
| 1081 | console.error('新增出库失败:', error) | 1081 | console.error('新增出库失败:', error) |
| 1082 | - showMessage('新增出库失败, 请重试', 'error') | 1082 | + // 优先展示后端返回的具体错误信息 |
| 1083 | + const anyError: any = error as any | ||
| 1084 | + let errorMessage = '新增出库失败, 请重试' | ||
| 1085 | + if (anyError && anyError.response && anyError.response.data) { | ||
| 1086 | + const errorData = anyError.response.data | ||
| 1087 | + if (typeof errorData.message === 'string' && errorData.message.trim().length > 0) { | ||
| 1088 | + errorMessage = errorData.message | ||
| 1089 | + } | ||
| 1090 | + // 如果有字段级校验错误,拼接展示 | ||
| 1091 | + if (errorData.data && typeof errorData.data === 'object') { | ||
| 1092 | + const fieldErrors = Object.values(errorData.data).filter((msg: any) => typeof msg === 'string') as string[] | ||
| 1093 | + if (fieldErrors.length > 0) { | ||
| 1094 | + errorMessage = fieldErrors.join('; ') | ||
| 1095 | + } | ||
| 1096 | + } | ||
| 1097 | + } | ||
| 1098 | + showMessage(errorMessage, 'error') | ||
| 1083 | } | 1099 | } |
| 1084 | } | 1100 | } |
| 1085 | 1101 | ||
| ... | @@ -1117,7 +1133,23 @@ const handleSubmitEdit = async () => { | ... | @@ -1117,7 +1133,23 @@ const handleSubmitEdit = async () => { |
| 1117 | fetchDeliveries() // 刷新列表 | 1133 | fetchDeliveries() // 刷新列表 |
| 1118 | } catch (error) { | 1134 | } catch (error) { |
| 1119 | console.error('编辑出库失败:', error) | 1135 | console.error('编辑出库失败:', error) |
| 1120 | - showMessage('编辑出库失败, 请重试', 'error') | 1136 | + // 优先展示后端返回的具体错误信息 |
| 1137 | + const anyError: any = error as any | ||
| 1138 | + let errorMessage = '编辑出库失败, 请重试' | ||
| 1139 | + if (anyError && anyError.response && anyError.response.data) { | ||
| 1140 | + const errorData = anyError.response.data | ||
| 1141 | + if (typeof errorData.message === 'string' && errorData.message.trim().length > 0) { | ||
| 1142 | + errorMessage = errorData.message | ||
| 1143 | + } | ||
| 1144 | + // 如果有字段级校验错误,拼接展示 | ||
| 1145 | + if (errorData.data && typeof errorData.data === 'object') { | ||
| 1146 | + const fieldErrors = Object.values(errorData.data).filter((msg: any) => typeof msg === 'string') as string[] | ||
| 1147 | + if (fieldErrors.length > 0) { | ||
| 1148 | + errorMessage = fieldErrors.join('; ') | ||
| 1149 | + } | ||
| 1150 | + } | ||
| 1151 | + } | ||
| 1152 | + showMessage(errorMessage, 'error') | ||
| 1121 | } | 1153 | } |
| 1122 | } | 1154 | } |
| 1123 | 1155 | ... | ... |
| ... | @@ -991,7 +991,23 @@ const handleSubmit = async () => { | ... | @@ -991,7 +991,23 @@ const handleSubmit = async () => { |
| 991 | fetchOrders() | 991 | fetchOrders() |
| 992 | } catch (error) { | 992 | } catch (error) { |
| 993 | console.error('保存订单失败:', error) | 993 | console.error('保存订单失败:', error) |
| 994 | - showMessage('保存订单失败, 请重试', 'error') | 994 | + // 优先展示后端返回的具体错误信息 |
| 995 | + const anyError: any = error as any | ||
| 996 | + let errorMessage = '保存订单失败, 请重试' | ||
| 997 | + if (anyError && anyError.response && anyError.response.data) { | ||
| 998 | + const errorData = anyError.response.data | ||
| 999 | + if (typeof errorData.message === 'string' && errorData.message.trim().length > 0) { | ||
| 1000 | + errorMessage = errorData.message | ||
| 1001 | + } | ||
| 1002 | + // 如果有字段级校验错误,拼接展示 | ||
| 1003 | + if (errorData.data && typeof errorData.data === 'object') { | ||
| 1004 | + const fieldErrors = Object.values(errorData.data).filter((msg: any) => typeof msg === 'string') as string[] | ||
| 1005 | + if (fieldErrors.length > 0) { | ||
| 1006 | + errorMessage = fieldErrors.join('; ') | ||
| 1007 | + } | ||
| 1008 | + } | ||
| 1009 | + } | ||
| 1010 | + showMessage(errorMessage, 'error') | ||
| 995 | } | 1011 | } |
| 996 | } | 1012 | } |
| 997 | 1013 | ... | ... |
| 1 | { | 1 | { |
| 2 | - "token": "eyJhbGciOiJIUzUxMiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwic3ViIjoiYWRtaW4iLCJpYXQiOjE3NjAzMjY2OTIsImV4cCI6MTc2MDQxMzA5Mn0.g_bbqdvMIIoPws2bOC8AJpFHYo-zSFgybXAEJUF3rvheltchQG1q_jZZSSw2tWLQvZOjzFeJxOROJwKbu5JnIQ", | 2 | + "token": "eyJhbGciOiJIUzUxMiJ9.eyJ1c2VybmFtZSI6ImFkbWluIiwic3ViIjoiYWRtaW4iLCJpYXQiOjE3NjA0Mjc2NTEsImV4cCI6MTc2MDUxNDA1MX0.vtyVtnZ-g6QJB3CnB9yrB23oLxNkL5doezafBfgyT3byTSUOUD162ZEFw6K3aFT8wYkn25TVyTvLVHY9CufIgg", |
| 3 | - "saved_at": 1760326692 | 3 | + "saved_at": 1760427651 |
| 4 | } | 4 | } |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
No preview for this file type
-
Please register or login to post a comment