Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f82d9c667f | |||
| 7e1041391a |
+33
@@ -208,6 +208,39 @@ public class LabelPackageController extends BaseController
|
||||
return success(payProductService.selectPayProductDetail(productId));
|
||||
}
|
||||
|
||||
/** 查询打单产品已绑定渠道(默认应收 AR) */
|
||||
@PreAuthorize("@ss.hasPermi('price:label:query')")
|
||||
@GetMapping("/product/{productId}/channels")
|
||||
public AjaxResult productChannels(@PathVariable Long productId,
|
||||
@RequestParam(value = "payType", required = false) String payType)
|
||||
{
|
||||
String type = (payType == null || payType.trim().isEmpty()) ? "AR" : payType.trim();
|
||||
return success(payProductService.listProductChannelBinds(productId, type));
|
||||
}
|
||||
|
||||
/** 覆盖保存打单产品渠道绑定,写入 srv_channel_product_map */
|
||||
@PreAuthorize("@ss.hasPermi('price:label:edit')")
|
||||
@Log(title = "打单产品绑定渠道", businessType = BusinessType.UPDATE)
|
||||
@PutMapping("/product/{productId}/channels")
|
||||
public AjaxResult replaceProductChannels(@PathVariable Long productId, @RequestBody Map<String, Object> body)
|
||||
{
|
||||
String payType = body == null || body.get("payType") == null ? "AR" : String.valueOf(body.get("payType")).trim();
|
||||
List<String> channelIds = new ArrayList<String>();
|
||||
Object rawIds = body == null ? null : body.get("channelIds");
|
||||
if (rawIds instanceof List<?>)
|
||||
{
|
||||
for (Object item : (List<?>) rawIds)
|
||||
{
|
||||
if (item != null && !String.valueOf(item).trim().isEmpty())
|
||||
{
|
||||
channelIds.add(String.valueOf(item).trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
String msg = payProductService.replaceProductChannelBinds(productId, payType, channelIds);
|
||||
return AjaxResult.success(msg);
|
||||
}
|
||||
|
||||
@PreAuthorize("@ss.hasPermi('price:label:remove')")
|
||||
@Log(title = "打单套餐移除产品", businessType = BusinessType.DELETE)
|
||||
@DeleteMapping("/{priceSetId}/products/{productIds}")
|
||||
|
||||
@@ -120,6 +120,12 @@ public class PayProduct extends BaseEntity
|
||||
@Excel(name = "附加费数", width = 12)
|
||||
private Integer surchargeCount;
|
||||
|
||||
/** 已绑定渠道展示文案(非表字段,列表回显) */
|
||||
private String boundChannelText;
|
||||
|
||||
/** 已绑定渠道数量(非表字段) */
|
||||
private Integer boundChannelCount;
|
||||
|
||||
@Excel(name = "其他配置数", width = 12)
|
||||
private Integer extraCount;
|
||||
|
||||
|
||||
@@ -84,9 +84,10 @@ public class PrcOrderBill extends BaseEntity
|
||||
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
|
||||
private Date bizDate;
|
||||
private Long tmsId;
|
||||
|
||||
private String matchSource;
|
||||
private String matchMessage;
|
||||
/** 渠道编码(上游 TAB_ORDER.PRODUCT_FLOOR_CODE) */
|
||||
private String productFloorCode;
|
||||
/** 渠道名称(上游 TAB_ORDER.PRODUCT_FLOOR) */
|
||||
private String productFloor;
|
||||
private Long priceSetId;
|
||||
private String priceSetCode;
|
||||
private String priceSetName;
|
||||
|
||||
+4
-2
@@ -43,8 +43,10 @@ public class PrcBillingBillListExportRow implements Serializable
|
||||
private BigDecimal incomeTotal;
|
||||
@Excel(name = "应付总额", scale = 2, width = 14)
|
||||
private BigDecimal payTotal;
|
||||
@Excel(name = "计价来源", width = 16)
|
||||
private String matchSourceLabel;
|
||||
@Excel(name = "渠道编码", width = 16)
|
||||
private String productFloorCode;
|
||||
@Excel(name = "渠道名称", width = 20)
|
||||
private String productFloor;
|
||||
@Excel(name = "订单状态", width = 12)
|
||||
private String orderStatusLabel;
|
||||
@Excel(name = "计费状态", width = 14)
|
||||
|
||||
@@ -34,6 +34,10 @@ public class TmsPriceQuoteResult implements Serializable
|
||||
|
||||
private String productCode;
|
||||
private String productName;
|
||||
/** 渠道编码 */
|
||||
private String productFloorCode;
|
||||
/** 渠道名称 */
|
||||
private String productFloor;
|
||||
private String countryCode;
|
||||
private String countryName;
|
||||
private Long zoneId;
|
||||
|
||||
@@ -10,6 +10,11 @@ public interface ChannelProductMapMapper
|
||||
{
|
||||
ChannelProductMap selectByChannelAndType(@Param("channelId") String channelId, @Param("payType") String payType);
|
||||
|
||||
java.util.List<ChannelProductMap> selectByProductIdAndType(@Param("productId") Long productId,
|
||||
@Param("payType") String payType);
|
||||
|
||||
java.util.List<ChannelProductMap> selectByProductIdsAndType(@Param("productIds") java.util.List<Long> productIds,
|
||||
@Param("payType") String payType);
|
||||
|
||||
int upsert(ChannelProductMap row);
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import com.bms.price.domain.PrcOrderBill;
|
||||
import com.bms.price.domain.PrcOrderBillExt;
|
||||
|
||||
/**
|
||||
@@ -14,6 +15,18 @@ public final class OracleOrderBillExtFiller
|
||||
{
|
||||
private OracleOrderBillExtFiller() {}
|
||||
|
||||
|
||||
/** 从上游 TAB_ORDER 写入 prc_order_bill 渠道编码/名称。 */
|
||||
public static void fillBillChannelFromRow(PrcOrderBill bill, Map<String, Object> row)
|
||||
{
|
||||
if (bill == null || row == null || row.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
bill.setProductFloorCode(str(row, "PRODUCT_FLOOR_CODE"));
|
||||
bill.setProductFloor(str(row, "PRODUCT_FLOOR"));
|
||||
}
|
||||
|
||||
public static void fillFromRow(PrcOrderBillExt ext, Map<String, Object> row)
|
||||
{
|
||||
if (ext == null || row == null || row.isEmpty())
|
||||
|
||||
@@ -61,6 +61,16 @@ public interface IPayProductService
|
||||
/** 批量绑定渠道应收/应付产品;未传的产品不改原绑定 */
|
||||
String batchBindChannel(java.util.List<String> channelIds, Long apProductId, Long arProductId);
|
||||
|
||||
/** 查询产品已绑定的渠道(按收付类型) */
|
||||
java.util.List<com.bms.price.domain.ChannelProductMap> listProductChannelBinds(Long productId, String payType);
|
||||
|
||||
/**
|
||||
* 覆盖保存产品的渠道绑定:勾选渠道写入 srv_channel_product_map,
|
||||
* 取消勾选且当前仍绑该产品的渠道会解绑。
|
||||
*/
|
||||
String replaceProductChannelBinds(Long productId, String payType, java.util.List<String> channelIds);
|
||||
|
||||
|
||||
/**
|
||||
* 打单套餐预览:解析复用应付解析器,但「已存在」只按本套餐 price_set_id 判断,
|
||||
* 不与应付公共模板互相挡导入。
|
||||
|
||||
+143
@@ -1101,9 +1101,104 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
product.setSurchargeCount(term.getSurchargeCount() == null ? product.getSurchargeCount() : term.getSurchargeCount());
|
||||
list.add(product);
|
||||
}
|
||||
fillLabelBoundChannels(list);
|
||||
return list;
|
||||
}
|
||||
|
||||
/** 打单产品列表回填已绑定渠道(收款 AR) */
|
||||
private void fillLabelBoundChannels(List<PayProduct> list)
|
||||
{
|
||||
if (list == null || list.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
java.util.LinkedHashSet<Long> ids = new java.util.LinkedHashSet<Long>();
|
||||
for (PayProduct product : list)
|
||||
{
|
||||
if (product != null && product.getProductId() != null)
|
||||
{
|
||||
ids.add(product.getProductId());
|
||||
}
|
||||
}
|
||||
if (ids.isEmpty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
List<ChannelProductMap> binds = channelProductMapMapper.selectByProductIdsAndType(
|
||||
new ArrayList<Long>(ids), PAY_TYPE_AR);
|
||||
java.util.Map<Long, java.util.List<ChannelProductMap>> byProduct =
|
||||
new java.util.HashMap<Long, java.util.List<ChannelProductMap>>();
|
||||
if (binds != null)
|
||||
{
|
||||
for (ChannelProductMap row : binds)
|
||||
{
|
||||
if (row == null || row.getProductId() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
java.util.List<ChannelProductMap> bucket = byProduct.get(row.getProductId());
|
||||
if (bucket == null)
|
||||
{
|
||||
bucket = new ArrayList<ChannelProductMap>();
|
||||
byProduct.put(row.getProductId(), bucket);
|
||||
}
|
||||
bucket.add(row);
|
||||
}
|
||||
}
|
||||
for (PayProduct product : list)
|
||||
{
|
||||
if (product == null || product.getProductId() == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
java.util.List<ChannelProductMap> bucket = byProduct.get(product.getProductId());
|
||||
if (bucket == null || bucket.isEmpty())
|
||||
{
|
||||
product.setBoundChannelCount(Integer.valueOf(0));
|
||||
product.setBoundChannelText(null);
|
||||
continue;
|
||||
}
|
||||
product.setBoundChannelCount(Integer.valueOf(bucket.size()));
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (ChannelProductMap row : bucket)
|
||||
{
|
||||
if (row == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
String code = row.getChannelCode();
|
||||
String name = row.getChannelName();
|
||||
String label;
|
||||
if (!isBlank(code) && !isBlank(name) && !code.equals(name))
|
||||
{
|
||||
label = code + "/" + name;
|
||||
}
|
||||
else if (!isBlank(code))
|
||||
{
|
||||
label = code;
|
||||
}
|
||||
else if (!isBlank(name))
|
||||
{
|
||||
label = name;
|
||||
}
|
||||
else
|
||||
{
|
||||
label = row.getChannelId();
|
||||
}
|
||||
if (isBlank(label))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (sb.length() > 0)
|
||||
{
|
||||
sb.append("、");
|
||||
}
|
||||
sb.append(label);
|
||||
}
|
||||
product.setBoundChannelText(sb.length() == 0 ? null : sb.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public int removeLabelProducts(Long priceSetId, Long[] productIds)
|
||||
@@ -1701,6 +1796,54 @@ public class PayProductServiceImpl implements IPayProductService
|
||||
return "已为 " + n + " 个渠道绑定产品";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ChannelProductMap> listProductChannelBinds(Long productId, String payType)
|
||||
{
|
||||
Long root = resolveRoot(productId);
|
||||
String type = payTypeOf(payType);
|
||||
List<ChannelProductMap> list = channelProductMapMapper.selectByProductIdAndType(root, type);
|
||||
return list == null ? new ArrayList<ChannelProductMap>() : list;
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public String replaceProductChannelBinds(Long productId, String payType, List<String> channelIds)
|
||||
{
|
||||
Long root = resolveRoot(productId);
|
||||
String type = payTypeOf(payType);
|
||||
java.util.LinkedHashSet<String> selected = new java.util.LinkedHashSet<String>();
|
||||
if (channelIds != null)
|
||||
{
|
||||
for (String channelId : channelIds)
|
||||
{
|
||||
if (!isBlank(channelId))
|
||||
{
|
||||
selected.add(channelId.trim());
|
||||
}
|
||||
}
|
||||
}
|
||||
List<ChannelProductMap> existing = channelProductMapMapper.selectByProductIdAndType(root, type);
|
||||
if (existing != null)
|
||||
{
|
||||
for (ChannelProductMap row : existing)
|
||||
{
|
||||
if (row == null || isBlank(row.getChannelId()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (!selected.contains(row.getChannelId().trim()))
|
||||
{
|
||||
channelProductMapMapper.deleteByChannelAndType(row.getChannelId().trim(), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (String channelId : selected)
|
||||
{
|
||||
bindChannel(channelId, root, type);
|
||||
}
|
||||
return "已绑定 " + selected.size() + " 个渠道";
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindChannel(String channelId, String payType)
|
||||
{
|
||||
|
||||
+6
-7
@@ -2061,9 +2061,6 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
bill.setWeight(weight);
|
||||
bill.setBizDate(bizDate);
|
||||
bill.setTmsId(request.getTmsId() == null ? null : Long.valueOf(request.getTmsId()));
|
||||
// 不在订单账单上持久化 match_source / match_message。
|
||||
bill.setMatchSource(null);
|
||||
bill.setMatchMessage(null);
|
||||
bill.setPriceSetId(result.getPriceSetId());
|
||||
bill.setPriceSetCode(result.getPriceSetCode());
|
||||
bill.setPriceSetName(result.getPriceSetName());
|
||||
@@ -2614,8 +2611,6 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
r.setCustomerCode(bill.getCustomerCode());
|
||||
fillResultOrder(r, bill);
|
||||
r.setFromCache(Boolean.TRUE);
|
||||
r.setMatchSource(bill.getMatchSource());
|
||||
r.setMatchMessage(bill.getMatchMessage());
|
||||
r.setCustomerId(bill.getCustomerId());
|
||||
r.setPriceSetId(bill.getPriceSetId());
|
||||
r.setPriceSetCode(bill.getPriceSetCode());
|
||||
@@ -2627,6 +2622,8 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
r.setPsdId(bill.getPsdId());
|
||||
r.setProductCode(bill.getProductCode());
|
||||
r.setProductName(bill.getProductName());
|
||||
r.setProductFloorCode(bill.getProductFloorCode());
|
||||
r.setProductFloor(bill.getProductFloor());
|
||||
r.setCountryCode(bill.getCountryCode());
|
||||
r.setCountryName(bill.getCountryName());
|
||||
r.setWeightMin(bill.getWeightMin());
|
||||
@@ -3589,6 +3586,10 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
bill.setProductName(request.getProductName());
|
||||
bill.setCountryCode(request.getCountryCode());
|
||||
bill.setCountryName(request.getCountryName());
|
||||
if (request.getUpstreamRow() != null && !request.getUpstreamRow().isEmpty())
|
||||
{
|
||||
OracleOrderBillExtFiller.fillBillChannelFromRow(bill, request.getUpstreamRow());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -3656,7 +3657,5 @@ public class PrcOrderBillServiceImpl implements IPrcOrderBillService
|
||||
failText = failText.substring(0, 1000);
|
||||
}
|
||||
bill.setErrorMessage(failText);
|
||||
bill.setMatchMessage(null);
|
||||
bill.setMatchSource(null);
|
||||
}
|
||||
}
|
||||
|
||||
+2
-25
@@ -192,7 +192,8 @@ public final class OrderBillExportSupport
|
||||
row.setReceiveWeight(bill.getReceiveWeight());
|
||||
row.setIncomeTotal(bill.getIncomeTotal());
|
||||
row.setPayTotal(bill.getPayTotal());
|
||||
row.setMatchSourceLabel(matchSourceLabel(bill.getMatchSource()));
|
||||
row.setProductFloorCode(bill.getProductFloorCode());
|
||||
row.setProductFloor(bill.getProductFloor());
|
||||
row.setOrderStatusLabel(orderStatusLabel(bill.getOrderStatus()));
|
||||
row.setBillingFailStatusLabel(billingFailStatusLabel(bill.getBillingFailStatus()));
|
||||
row.setCustomerActiveStatusLabel(customerActiveLabel(bill.getCustomerActiveStatus()));
|
||||
@@ -270,30 +271,6 @@ public final class OrderBillExportSupport
|
||||
}
|
||||
}
|
||||
|
||||
public static String matchSourceLabel(String source)
|
||||
{
|
||||
if (StringUtils.isEmpty(source))
|
||||
{
|
||||
return "";
|
||||
}
|
||||
if ("PACKAGE_FIXED".equals(source) || "FIXED".equals(source))
|
||||
{
|
||||
return "客户固定价套餐";
|
||||
}
|
||||
if ("PACKAGE_DISCOUNT".equals(source) || "DISCOUNT".equals(source))
|
||||
{
|
||||
return "客户折扣套餐";
|
||||
}
|
||||
if ("PRODUCT_DEFAULT".equals(source))
|
||||
{
|
||||
return "产品默认价";
|
||||
}
|
||||
if ("BILLING_FAIL".equals(source))
|
||||
{
|
||||
return "计费失败";
|
||||
}
|
||||
return source;
|
||||
}
|
||||
|
||||
public static String customerActiveLabel(String status)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,44 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
limit 1
|
||||
</select>
|
||||
|
||||
<select id="selectByProductIdAndType" resultType="com.bms.price.domain.ChannelProductMap">
|
||||
select m.id,
|
||||
m.channel_id as channelId,
|
||||
m.channel_code as channelCode,
|
||||
m.product_id as productId,
|
||||
c.channel_name as channelName,
|
||||
m.pay_type as payType,
|
||||
m.create_by as createBy,
|
||||
m.create_time as createTime,
|
||||
m.update_by as updateBy,
|
||||
m.update_time as updateTime
|
||||
from srv_channel_product_map m
|
||||
left join srv_service_channel c on c.id = m.channel_id
|
||||
where m.product_id = #{productId}
|
||||
and m.pay_type = #{payType}
|
||||
order by m.channel_code asc, m.channel_id asc
|
||||
</select>
|
||||
|
||||
<select id="selectByProductIdsAndType" resultType="com.bms.price.domain.ChannelProductMap">
|
||||
select m.id,
|
||||
m.channel_id as channelId,
|
||||
m.channel_code as channelCode,
|
||||
m.product_id as productId,
|
||||
c.channel_name as channelName,
|
||||
m.pay_type as payType,
|
||||
m.create_by as createBy,
|
||||
m.create_time as createTime,
|
||||
m.update_by as updateBy,
|
||||
m.update_time as updateTime
|
||||
from srv_channel_product_map m
|
||||
left join srv_service_channel c on c.id = m.channel_id
|
||||
where m.pay_type = #{payType}
|
||||
and m.product_id in
|
||||
<foreach collection="productIds" item="id" open="(" separator="," close=")">
|
||||
#{id}
|
||||
</foreach>
|
||||
order by m.product_id asc, m.channel_code asc, m.channel_id asc
|
||||
</select>
|
||||
|
||||
<insert id="upsert">
|
||||
insert into srv_channel_product_map (
|
||||
|
||||
@@ -42,8 +42,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<result property="weight" column="weight" />
|
||||
<result property="bizDate" column="biz_date" />
|
||||
<result property="tmsId" column="tms_id" />
|
||||
<result property="matchSource" column="match_source" />
|
||||
<result property="matchMessage" column="match_message" />
|
||||
<result property="productFloorCode" column="product_floor_code" />
|
||||
<result property="productFloor" column="product_floor" />
|
||||
<result property="priceSetId" column="price_set_id" />
|
||||
<result property="priceSetCode" column="price_set_code" />
|
||||
<result property="priceSetName" column="price_set_name" />
|
||||
@@ -93,7 +93,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
pieces, actual_weight, receive_weight, volume, volume_weight, pkg_length, pkg_width, pkg_height,
|
||||
shipper_name, consignee_name, dest_postcode, warehouse_code, order_time, order_remark,
|
||||
product_code, product_name, country_code, country_name, weight, biz_date, tms_id,
|
||||
match_source, match_message, price_set_id, price_set_code, price_set_name,
|
||||
product_floor_code, product_floor, price_set_id, price_set_code, price_set_name,
|
||||
set_type, bind_priority, customer_priceset_id, psv_id, psd_id,
|
||||
weight_min, weight_max, weight_label, effective_date, charge_weight,
|
||||
freight_rate, base_freight_rate, discount_percent, registration_fee,
|
||||
@@ -112,7 +112,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
p.pieces, p.actual_weight, p.receive_weight, p.volume, p.volume_weight, p.pkg_length, p.pkg_width, p.pkg_height,
|
||||
p.shipper_name, p.consignee_name, p.dest_postcode, p.warehouse_code, p.order_time, p.order_status, p.bl_pickup, p.pickup_date, p.order_remark,
|
||||
p.product_code, p.product_name, p.country_code, p.country_name, p.weight, p.biz_date, p.tms_id,
|
||||
p.match_source, p.match_message, p.price_set_id, p.price_set_code, p.price_set_name,
|
||||
p.product_floor_code, p.product_floor, p.price_set_id, p.price_set_code, p.price_set_name,
|
||||
p.set_type, p.bind_priority, p.customer_priceset_id, p.psv_id, p.psd_id,
|
||||
p.weight_min, p.weight_max, p.weight_label, p.effective_date, p.charge_weight,
|
||||
p.freight_rate, p.base_freight_rate, p.discount_percent, p.registration_fee,
|
||||
@@ -542,8 +542,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
<if test="countryCode != null and countryCode != ''">
|
||||
AND p.country_code = #{countryCode}
|
||||
</if>
|
||||
<if test="matchSource != null and matchSource != ''">
|
||||
AND p.match_source = #{matchSource}
|
||||
<if test="productFloorCode != null and productFloorCode != ''">
|
||||
AND p.product_floor_code like concat('%', #{productFloorCode}, '%')
|
||||
</if>
|
||||
<if test="bizDate != null">
|
||||
AND p.biz_date = #{bizDate}
|
||||
@@ -844,7 +844,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
pieces, actual_weight, receive_weight, volume, volume_weight, pkg_length, pkg_width, pkg_height,
|
||||
shipper_name, consignee_name, dest_postcode, warehouse_code, order_time, order_status, bl_pickup, pickup_date, order_remark,
|
||||
product_code, product_name, country_code, country_name, weight, biz_date, tms_id,
|
||||
match_source, match_message, price_set_id, price_set_code, price_set_name,
|
||||
product_floor_code, product_floor, price_set_id, price_set_code, price_set_name,
|
||||
set_type, bind_priority, customer_priceset_id, psv_id, psd_id,
|
||||
weight_min, weight_max, weight_label, effective_date, charge_weight,
|
||||
freight_rate, base_freight_rate, discount_percent, registration_fee,
|
||||
@@ -858,7 +858,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
#{pieces}, #{actualWeight}, #{receiveWeight}, #{volume}, #{volumeWeight}, #{pkgLength}, #{pkgWidth}, #{pkgHeight},
|
||||
#{shipperName}, #{consigneeName}, #{destPostcode}, #{warehouseCode}, #{orderTime}, #{orderStatus}, #{blPickup}, #{pickupDate}, #{orderRemark},
|
||||
#{productCode}, #{productName}, #{countryCode}, #{countryName}, #{weight}, #{bizDate}, #{tmsId},
|
||||
#{matchSource}, #{matchMessage}, #{priceSetId}, #{priceSetCode}, #{priceSetName},
|
||||
#{productFloorCode}, #{productFloor}, #{priceSetId}, #{priceSetCode}, #{priceSetName},
|
||||
#{setType}, #{bindPriority}, #{customerPricesetId}, #{psvId}, #{psdId},
|
||||
#{weightMin}, #{weightMax}, #{weightLabel}, #{effectiveDate}, #{chargeWeight},
|
||||
#{freightRate}, #{baseFreightRate}, #{discountPercent}, #{registrationFee},
|
||||
@@ -908,8 +908,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||
weight = #{weight},
|
||||
biz_date = #{bizDate},
|
||||
tms_id = #{tmsId},
|
||||
match_source = #{matchSource},
|
||||
match_message = #{matchMessage},
|
||||
product_floor_code = #{productFloorCode},
|
||||
product_floor = #{productFloor},
|
||||
price_set_id = #{priceSetId},
|
||||
price_set_code = #{priceSetCode},
|
||||
price_set_name = #{priceSetName},
|
||||
|
||||
@@ -924,8 +924,8 @@ CREATE TABLE `prc_order_bill` (
|
||||
`weight` decimal(10,3) DEFAULT NULL COMMENT '计费重量KG',
|
||||
`biz_date` datetime NOT NULL COMMENT '计费时间',
|
||||
`tms_id` bigint(20) DEFAULT NULL COMMENT '多租户系统ID',
|
||||
`match_source` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '命中来源',
|
||||
`match_message` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '命中说明',
|
||||
`product_floor_code` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渠道编码',
|
||||
`product_floor` varchar(200) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '渠道名称',
|
||||
`price_set_id` bigint(20) DEFAULT NULL COMMENT '价格套餐ID',
|
||||
`price_set_code` varchar(20) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '套餐编码',
|
||||
`price_set_name` varchar(50) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '套餐名称',
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
-- prc_order_bill: drop match_source / match_message.
|
||||
-- Idempotent.
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
SET @sql_drop_match_source = (
|
||||
SELECT IF(
|
||||
COUNT(*) > 0,
|
||||
'ALTER TABLE prc_order_bill DROP COLUMN match_source',
|
||||
'SELECT 1'
|
||||
)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'prc_order_bill' AND COLUMN_NAME = 'match_source'
|
||||
);
|
||||
PREPARE stmt FROM @sql_drop_match_source;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql_drop_match_message = (
|
||||
SELECT IF(
|
||||
COUNT(*) > 0,
|
||||
'ALTER TABLE prc_order_bill DROP COLUMN match_message',
|
||||
'SELECT 1'
|
||||
)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'prc_order_bill' AND COLUMN_NAME = 'match_message'
|
||||
);
|
||||
PREPARE stmt FROM @sql_drop_match_message;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -0,0 +1,30 @@
|
||||
-- prc_order_bill: add product_floor_code / product_floor from upstream.
|
||||
-- Idempotent.
|
||||
|
||||
SET NAMES utf8mb4;
|
||||
|
||||
SET @sql_add_floor_code = (
|
||||
SELECT IF(
|
||||
COUNT(*) = 0,
|
||||
'ALTER TABLE prc_order_bill ADD COLUMN product_floor_code varchar(64) DEFAULT NULL COMMENT ''渠道编码'' AFTER tms_id',
|
||||
'SELECT 1'
|
||||
)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'prc_order_bill' AND COLUMN_NAME = 'product_floor_code'
|
||||
);
|
||||
PREPARE stmt FROM @sql_add_floor_code;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
|
||||
SET @sql_add_floor_name = (
|
||||
SELECT IF(
|
||||
COUNT(*) = 0,
|
||||
'ALTER TABLE prc_order_bill ADD COLUMN product_floor varchar(200) DEFAULT NULL COMMENT ''渠道名称'' AFTER product_floor_code',
|
||||
'SELECT 1'
|
||||
)
|
||||
FROM information_schema.COLUMNS
|
||||
WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = 'prc_order_bill' AND COLUMN_NAME = 'product_floor'
|
||||
);
|
||||
PREPARE stmt FROM @sql_add_floor_name;
|
||||
EXECUTE stmt;
|
||||
DEALLOCATE PREPARE stmt;
|
||||
@@ -162,3 +162,19 @@ export function removeLabelProducts(priceSetId, productIds) {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export function listLabelProductChannels(productId, payType = 'AR') {
|
||||
return request({
|
||||
url: '/price/label/product/' + productId + '/channels',
|
||||
method: 'get',
|
||||
params: { payType }
|
||||
})
|
||||
}
|
||||
|
||||
export function replaceLabelProductChannels(productId, data) {
|
||||
return request({
|
||||
url: '/price/label/product/' + productId + '/channels',
|
||||
method: 'put',
|
||||
data
|
||||
})
|
||||
}
|
||||
|
||||
@@ -62,7 +62,8 @@ export const BILLING_BILL_EXPORT_FIELDS = [
|
||||
{ prop: 'receiveWeight', label: '收货重' },
|
||||
{ prop: 'incomeTotal', label: '应收总额' },
|
||||
{ prop: 'payTotal', label: '应付总额' },
|
||||
{ prop: 'matchSourceLabel', label: '计价来源' },
|
||||
{ prop: 'productFloorCode', label: '渠道编码' },
|
||||
{ prop: 'productFloor', label: '渠道名称' },
|
||||
{ prop: 'orderStatusLabel', label: '订单状态' },
|
||||
{ prop: 'billingFailStatusLabel', label: '计费状态' },
|
||||
{ prop: 'customerActiveStatusLabel', label: '客户状态' },
|
||||
|
||||
@@ -80,9 +80,8 @@
|
||||
<el-descriptions-item label="原计费重(kg)">{{ formatWeight(detail.weight) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="重量段">{{ detail.weightLabel || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="计费时间">{{ detail.bizDate || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="计价来源">
|
||||
<el-tag size="small" :type="sourceTagType(detail.matchSource)">{{ sourceLabel(detail.matchSource) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="渠道编码">{{ detail.productFloorCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="渠道名称">{{ detail.productFloor || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="计费状态">
|
||||
<el-tag size="small" :type="billingFailTagType(detail.billingFailStatus)">{{ billingFailLabel(detail.billingFailStatus) }}</el-tag>
|
||||
</el-descriptions-item>
|
||||
@@ -96,10 +95,6 @@
|
||||
<el-descriptions-item label="运费单价" >{{ formatRate(detail.freightRate) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="挂号费" >{{ formatMoney(detail.registrationFee) }}</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
<div v-if="detail.matchMessage" class="match-note">
|
||||
<span class="match-note__label">命中说明</span>
|
||||
<span>{{ detail.matchMessage }}</span>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="detail-block">
|
||||
@@ -422,18 +417,6 @@ function billingFailTagType(status) {
|
||||
return 'success'
|
||||
}
|
||||
|
||||
function sourceLabel(source) {
|
||||
const map = {
|
||||
PACKAGE_FIXED: '客户固定价套餐',
|
||||
PACKAGE_DISCOUNT: '客户折扣套餐',
|
||||
PRODUCT_DEFAULT: '产品默认价',
|
||||
BILLING_FAIL: '计费失败',
|
||||
FIXED: '客户固定价套餐',
|
||||
DISCOUNT: '客户折扣套餐'
|
||||
}
|
||||
return map[source] || source || '-'
|
||||
}
|
||||
|
||||
function roundModeLabel(mode) {
|
||||
const map = { UP: '向上取值', DOWN: '向下取整', HALF_UP: '四舍五入' }
|
||||
return map[mode] || mode || '四舍五入'
|
||||
@@ -466,14 +449,6 @@ function displayFeeName(row) {
|
||||
return name || typeLabel || row.feeType || '-'
|
||||
}
|
||||
|
||||
function sourceTagType(source) {
|
||||
if (source === 'PACKAGE_FIXED' || source === 'FIXED') return 'success'
|
||||
if (source === 'PACKAGE_DISCOUNT' || source === 'DISCOUNT') return 'warning'
|
||||
if (source === 'PRODUCT_DEFAULT') return 'info'
|
||||
if (source === 'BILLING_FAIL') return 'danger'
|
||||
return ''
|
||||
}
|
||||
|
||||
function refundLabel(status) {
|
||||
const map = { NONE: '未退费', REFUNDED: '已退费' }
|
||||
return map[status] || status || '未退费'
|
||||
|
||||
@@ -8,8 +8,7 @@
|
||||
@close="emit('update:visible', false)"
|
||||
>
|
||||
<div class="toolbar">
|
||||
<el-input v-model="keyword" clearable placeholder="产品名称 / 工作表 / 国家" style="width: 260px" />
|
||||
<el-button type="danger" plain :disabled="!selectedIds.length" @click="handleRemove" v-hasPermi="['price:label:remove']">移除</el-button>
|
||||
<el-input v-model="keyword" clearable :placeholder="phSearch" style="width: 300px" />
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="loading"
|
||||
@@ -17,30 +16,26 @@
|
||||
border
|
||||
height="calc(100vh - 220px)"
|
||||
row-key="termId"
|
||||
@selection-change="onSelect"
|
||||
>
|
||||
<el-table-column type="selection" width="48" align="center" />
|
||||
<el-table-column prop="productId" label="产品编号" width="90" align="center" />
|
||||
<el-table-column prop="productName" label="产品名称" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column prop="supplierName" label="价卡归属" width="100" align="center" />
|
||||
<el-table-column prop="countryScope" label="国家/口岸" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="chargeType" label="费用类型" width="110" align="center" />
|
||||
<el-table-column prop="sheetName" label="报价工作表" min-width="140" show-overflow-tooltip />
|
||||
<el-table-column prop="versionNo" label="版本" width="70" align="center" />
|
||||
<el-table-column label="有效期" min-width="180" align="center">
|
||||
<el-table-column prop="productId" :label="colId" width="90" align="center" />
|
||||
<el-table-column prop="productName" :label="colName" min-width="150" show-overflow-tooltip />
|
||||
<el-table-column :label="colTerm" min-width="180" align="center">
|
||||
<template #default="{ row }">{{ termText(row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="状态" width="90" align="center">
|
||||
<el-table-column :label="colStatus" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<el-tag :type="termStatusTag(row.termStatus)" size="small">{{ termStatusText(row.termStatus) }}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column prop="weightCount" label="重量段" width="80" align="center" />
|
||||
<el-table-column prop="surchargeCount" label="附加费" width="80" align="center" />
|
||||
<el-table-column label="操作" width="160" align="center" fixed="right">
|
||||
<el-table-column prop="weightCount" :label="colWeight" width="80" align="center" />
|
||||
<el-table-column prop="surchargeCount" :label="colSc" width="80" align="center" />
|
||||
<el-table-column :label="colBoundChannels" min-width="180" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ boundChannelText(row) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="colAction" width="160" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="primary" @click="openProduct(row)" v-hasPermi="['price:label:query']">查看</el-button>
|
||||
<el-button link type="danger" @click="handleRemove([row.productId])" v-hasPermi="['price:label:remove']">移除</el-button>
|
||||
<el-button link type="primary" @click="openBindList(row)" v-hasPermi="['price:label:edit']">绑定</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
@@ -51,11 +46,89 @@
|
||||
<el-button @click="detailVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<el-drawer
|
||||
v-model="bindListVisible"
|
||||
:title="bindListTitle"
|
||||
size="520px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@closed="onBindListClosed"
|
||||
>
|
||||
<div class="bind-list-toolbar">
|
||||
<el-button type="primary" plain @click="openAddChannels" v-hasPermi="['price:label:edit']">添加渠道</el-button>
|
||||
</div>
|
||||
<el-table
|
||||
v-loading="bindListLoading"
|
||||
:data="boundChannels"
|
||||
border
|
||||
height="calc(100vh - 240px)"
|
||||
:empty-text="emptyBound"
|
||||
>
|
||||
<el-table-column prop="channelCode" :label="colChannelCode" min-width="120" show-overflow-tooltip />
|
||||
<el-table-column prop="channelName" :label="colChannelName" min-width="160" show-overflow-tooltip />
|
||||
<el-table-column :label="colAction" width="90" align="center" fixed="right">
|
||||
<template #default="{ row }">
|
||||
<el-button link type="danger" @click="removeBoundChannel(row)" v-hasPermi="['price:label:edit']">移除</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<template #footer>
|
||||
<el-button @click="bindListVisible = false">关闭</el-button>
|
||||
</template>
|
||||
</el-drawer>
|
||||
|
||||
<el-dialog
|
||||
v-model="addVisible"
|
||||
:title="addTitle"
|
||||
width="560px"
|
||||
append-to-body
|
||||
destroy-on-close
|
||||
@closed="onAddClosed"
|
||||
>
|
||||
<div v-loading="addLoading">
|
||||
<el-form label-width="88px">
|
||||
<el-form-item :label="lblProduct">
|
||||
<span>{{ bindProductName }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item :label="lblChannels">
|
||||
<el-select
|
||||
v-model="addChannelIds"
|
||||
multiple
|
||||
filterable
|
||||
clearable
|
||||
collapse-tags
|
||||
collapse-tags-tooltip
|
||||
:placeholder="phChannels"
|
||||
style="width: 100%"
|
||||
>
|
||||
<el-option
|
||||
v-for="item in addableChannelOptions"
|
||||
:key="item.id"
|
||||
:label="channelOptionLabel(item)"
|
||||
:value="String(item.id)"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<div class="bind-hint">{{ bindHint }}</div>
|
||||
</el-form>
|
||||
</div>
|
||||
<template #footer>
|
||||
<el-button @click="addVisible = false">取消</el-button>
|
||||
<el-button type="primary" :loading="addSaving" @click="submitAddChannels">保存</el-button>
|
||||
</template>
|
||||
</el-dialog>
|
||||
</el-drawer>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { listLabelProducts, getLabelProduct, removeLabelProducts } from '@/api/price/label'
|
||||
import {
|
||||
listLabelProducts,
|
||||
getLabelProduct,
|
||||
listLabelProductChannels,
|
||||
replaceLabelProductChannels
|
||||
} from '@/api/price/label'
|
||||
import { listChannelOptions } from '@/api/masterdata/serviceChannel'
|
||||
import PayConfigDetail from '@/views/price/basic/pay/components/PayConfigDetail.vue'
|
||||
|
||||
const props = defineProps({
|
||||
@@ -69,11 +142,40 @@ const { proxy } = getCurrentInstance()
|
||||
const loading = ref(false)
|
||||
const rows = ref([])
|
||||
const keyword = ref('')
|
||||
const selectedIds = ref([])
|
||||
const detailVisible = ref(false)
|
||||
const detailLoading = ref(false)
|
||||
const detail = ref(null)
|
||||
|
||||
const bindListVisible = ref(false)
|
||||
const bindListLoading = ref(false)
|
||||
const bindProductId = ref(null)
|
||||
const bindProductName = ref('')
|
||||
const boundChannels = ref([])
|
||||
const channelOptions = ref([])
|
||||
|
||||
const addVisible = ref(false)
|
||||
const addLoading = ref(false)
|
||||
const addSaving = ref(false)
|
||||
const addChannelIds = ref([])
|
||||
|
||||
const phSearch = '产品名称 / 绑定渠道'
|
||||
const colId = '产品编号'
|
||||
const colName = '产品名称'
|
||||
const colTerm = '有效期'
|
||||
const colStatus = '状态'
|
||||
const colWeight = '重量段'
|
||||
const colSc = '附加费'
|
||||
const colBoundChannels = '绑定渠道'
|
||||
const colAction = '操作'
|
||||
const colChannelCode = '渠道编码'
|
||||
const colChannelName = '渠道名称'
|
||||
const lblProduct = '产品'
|
||||
const lblChannels = '添加渠道'
|
||||
const phChannels = '请选择要添加的渠道(可多选)'
|
||||
const bindHint = '绑定为收款(AR),落库 srv_channel_product_map;一个渠道同一收付类型仅保留一条产品映射。'
|
||||
const emptyBound = '暂无绑定渠道'
|
||||
const addTitle = '添加渠道'
|
||||
|
||||
const title = computed(() => {
|
||||
const v = props.version || {}
|
||||
const label = v.versionLabel || (v.versionNo != null ? `V${v.versionNo}` : '')
|
||||
@@ -86,15 +188,24 @@ const detailTitle = computed(() => {
|
||||
return `${detail.value.productName || '产品'} ${no}`.trim()
|
||||
})
|
||||
|
||||
const bindListTitle = computed(() => {
|
||||
return bindProductName.value ? `绑定渠道 · ${bindProductName.value}` : '绑定渠道'
|
||||
})
|
||||
|
||||
const filteredRows = computed(() => {
|
||||
const kw = keyword.value.trim().toLowerCase()
|
||||
if (!kw) return rows.value
|
||||
return rows.value.filter(row => {
|
||||
const text = [row.productName, row.sheetName, row.countryScope, row.supplierName].join(' ').toLowerCase()
|
||||
const text = [row.productName, boundChannelText(row)].join(' ').toLowerCase()
|
||||
return text.includes(kw)
|
||||
})
|
||||
})
|
||||
|
||||
const addableChannelOptions = computed(() => {
|
||||
const bound = new Set((boundChannels.value || []).map(item => String(item.channelId)))
|
||||
return (channelOptions.value || []).filter(item => item && item.id != null && !bound.has(String(item.id)))
|
||||
})
|
||||
|
||||
function formatHour(val) {
|
||||
if (!val) return ''
|
||||
const text = String(val).replace('T', ' ')
|
||||
@@ -120,8 +231,17 @@ function termStatusTag(status) {
|
||||
return map[String(status)] || 'info'
|
||||
}
|
||||
|
||||
function onSelect(selection) {
|
||||
selectedIds.value = (selection || []).map(item => item.productId).filter(Boolean)
|
||||
function channelOptionLabel(item) {
|
||||
const code = item?.channelCode || item?.id || ''
|
||||
const name = item?.channelName || ''
|
||||
if (code && name && code !== name) return code + ' / ' + name
|
||||
return code || name || '-'
|
||||
}
|
||||
|
||||
function boundChannelText(row) {
|
||||
if (!row) return '-'
|
||||
if (row.boundChannelText) return row.boundChannelText
|
||||
return '-'
|
||||
}
|
||||
|
||||
async function load() {
|
||||
@@ -150,16 +270,96 @@ async function openProduct(row) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleRemove(ids) {
|
||||
const list = (Array.isArray(ids) ? ids : selectedIds.value).filter(Boolean)
|
||||
if (!list.length || !props.priceSetId) return
|
||||
proxy.$modal.confirm(`确认从本套餐移除选中的 ${list.length} 个产品?`).then(() => {
|
||||
return removeLabelProducts(props.priceSetId, list.join(','))
|
||||
}).then(() => {
|
||||
proxy.$modal.msgSuccess('已移除')
|
||||
load()
|
||||
emit('changed')
|
||||
}).catch(() => {})
|
||||
async function ensureChannelOptions() {
|
||||
if (channelOptions.value.length) return
|
||||
const res = await listChannelOptions({ blOpen: '1' })
|
||||
channelOptions.value = res.data || []
|
||||
}
|
||||
|
||||
async function loadBoundChannels() {
|
||||
if (!bindProductId.value) {
|
||||
boundChannels.value = []
|
||||
return
|
||||
}
|
||||
bindListLoading.value = true
|
||||
try {
|
||||
const res = await listLabelProductChannels(bindProductId.value, 'AR')
|
||||
boundChannels.value = res.data || []
|
||||
} finally {
|
||||
bindListLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
async function openBindList(row) {
|
||||
if (!row?.productId) return
|
||||
bindProductId.value = row.productId
|
||||
bindProductName.value = row.productName || String(row.productId)
|
||||
boundChannels.value = []
|
||||
bindListVisible.value = true
|
||||
await loadBoundChannels()
|
||||
}
|
||||
|
||||
function onBindListClosed() {
|
||||
bindProductId.value = null
|
||||
bindProductName.value = ''
|
||||
boundChannels.value = []
|
||||
addVisible.value = false
|
||||
addChannelIds.value = []
|
||||
}
|
||||
|
||||
async function openAddChannels() {
|
||||
addChannelIds.value = []
|
||||
addVisible.value = true
|
||||
addLoading.value = true
|
||||
try {
|
||||
await ensureChannelOptions()
|
||||
} finally {
|
||||
addLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
function onAddClosed() {
|
||||
addChannelIds.value = []
|
||||
}
|
||||
|
||||
function currentBoundIds() {
|
||||
return (boundChannels.value || []).map(item => String(item.channelId)).filter(Boolean)
|
||||
}
|
||||
|
||||
function submitAddChannels() {
|
||||
if (!bindProductId.value) return
|
||||
const selected = (addChannelIds.value || []).map(String).filter(Boolean)
|
||||
if (!selected.length) {
|
||||
proxy.$modal.msgWarning('请先选择要添加的渠道')
|
||||
return
|
||||
}
|
||||
const merged = Array.from(new Set(currentBoundIds().concat(selected)))
|
||||
addSaving.value = true
|
||||
replaceLabelProductChannels(bindProductId.value, {
|
||||
payType: 'AR',
|
||||
channelIds: merged
|
||||
}).then((res) => {
|
||||
proxy.$modal.msgSuccess((res && res.msg) || '添加成功')
|
||||
addVisible.value = false
|
||||
return loadBoundChannels()
|
||||
}).then(() => load()).catch(() => {}).finally(() => {
|
||||
addSaving.value = false
|
||||
})
|
||||
}
|
||||
|
||||
function removeBoundChannel(row) {
|
||||
if (!bindProductId.value || !row?.channelId) return
|
||||
const label = channelOptionLabel(row)
|
||||
proxy.$modal.confirm(`确认移除渠道「${label}」?`).then(() => {
|
||||
const remain = currentBoundIds().filter(id => id !== String(row.channelId))
|
||||
return replaceLabelProductChannels(bindProductId.value, {
|
||||
payType: 'AR',
|
||||
channelIds: remain
|
||||
})
|
||||
}).then((res) => {
|
||||
proxy.$modal.msgSuccess((res && res.msg) || '已移除')
|
||||
return loadBoundChannels()
|
||||
}).then(() => load()).catch(() => {})
|
||||
}
|
||||
|
||||
watch(() => [props.visible, props.priceSetId, props.version?.versionNo], ([vis]) => {
|
||||
@@ -174,4 +374,15 @@ watch(() => [props.visible, props.priceSetId, props.version?.versionNo], ([vis])
|
||||
margin-bottom: 12px;
|
||||
align-items: center;
|
||||
}
|
||||
.bind-list-toolbar {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
.bind-hint {
|
||||
margin: -4px 0 0 88px;
|
||||
color: #909399;
|
||||
font-size: 12px;
|
||||
line-height: 1.5;
|
||||
}
|
||||
</style>
|
||||
|
||||
Reference in New Issue
Block a user