From 520fc32a4e2e5eef4b6310185cddc8a011638c25 Mon Sep 17 00:00:00 2001 From: wuweihua <88888888> Date: Tue, 8 Sep 2026 11:55:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=A7=E5=93=81=E5=88=97=E8=A1=A8=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=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/SurchargeController.java | 38 ++++ .../com/ruoyi/price/domain/BmsProduct.java | 1 + .../ruoyi/price/domain/PrcSurchargeRel.java | 44 ++++ .../price/mapper/PrcSurchargeRelMapper.java | 24 ++ .../service/IPrcSurchargeRelService.java | 24 ++ .../service/impl/BmsProductServiceImpl.java | 5 + .../impl/PrcSurchargeRelServiceImpl.java | 79 +++++++ .../mapper/price/BmsProductMapper.xml | 4 +- .../mapper/price/PrcSurchargeRelMapper.xml | 84 +++++++ bms-back/sql/price/surcharge_rel.sql | 39 ++++ bms-front/src/api/price/surcharge.js | 25 +++ .../src/views/price/basic/product/index.vue | 205 +++++++++++++++++- 12 files changed, 569 insertions(+), 3 deletions(-) create mode 100644 bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/PrcSurchargeRel.java create mode 100644 bms-back/ruoyi-system/src/main/java/com/ruoyi/price/mapper/PrcSurchargeRelMapper.java create mode 100644 bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/IPrcSurchargeRelService.java create mode 100644 bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/PrcSurchargeRelServiceImpl.java create mode 100644 bms-back/ruoyi-system/src/main/resources/mapper/price/PrcSurchargeRelMapper.xml create mode 100644 bms-back/sql/price/surcharge_rel.sql diff --git a/bms-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/price/SurchargeController.java b/bms-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/price/SurchargeController.java index 02c123ae..6f57c47b 100644 --- a/bms-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/price/SurchargeController.java +++ b/bms-back/ruoyi-admin/src/main/java/com/ruoyi/web/controller/price/SurchargeController.java @@ -18,6 +18,8 @@ import com.ruoyi.common.core.domain.AjaxResult; import com.ruoyi.common.core.page.TableDataInfo; import com.ruoyi.common.enums.BusinessType; import com.ruoyi.price.domain.PrcSurcharge; +import com.ruoyi.price.domain.PrcSurchargeRel; +import com.ruoyi.price.service.IPrcSurchargeRelService; import com.ruoyi.price.service.IPrcSurchargeService; /** @@ -32,6 +34,9 @@ public class SurchargeController extends BaseController @Autowired private IPrcSurchargeService surchargeService; + @Autowired + private IPrcSurchargeRelService surchargeRelService; + @PreAuthorize("@ss.hasPermi('price:surcharge:list')") @GetMapping("/list") public TableDataInfo list(PrcSurcharge surcharge) @@ -48,6 +53,39 @@ public class SurchargeController extends BaseController return success(surchargeService.selectPrcSurchargeById(scId)); } + /** + * 查询指定产品已关联的附加费(非分页,供产品列表抽屉使用) + */ + @PreAuthorize("@ss.hasPermi('price:surcharge:query')") + @GetMapping("/byProduct/{productCode}") + public AjaxResult listByProduct(@PathVariable String productCode) + { + return success(surchargeRelService.selectRelByProductCode(productCode)); + } + + /** + * 绑定附加费到产品/明细(body: scId, productId, productCode, detailId;detailId 空=产品级) + */ + @PreAuthorize("@ss.hasPermi('price:surcharge:add')") + @Log(title = "附加费关联", businessType = BusinessType.INSERT) + @PostMapping("/rel") + public AjaxResult addRel(@RequestBody PrcSurchargeRel rel) + { + rel.setCreateBy(getUsername()); + return toAjax(surchargeRelService.insertPrcSurchargeRel(rel)); + } + + /** + * 解绑(删除关联记录,不删除附加费本身) + */ + @PreAuthorize("@ss.hasPermi('price:surcharge:remove')") + @Log(title = "附加费关联", businessType = BusinessType.DELETE) + @DeleteMapping("/rel/{relIds}") + public AjaxResult removeRel(@PathVariable Long[] relIds) + { + return toAjax(surchargeRelService.deletePrcSurchargeRelByIds(relIds)); + } + @PreAuthorize("@ss.hasPermi('price:surcharge:add')") @Log(title = "附加费配置", businessType = BusinessType.INSERT) @PostMapping diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/BmsProduct.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/BmsProduct.java index f5abb29f..f9811633 100644 --- a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/BmsProduct.java +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/BmsProduct.java @@ -30,6 +30,7 @@ public class BmsProduct extends BaseEntity private String sourceSheet; private Long tmsId; private Integer countryCount; + private Integer surchargeCount; private List countries; /** * 查询用:ACTIVE已生效 / PENDING待生效 / EXPIRED已失效 diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/PrcSurchargeRel.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/PrcSurchargeRel.java new file mode 100644 index 00000000..533dd255 --- /dev/null +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/domain/PrcSurchargeRel.java @@ -0,0 +1,44 @@ +package com.ruoyi.price.domain; + +import java.math.BigDecimal; +import com.ruoyi.common.core.domain.BaseEntity; +import lombok.Data; +import lombok.EqualsAndHashCode; + +/** + * 附加费与产品/明细关联 prc_surcharge_rel + * 同时携带附加费展示字段(JOIN prc_surcharge)与明细展示字段(LEFT JOIN bms_product_country), + * 便于产品列表抽屉直接渲染。 + * + * 语义: + * detail_id 为空 = 产品级附加费(作用于该产品全部明细) + * detail_id 有值 = 明细级附加费(作用于该产品某个 国家×重量段 明细) + */ +@Data +@EqualsAndHashCode(callSuper = true) +public class PrcSurchargeRel extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + private Long relId; + private Long scId; + private Long productId; + private String productCode; + private Long detailId; + + /** 附加费冗余展示字段 */ + private String scName; + private String feeType; + private String chargeType; + private BigDecimal chargeValue; + private String currency; + private String roundMode; + private String ssCode; + private String countryCode; + private String scNote; + + /** 明细展示字段 */ + private String countryName; + private BigDecimal weightMin; + private BigDecimal weightMax; +} diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/mapper/PrcSurchargeRelMapper.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/mapper/PrcSurchargeRelMapper.java new file mode 100644 index 00000000..529ba8c9 --- /dev/null +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/mapper/PrcSurchargeRelMapper.java @@ -0,0 +1,24 @@ +package com.ruoyi.price.mapper; + +import java.util.List; +import com.ruoyi.price.domain.PrcSurchargeRel; + +/** + * 附加费与产品/明细关联 数据层 + * + * @author ruoyi + */ +public interface PrcSurchargeRelMapper +{ + /** + * 查询关联列表(JOIN 附加费 + 明细),支持按 productCode / scId 过滤 + */ + public List selectPrcSurchargeRelList(PrcSurchargeRel rel); + + public int insertPrcSurchargeRel(PrcSurchargeRel rel); + + public int deletePrcSurchargeRelByIds(Long[] relIds); + + /** 删除产品时清理其关联 */ + public int deleteRelByProductCodes(String[] productCodes); +} diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/IPrcSurchargeRelService.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/IPrcSurchargeRelService.java new file mode 100644 index 00000000..f889184d --- /dev/null +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/IPrcSurchargeRelService.java @@ -0,0 +1,24 @@ +package com.ruoyi.price.service; + +import java.util.List; +import com.ruoyi.price.domain.PrcSurchargeRel; + +/** + * 附加费与产品/明细关联 服务层 + * + * @author ruoyi + */ +public interface IPrcSurchargeRelService +{ + /** 查询某产品已关联的附加费(含附加费与明细展示字段) */ + public List selectRelByProductCode(String productCode); + + public List selectPrcSurchargeRelList(PrcSurchargeRel rel); + + public int insertPrcSurchargeRel(PrcSurchargeRel rel); + + public int deletePrcSurchargeRelByIds(Long[] relIds); + + /** 删除产品时清理其关联 */ + public int deleteRelByProductCodes(String[] productCodes); +} diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/BmsProductServiceImpl.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/BmsProductServiceImpl.java index af3334ed..c921643d 100644 --- a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/BmsProductServiceImpl.java +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/BmsProductServiceImpl.java @@ -32,6 +32,7 @@ import com.ruoyi.price.domain.BmsProductCountry; import com.ruoyi.price.mapper.BmsProductCountryMapper; import com.ruoyi.price.mapper.BmsProductMapper; import com.ruoyi.price.service.IBmsProductService; +import com.ruoyi.price.service.IPrcSurchargeRelService; import com.ruoyi.system.domain.BmsRegion; import com.ruoyi.system.mapper.BmsRegionMapper; @@ -64,6 +65,9 @@ public class BmsProductServiceImpl implements IBmsProductService @Autowired private BmsRegionMapper regionMapper; + @Autowired + private IPrcSurchargeRelService surchargeRelService; + @Override public BmsProduct selectBmsProductById(Long productId) { @@ -116,6 +120,7 @@ public class BmsProductServiceImpl implements IBmsProductService if (!codes.isEmpty()) { countryMapper.deleteByProductCodes(codes.toArray(new String[0])); + surchargeRelService.deleteRelByProductCodes(codes.toArray(new String[0])); } return productMapper.deleteBmsProductByIds(productIds); } diff --git a/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/PrcSurchargeRelServiceImpl.java b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/PrcSurchargeRelServiceImpl.java new file mode 100644 index 00000000..94c2c4fa --- /dev/null +++ b/bms-back/ruoyi-system/src/main/java/com/ruoyi/price/service/impl/PrcSurchargeRelServiceImpl.java @@ -0,0 +1,79 @@ +package com.ruoyi.price.service.impl; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.price.domain.PrcSurchargeRel; +import com.ruoyi.price.mapper.PrcSurchargeRelMapper; +import com.ruoyi.price.service.IPrcSurchargeRelService; + +/** + * 附加费与产品/明细关联 服务层实现 + * + * @author ruoyi + */ +@Service +public class PrcSurchargeRelServiceImpl implements IPrcSurchargeRelService +{ + @Autowired + private PrcSurchargeRelMapper relMapper; + + @Override + public List selectRelByProductCode(String productCode) + { + PrcSurchargeRel query = new PrcSurchargeRel(); + query.setProductCode(productCode); + return relMapper.selectPrcSurchargeRelList(query); + } + + @Override + public List selectPrcSurchargeRelList(PrcSurchargeRel rel) + { + return relMapper.selectPrcSurchargeRelList(rel); + } + + @Override + public int insertPrcSurchargeRel(PrcSurchargeRel rel) + { + validate(rel); + return relMapper.insertPrcSurchargeRel(rel); + } + + @Override + public int deletePrcSurchargeRelByIds(Long[] relIds) + { + if (relIds == null || relIds.length == 0) + { + return 0; + } + return relMapper.deletePrcSurchargeRelByIds(relIds); + } + + @Override + public int deleteRelByProductCodes(String[] productCodes) + { + if (productCodes == null || productCodes.length == 0) + { + return 0; + } + return relMapper.deleteRelByProductCodes(productCodes); + } + + private void validate(PrcSurchargeRel rel) + { + if (rel.getScId() == null) + { + throw new ServiceException("附加费ID不能为空"); + } + if (rel.getProductId() == null) + { + throw new ServiceException("产品ID不能为空"); + } + if (StringUtils.isEmpty(rel.getProductCode())) + { + throw new ServiceException("产品代码不能为空"); + } + } +} diff --git a/bms-back/ruoyi-system/src/main/resources/mapper/price/BmsProductMapper.xml b/bms-back/ruoyi-system/src/main/resources/mapper/price/BmsProductMapper.xml index 0e6b330c..788e7ead 100644 --- a/bms-back/ruoyi-system/src/main/resources/mapper/price/BmsProductMapper.xml +++ b/bms-back/ruoyi-system/src/main/resources/mapper/price/BmsProductMapper.xml @@ -23,13 +23,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" + select p.product_id, p.product_code, p.product_name, p.service_level, p.cargo_attr, p.dest_region, p.update_note, p.tax_mode, p.effective_date, p.status, p.source_sheet, p.remark, p.tms_id, p.created_by, p.created_at, p.updated_by, p.updated_at, - (select count(distinct c.country_name) from bms_product_country c where c.product_code = p.product_code) as country_count + (select count(distinct c.country_name) from bms_product_country c where c.product_code = p.product_code) as country_count, + (select count(*) from prc_surcharge_rel r where r.product_id = p.product_id) as surcharge_count from bms_product p diff --git a/bms-back/ruoyi-system/src/main/resources/mapper/price/PrcSurchargeRelMapper.xml b/bms-back/ruoyi-system/src/main/resources/mapper/price/PrcSurchargeRelMapper.xml new file mode 100644 index 00000000..f8aeee71 --- /dev/null +++ b/bms-back/ruoyi-system/src/main/resources/mapper/price/PrcSurchargeRelMapper.xml @@ -0,0 +1,84 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select r.rel_id, r.sc_id, r.product_id, r.product_code, r.detail_id, + r.created_by, r.created_at, r.updated_by, r.updated_at, + s.sc_name, s.fee_type, s.charge_type, s.charge_value, s.currency, + s.round_mode, s.ss_code, s.country_code, s.sc_note, + c.country_name, c.weight_min, c.weight_max + from prc_surcharge_rel r + join prc_surcharge s on s.sc_id = r.sc_id + left join bms_product_country c on c.detail_id = r.detail_id + + + + + + insert into prc_surcharge_rel ( + sc_id, product_id, product_code, detail_id, + created_by, + created_at + ) values ( + #{scId}, #{productId}, #{productCode}, #{detailId}, + #{createBy}, + sysdate() + ) + + + + delete from prc_surcharge_rel where rel_id in + + #{relId} + + + + + delete from prc_surcharge_rel where product_code in + + #{code} + + + + diff --git a/bms-back/sql/price/surcharge_rel.sql b/bms-back/sql/price/surcharge_rel.sql new file mode 100644 index 00000000..8a9010aa --- /dev/null +++ b/bms-back/sql/price/surcharge_rel.sql @@ -0,0 +1,39 @@ +-- 附加费关联表:维护 prc_surcharge 与 bms_product(产品表) / bms_product_country(明细表) 的关系 +-- 语义: +-- product_id 产品主键(外键关联 bms_product.product_id,与 product_code 一一对应) +-- product_code 产品对接代码(便于与明细表 bms_product_country 及前端交互) +-- detail_id 为空 = 产品级附加费(作用于该产品全部明细) +-- 有值 = 明细级附加费(作用于该产品某个 国家×重量段 明细) +-- 一个附加费可关联多个产品/明细;一个产品/明细可挂多个附加费(多对多) +-- 执行后即可在「产品列表」按产品/明细维护附加费关联 +SET NAMES utf8mb4; + +CREATE TABLE IF NOT EXISTS prc_surcharge_rel ( + rel_id BIGINT(20) NOT NULL AUTO_INCREMENT COMMENT '关联ID', + sc_id BIGINT(20) NOT NULL COMMENT '附加费配置ID prc_surcharge.sc_id', + product_id BIGINT(20) NOT NULL COMMENT '产品ID bms_product.product_id', + product_code VARCHAR(20) NOT NULL COMMENT '产品对接代码 bms_product.product_code', + detail_id BIGINT(20) DEFAULT NULL COMMENT '产品明细ID bms_product_country.detail_id(空=作用于产品全部明细)', + created_by VARCHAR(64) DEFAULT '' COMMENT '创建人', + created_at DATETIME DEFAULT NULL COMMENT '创建时间', + updated_by VARCHAR(64) DEFAULT '' COMMENT '更新人', + updated_at DATETIME DEFAULT NULL COMMENT '更新时间', + PRIMARY KEY (rel_id), + UNIQUE KEY uk_rel_scope (sc_id, product_id, detail_id), + INDEX idx_rel_sc (sc_id), + INDEX idx_rel_product (product_id), + INDEX idx_rel_product_code (product_code), + INDEX idx_rel_detail (detail_id), + CONSTRAINT fk_rel_sc FOREIGN KEY (sc_id) REFERENCES prc_surcharge (sc_id) ON DELETE CASCADE, + CONSTRAINT fk_rel_product FOREIGN KEY (product_id) REFERENCES bms_product (product_id) ON DELETE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci COMMENT='附加费与产品/明细关联表'; + +-- 若已按旧版(无 product_id)建表且已有数据,升级步骤: +-- ALTER TABLE prc_surcharge_rel ADD COLUMN product_id BIGINT(20) DEFAULT NULL COMMENT '产品ID' AFTER sc_id; +-- UPDATE prc_surcharge_rel r JOIN bms_product p ON p.product_code = r.product_code SET r.product_id = p.product_id; +-- ALTER TABLE prc_surcharge_rel MODIFY COLUMN product_id BIGINT(20) NOT NULL COMMENT '产品ID bms_product.product_id'; +-- ALTER TABLE prc_surcharge_rel ADD INDEX idx_rel_product (product_id); +-- ALTER TABLE prc_surcharge_rel ADD CONSTRAINT fk_rel_product FOREIGN KEY (product_id) REFERENCES bms_product (product_id) ON DELETE CASCADE; + +-- 若上一版方案(prc_surcharge 加 product_code 字段)已执行,可手动回退(MySQL 5.7 不支持 DROP COLUMN IF EXISTS): +-- ALTER TABLE prc_surcharge DROP COLUMN product_code; diff --git a/bms-front/src/api/price/surcharge.js b/bms-front/src/api/price/surcharge.js index a9412756..d8ccdca0 100644 --- a/bms-front/src/api/price/surcharge.js +++ b/bms-front/src/api/price/surcharge.js @@ -19,6 +19,31 @@ export function getSurcharge(scId) { }) } +/** 查询指定产品的附加费关联(非分页,含附加费与明细展示字段) */ +export function listSurchargeByProduct(productCode) { + return request({ + url: '/price/surcharge/byProduct/' + productCode, + method: 'get' + }) +} + +/** 绑定附加费到产品/明细(scId + productCode + detailId) */ +export function addSurchargeRel(data) { + return request({ + url: '/price/surcharge/rel', + method: 'post', + data: data + }) +} + +/** 解绑附加费关联 */ +export function delSurchargeRel(relIds) { + return request({ + url: '/price/surcharge/rel/' + relIds, + method: 'delete' + }) +} + /** 新增附加费配置 */ export function addSurcharge(data) { return request({ diff --git a/bms-front/src/views/price/basic/product/index.vue b/bms-front/src/views/price/basic/product/index.vue index 26608b3d..17a40002 100644 --- a/bms-front/src/views/price/basic/product/index.vue +++ b/bms-front/src/views/price/basic/product/index.vue @@ -40,6 +40,7 @@ @@ -149,6 +150,75 @@ + +
+ 新增关联 +
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + 产品级(全部明细) + 明细级(指定国家×重量段) + + + + + + + + + + + import ExcelImportDialog from '@/components/ExcelImportDialog' import { listProduct, getProduct, addProduct, updateProduct, delProduct, listProductCountries } from '@/api/price/product' +import { listSurchargeByProduct, listSurcharge, addSurchargeRel, delSurchargeRel } from '@/api/price/surcharge' +import { listRegionOptions } from '@/api/data/region' +import { onMounted } from 'vue' const { proxy } = getCurrentInstance() -const { bms_product_effect_status, bms_tax_mode } = useDict('bms_product_effect_status', 'bms_tax_mode') +const { bms_product_effect_status, bms_tax_mode, bms_round_mode, bms_charge_type } = useDict('bms_product_effect_status', 'bms_tax_mode', 'bms_round_mode', 'bms_charge_type') const tableRef = ref() const importRef = ref() const formRef = ref() @@ -176,6 +249,18 @@ const countryTitle = ref('') const countryLoading = ref(false) const countryList = ref([]) const countryKeyword = ref('') + +const surchargeOpen = ref(false) +const surchargeTitle = ref('') +const surchargeLoading = ref(false) +const surchargeList = ref([]) +const currentProduct = ref(null) +const regionOptions = ref([]) + +const surchargePool = ref([]) +const relOpen = ref(false) +const relTitle = ref('') +const relFormRef = ref() const filteredCountryList = computed(() => { const kw = countryKeyword.value.trim().toLowerCase() if (!kw) return countryList.value @@ -194,9 +279,10 @@ const columns = [ { prop: 'taxMode', label: '税模式', width: 90, align: 'center', dict: 'bms_tax_mode' }, { prop: 'effectiveDate', label: '生效日期', width: 120, align: 'center' }, { prop: 'countryCount', label: '国家数', width: 80, align: 'center' }, + { prop: 'surchargeCount', label: '附加费数', width: 90, align: 'center' }, { prop: 'status', label: '状态', width: 90, align: 'center', slot: 'status' }, { prop: 'updateNote', label: '更新内容', minWidth: 160, showOverflowTooltip: true }, - { prop: 'action', label: '操作', width: 240, fixed: 'right', slot: 'action' } + { prop: 'action', label: '操作', width: 300, fixed: 'right', slot: 'action' } ] const searchColumns = [ @@ -343,9 +429,124 @@ function countrySpanMethod({ column, rowIndex }) { while (rowIndex + count < list.length && list[rowIndex + count]?.countryCode === cur) count++ return { rowspan: count, colspan: 1 } } + +// ===== 产品附加费关联 ===== +const relData = reactive({ + relForm: {}, + relRules: { + scId: [{ required: true, message: '请选择附加费', trigger: 'change' }] + } +}) +const { relForm, relRules } = toRefs(relData) + +function openSurcharges(row) { + currentProduct.value = row + surchargeTitle.value = `${row.productCode} · ${row.productName} · 附加费关联` + surchargeOpen.value = true + loadSurcharges() +} + +function loadSurcharges() { + if (!currentProduct.value) return + surchargeLoading.value = true + listSurchargeByProduct(currentProduct.value.productCode).then(res => { + surchargeList.value = res.data || [] + }).finally(() => { + surchargeLoading.value = false + }) +} + +function loadSurchargePool() { + return listSurcharge({ ssCode: 'on', pageNum: 1, pageSize: 1000 }).then(res => { + surchargePool.value = res.rows || [] + }) +} + +function resetRelForm() { + relForm.value = { + scId: undefined, + scope: 'PRODUCT', + detailId: undefined + } + relFormRef.value && relFormRef.value.resetFields() +} + +function handleRelAdd() { + resetRelForm() + relTitle.value = '新增附加费关联' + relOpen.value = true + loadSurchargePool() +} + +function submitRel() { + relFormRef.value.validate(valid => { + if (!valid) return + if (relForm.value.scope === 'DETAIL' && !relForm.value.detailId) { + proxy.$modal.msgError('请选择明细') + return + } + const payload = { + scId: relForm.value.scId, + productId: currentProduct.value ? currentProduct.value.productId : undefined, + productCode: currentProduct.value ? currentProduct.value.productCode : undefined, + detailId: relForm.value.scope === 'DETAIL' ? relForm.value.detailId : null + } + addSurchargeRel(payload).then(() => { + proxy.$modal.msgSuccess('关联成功') + relOpen.value = false + loadSurcharges() + tableRef.value.refresh() + }) + }) +} + +function handleRelDelete(relId) { + proxy.$modal.confirm('是否确认解绑该附加费?').then(() => { + return delSurchargeRel(relId) + }).then(() => { + proxy.$modal.msgSuccess('解绑成功') + loadSurcharges() + tableRef.value.refresh() + }).catch(() => {}) +} + +function detailLabel(d) { + const w = d.weightMin != null && d.weightMax != null ? `${d.weightMin}-${d.weightMax}kg` : '-' + return `${d.countryName || d.countryCode || '-'} · ${w}` +} + +function chargeTypeLabel(val) { + const found = bms_charge_type.value.find(c => c.value === val) + return found ? found.label : (val || '-') +} + +function roundModeLabel(val) { + const found = bms_round_mode.value.find(d => d.value === val) + return found ? found.label : (val || '-') +} + +function formatChargeValue(row) { + if (row.chargeValue == null) return '-' + const v = Number(row.chargeValue) + if (row.chargeType === 'RATE') return (v * 100).toFixed(2) + '%' + return v + ' ' + (row.currency || 'CNY') +} + +function countryLabel(code) { + if (!code) return '全部' + const found = regionOptions.value.find(r => r.countryCode2 === code) + return found ? (found.countryNameCn || found.countryNameEn || code) : code +} + +onMounted(() => { + listRegionOptions().then(res => { + regionOptions.value = res.data || [] + }) +})