From c860d1666dd5e2b9c27c2bcb87913f7c48b6b039 Mon Sep 17 00:00:00 2001 From: wuweihua <88888888> Date: Tue, 22 Sep 2026 10:40:13 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E9=99=84=E5=8A=A0=E8=B4=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/price/PriceSetController.java | 18 +++++- .../price/service/IPrcPriceSetService.java | 9 +++ .../service/impl/PrcPriceSetServiceImpl.java | 33 ++++++++++ .../task/PrcPriceSetSaveAsyncRunner.java | 25 ++++++++ bms-front/src/api/price/set.js | 35 +++++++++++ .../set/components/create/PriceEditDrawer.vue | 12 +++- .../set/components/create/StepDetails.vue | 60 +++++++++---------- .../components/create/SurchargeCountCell.vue | 46 ++++++++++---- 8 files changed, 192 insertions(+), 46 deletions(-) diff --git a/bms-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/price/PriceSetController.java b/bms-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/price/PriceSetController.java index 91c3c5ad..80ec7737 100644 --- a/bms-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/price/PriceSetController.java +++ b/bms-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/price/PriceSetController.java @@ -211,15 +211,29 @@ public class PriceSetController extends BaseController } @PreAuthorize("@ss.hasPermi('price:set:edit') or @ss.hasPermi('price:set:forceEdit')") - @Log(title = "套餐明细", businessType = BusinessType.UPDATE) + @Log(title = "\u5957\u9910\u660e\u7ec6", businessType = BusinessType.UPDATE) @PutMapping("/detail") public AjaxResult editDetail(@RequestBody PrcPriceSetDetail detail) { return toAjax(priceSetService.updateDetail(detail)); } + /** + * Async batch write of detail surcharge snapshots. Returns taskId; poll /save/task/{taskId}. + */ @PreAuthorize("@ss.hasPermi('price:set:edit') or @ss.hasPermi('price:set:forceEdit')") - @Log(title = "套餐明细", businessType = BusinessType.DELETE) + @Log(title = "\u5957\u9910\u9644\u52a0\u8d39", businessType = BusinessType.UPDATE) + @PostMapping("/detail/surcharge/async") + public AjaxResult batchSurchargeAsync(@RequestBody List details) + { + String taskId = priceSetService.submitDetailSurchargeAsync(details); + Map payload = new HashMap(); + payload.put("taskId", taskId); + return success(payload); + } + + @PreAuthorize("@ss.hasPermi('price:set:edit') or @ss.hasPermi('price:set:forceEdit')") + @Log(title = "\u5957\u9910\u660e\u7ec6", businessType = BusinessType.DELETE) @DeleteMapping("/detail/{psdIds}") public AjaxResult removeDetail(@PathVariable Long[] psdIds) { diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/IPrcPriceSetService.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/IPrcPriceSetService.java index abbdffc6..28c79545 100644 --- a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/IPrcPriceSetService.java +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/IPrcPriceSetService.java @@ -85,6 +85,15 @@ public interface IPrcPriceSetService /** submit async save, return taskId immediately */ public String submitSaveAsync(PrcPriceSet set); + /** + * Submit async batch write of detail surcharge snapshots (product-level pick can hit many rows). + * @return taskId for polling getSaveTask + */ + public String submitDetailSurchargeAsync(List details); + + /** Sync batch update of detail surcharge snapshots */ + public int batchUpdateDetailSurcharges(List details); + /** poll async save progress */ public PrcPriceSetSaveTask getSaveTask(String taskId); } diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/PrcPriceSetServiceImpl.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/PrcPriceSetServiceImpl.java index 8e5bed6f..b01a8216 100644 --- a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/PrcPriceSetServiceImpl.java +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/PrcPriceSetServiceImpl.java @@ -125,6 +125,39 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService return taskId; } + @Override + public String submitDetailSurchargeAsync(List details) + { + String taskId = IdUtils.fastSimpleUUID(); + saveAsyncRunner.put(taskId, PrcPriceSetSaveTask.STATUS_PENDING, 0, "queued", null, null); + saveAsyncRunner.runSurchargeBatch(taskId, details); + return taskId; + } + + @Override + public int batchUpdateDetailSurcharges(List details) + { + if (details == null || details.isEmpty()) + { + return 0; + } + int rows = 0; + for (PrcPriceSetDetail detail : details) + { + if (detail == null || detail.getPsdId() == null) + { + continue; + } + // Always replace snapshot for this batch API (null would skip in updateDetail) + if (detail.getSurcharges() == null) + { + detail.setSurcharges(new ArrayList()); + } + rows += updateDetail(detail); + } + return rows; + } + @Override public PrcPriceSetSaveTask getSaveTask(String taskId) { diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/task/PrcPriceSetSaveAsyncRunner.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/task/PrcPriceSetSaveAsyncRunner.java index be45df97..6a8dfa8c 100644 --- a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/task/PrcPriceSetSaveAsyncRunner.java +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/task/PrcPriceSetSaveAsyncRunner.java @@ -1,5 +1,6 @@ package com.ruoyi.price.task; +import java.util.List; import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -9,6 +10,7 @@ import org.springframework.stereotype.Component; import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.utils.StringUtils; import com.ruoyi.price.domain.PrcPriceSet; +import com.ruoyi.price.domain.PrcPriceSetDetail; import com.ruoyi.price.domain.PrcPriceSetSaveTask; import com.ruoyi.price.service.IPrcPriceSetService; @@ -51,6 +53,29 @@ public class PrcPriceSetSaveAsyncRunner } } + /** Background write of detail surcharge snapshots for many rows. */ + @Async("threadPoolTaskExecutor") + public void runSurchargeBatch(String taskId, List details) + { + try + { + put(taskId, PrcPriceSetSaveTask.STATUS_RUNNING, 10, "saving surcharges", null, null); + int rows = priceSetService.batchUpdateDetailSurcharges(details); + put(taskId, PrcPriceSetSaveTask.STATUS_SUCCESS, 100, "done", null, null); + log.info("async surcharge batch done, taskId={}, rows={}", taskId, rows); + } + catch (Exception e) + { + log.error("async surcharge batch failed, taskId={}", taskId, e); + String msg = e.getMessage(); + if (StringUtils.isEmpty(msg)) + { + msg = e.getClass().getSimpleName(); + } + put(taskId, PrcPriceSetSaveTask.STATUS_FAIL, 100, "failed", null, msg); + } + } + public void put(String taskId, String status, int percent, String message, Long priceSetId, String error) { PrcPriceSetSaveTask task = new PrcPriceSetSaveTask(); diff --git a/bms-front/src/api/price/set.js b/bms-front/src/api/price/set.js index 80699aee..71dfefe8 100644 --- a/bms-front/src/api/price/set.js +++ b/bms-front/src/api/price/set.js @@ -197,6 +197,41 @@ export function updateSetDetail(data) { }) } +/** + * Submit async batch write of detail surcharge snapshots and poll until done. + * @returns {Promise<{ task: object }>} + */ +export async function updateSetDetailSurchargeAsync(details, onProgress) { + const submitRes = await request({ + url: '/price/set/detail/surcharge/async', + method: 'post', + data: details || [] + }) + const taskId = pickSaveTaskId(submitRes) + if (!taskId) { + throw new Error('missing surcharge taskId') + } + const started = Date.now() + const maxMs = 30 * 60 * 1000 + while (Date.now() - started < maxMs) { + const res = await getPriceSetSaveTask(taskId) + const task = res.data || {} + if (typeof onProgress === 'function') { + onProgress(task) + } + if (task.status === 'SUCCESS') { + return { task } + } + if (task.status === 'FAIL') { + const err = new Error(task.error || task.message || 'surcharge save failed') + err.task = task + throw err + } + await new Promise(resolve => setTimeout(resolve, 800)) + } + throw new Error('surcharge save timeout') +} + export function delSetDetail(psdIds) { return request({ url: '/price/set/detail/' + psdIds, diff --git a/bms-front/src/views/price/set/components/create/PriceEditDrawer.vue b/bms-front/src/views/price/set/components/create/PriceEditDrawer.vue index 9e41dd20..9d6e13f6 100644 --- a/bms-front/src/views/price/set/components/create/PriceEditDrawer.vue +++ b/bms-front/src/views/price/set/components/create/PriceEditDrawer.vue @@ -73,7 +73,7 @@ @@ -97,7 +97,7 @@ const props = defineProps({ productName: { type: String, default: '' }, rows: { type: Array, default: () => [] } }) -const emit = defineEmits(['update:modelValue', 'pick-surcharge', 'row-change']) +const emit = defineEmits(['update:modelValue', 'pick-surcharge', 'row-change', 'surcharge-change']) const { proxy } = getCurrentInstance() @@ -187,6 +187,14 @@ function pickSurcharge(row) { emit('pick-surcharge', row || null) } +function removeSurcharge(row, sc) { + if (!row || !sc || sc.scId == null) return + const scId = String(sc.scId) + const next = (row.surcharges || []).filter(s => s && String(s.scId) !== scId) + row.surcharges = next + emit('surcharge-change', row) +} + function countryKey(row) { return String(row.countryCode || row.countryName || '').toUpperCase() } diff --git a/bms-front/src/views/price/set/components/create/StepDetails.vue b/bms-front/src/views/price/set/components/create/StepDetails.vue index 32fe753f..7e6a89f9 100644 --- a/bms-front/src/views/price/set/components/create/StepDetails.vue +++ b/bms-front/src/views/price/set/components/create/StepDetails.vue @@ -35,11 +35,6 @@ --> - - -