新增按版本获取价格设置明细的接口,优化产品下拉选项查询,更新相关服务和前端调用逻辑。
This commit is contained in:
@@ -227,6 +227,14 @@ public class PriceSetController extends BaseController
|
|||||||
return success(priceSetService.selectDetailListByProduct(psvId, productCode));
|
return success(priceSetService.selectDetailListByProduct(psvId, productCode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** All detail rows for a version (no page); batch prefetch instead of N byProduct calls. */
|
||||||
|
@PreAuthorize("@ss.hasPermi('price:set:list')")
|
||||||
|
@GetMapping("/detail/byVersion")
|
||||||
|
public AjaxResult detailByVersion(@RequestParam("psvId") Long psvId)
|
||||||
|
{
|
||||||
|
return success(priceSetService.selectDetailListByVersion(psvId));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 版本明细搜索下拉选项:按版本去重后的 产品/国家/分区
|
* 版本明细搜索下拉选项:按版本去重后的 产品/国家/分区
|
||||||
*/
|
*/
|
||||||
|
|||||||
+3
-3
@@ -63,13 +63,13 @@ public class ProductController extends BaseController
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 产品下拉选项(非分页)。
|
* Product dropdown (non-paged). Slim query, no list-page status refresh.
|
||||||
* 供计费列表、客户绑定等场景选择产品;不做权限控制(仍需登录)。
|
* Used by price-set / billing / customer bind; login required, no extra perm.
|
||||||
*/
|
*/
|
||||||
@GetMapping("/optionselect")
|
@GetMapping("/optionselect")
|
||||||
public AjaxResult optionselect(BmsProduct product)
|
public AjaxResult optionselect(BmsProduct product)
|
||||||
{
|
{
|
||||||
List<BmsProduct> list = productService.selectBmsProductList(product);
|
List<BmsProduct> list = productService.selectBmsProductOptions(product);
|
||||||
return success(list);
|
return success(list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,7 @@ price.product.import.sheetNotFound=未找到「产品目录」sheet,请上传
|
|||||||
price.product.import.noData=产品目录无有效数据行
|
price.product.import.noData=产品目录无有效数据行
|
||||||
price.product.import.catalogHeaderMissing=「产品目录」未找到表头「对接代码」,请在标题行下补齐表头(对接代码、产品名称、时效、走货属性、国家等)
|
price.product.import.catalogHeaderMissing=「产品目录」未找到表头「对接代码」,请在标题行下补齐表头(对接代码、产品名称、时效、走货属性、国家等)
|
||||||
price.product.import.countryCatalogHeaderMissing=「产品目录」未找到表头「产品名称」或「产品ID」,请确认是否为单国专线成本价表格式
|
price.product.import.countryCatalogHeaderMissing=「产品目录」未找到表头「产品名称」或「产品ID」,请确认是否为单国专线成本价表格式
|
||||||
|
price.product.import.singleCountryAsMulti=当前选择的是「全部导入(多国家价表)」,但上传的文件更像单国专线成本价表(价表无「国家」列)。请改用「按国家导入」,并选择目的国家后再上传。
|
||||||
price.product.import.regionEmpty=region 无可用国家数据,请先同步/维护国家表后再导入
|
price.product.import.regionEmpty=region 无可用国家数据,请先同步/维护国家表后再导入
|
||||||
price.product.import.partialFail=导入完成但存在失败项:新增 {0},跳过 {1};失败明细:{2}
|
price.product.import.partialFail=导入完成但存在失败项:新增 {0},跳过 {1};失败明细:{2}
|
||||||
price.product.import.effTooEarly=产品{0}({1})导入生效时间{2}早于该产品上一版生效时间{3},不允许导入
|
price.product.import.effTooEarly=产品{0}({1})导入生效时间{2}早于该产品上一版生效时间{3},不允许导入
|
||||||
|
|||||||
@@ -30,6 +30,9 @@ public interface BmsProductMapper
|
|||||||
|
|
||||||
public List<BmsProduct> selectBmsProductList(BmsProduct product);
|
public List<BmsProduct> selectBmsProductList(BmsProduct product);
|
||||||
|
|
||||||
|
/** Dropdown options: slim columns, no country/surcharge count subqueries */
|
||||||
|
public List<BmsProduct> selectBmsProductOptions(BmsProduct product);
|
||||||
|
|
||||||
public int insertBmsProduct(BmsProduct product);
|
public int insertBmsProduct(BmsProduct product);
|
||||||
|
|
||||||
public int updateBmsProduct(BmsProduct product);
|
public int updateBmsProduct(BmsProduct product);
|
||||||
|
|||||||
@@ -19,6 +19,9 @@ public interface IBmsProductService
|
|||||||
|
|
||||||
public List<BmsProduct> selectBmsProductList(BmsProduct product);
|
public List<BmsProduct> selectBmsProductList(BmsProduct product);
|
||||||
|
|
||||||
|
/** Product dropdown options (no status refresh, no count subqueries). */
|
||||||
|
public List<BmsProduct> selectBmsProductOptions(BmsProduct product);
|
||||||
|
|
||||||
public int insertBmsProduct(BmsProduct product);
|
public int insertBmsProduct(BmsProduct product);
|
||||||
|
|
||||||
public int updateBmsProduct(BmsProduct product);
|
public int updateBmsProduct(BmsProduct product);
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ public interface IPrcPriceSetService
|
|||||||
*/
|
*/
|
||||||
public List<PrcPriceSetDetail> selectDetailListByProduct(Long psvId, String productCode);
|
public List<PrcPriceSetDetail> selectDetailListByProduct(Long psvId, String productCode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load all detail rows for a version (no pagination). For batch prefetch vs N byProduct calls.
|
||||||
|
*/
|
||||||
|
public List<PrcPriceSetDetail> selectDetailListByVersion(Long psvId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 版本明细搜索下拉选项:按版本去重后的 产品/国家/分区 列表。
|
* 版本明细搜索下拉选项:按版本去重后的 产品/国家/分区 列表。
|
||||||
* 返回 { products: [{code,name}], countries: [{code,name}], zones: [{code,name}] }
|
* 返回 { products: [{code,name}], countries: [{code,name}], zones: [{code,name}] }
|
||||||
|
|||||||
+89
-2
@@ -129,8 +129,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
|||||||
@Override
|
@Override
|
||||||
public List<BmsProduct> selectBmsProductList(BmsProduct product)
|
public List<BmsProduct> selectBmsProductList(BmsProduct product)
|
||||||
{
|
{
|
||||||
productMapper.refreshStatusByDates();
|
// Status refresh is done on activate / scheduled task; skip UPDATE on every list read.
|
||||||
countryMapper.refreshStatusByDates();
|
|
||||||
if (product != null)
|
if (product != null)
|
||||||
{
|
{
|
||||||
product.setStatus(normalizeStatusCode(product.getStatus()));
|
product.setStatus(normalizeStatusCode(product.getStatus()));
|
||||||
@@ -139,6 +138,17 @@ public class BmsProductServiceImpl implements IBmsProductService
|
|||||||
return productMapper.selectBmsProductList(product);
|
return productMapper.selectBmsProductList(product);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<BmsProduct> selectBmsProductOptions(BmsProduct product)
|
||||||
|
{
|
||||||
|
if (product != null)
|
||||||
|
{
|
||||||
|
product.setStatus(normalizeStatusCode(product.getStatus()));
|
||||||
|
product.setEffectStatus(normalizeStatusCode(product.getEffectStatus()));
|
||||||
|
}
|
||||||
|
return productMapper.selectBmsProductOptions(product);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int insertBmsProduct(BmsProduct product)
|
public int insertBmsProduct(BmsProduct product)
|
||||||
{
|
{
|
||||||
@@ -378,6 +388,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
|||||||
{
|
{
|
||||||
throw new ServiceException(MessageUtils.message("price.product.import.sheetNotFound"));
|
throw new ServiceException(MessageUtils.message("price.product.import.sheetNotFound"));
|
||||||
}
|
}
|
||||||
|
assertNotSingleCountryQuoteForMultiImport(workbook);
|
||||||
|
|
||||||
List<BmsProduct> products = parseCatalog(catalog);
|
List<BmsProduct> products = parseCatalog(catalog);
|
||||||
if (products.isEmpty())
|
if (products.isEmpty())
|
||||||
@@ -678,6 +689,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
|||||||
{
|
{
|
||||||
throw new ServiceException(MessageUtils.message("price.product.import.sheetNotFound"));
|
throw new ServiceException(MessageUtils.message("price.product.import.sheetNotFound"));
|
||||||
}
|
}
|
||||||
|
assertNotSingleCountryQuoteForMultiImport(workbook);
|
||||||
List<BmsProduct> products = dedupeCatalogProducts(parseCatalog(catalog));
|
List<BmsProduct> products = dedupeCatalogProducts(parseCatalog(catalog));
|
||||||
if (products.isEmpty())
|
if (products.isEmpty())
|
||||||
{
|
{
|
||||||
@@ -763,6 +775,7 @@ public class BmsProductServiceImpl implements IBmsProductService
|
|||||||
}
|
}
|
||||||
if (out.isEmpty())
|
if (out.isEmpty())
|
||||||
{
|
{
|
||||||
|
assertNotSingleCountryQuoteForMultiImport(workbook);
|
||||||
throw new ServiceException(MessageUtils.message("price.set.import.noPriceRows"));
|
throw new ServiceException(MessageUtils.message("price.set.import.noPriceRows"));
|
||||||
}
|
}
|
||||||
QuoteWorkbook parsed = new QuoteWorkbook();
|
QuoteWorkbook parsed = new QuoteWorkbook();
|
||||||
@@ -778,6 +791,80 @@ public class BmsProductServiceImpl implements IBmsProductService
|
|||||||
private Map<String, List<BmsProductCountry>> byCode;
|
private Map<String, List<BmsProductCountry>> byCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Multi-country import expects price sheets with a "country" column.
|
||||||
|
* Single-country dedicated-line sheets use product-name + weight blocks instead.
|
||||||
|
*/
|
||||||
|
private void assertNotSingleCountryQuoteForMultiImport(Workbook workbook)
|
||||||
|
{
|
||||||
|
if (looksLikeSingleCountryQuote(workbook))
|
||||||
|
{
|
||||||
|
throw new ServiceException(MessageUtils.message("price.product.import.singleCountryAsMulti"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Detect single-country cost-sheet layout (no country column on price sheets). */
|
||||||
|
private boolean looksLikeSingleCountryQuote(Workbook workbook)
|
||||||
|
{
|
||||||
|
if (workbook == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
boolean sawCountryCol = false;
|
||||||
|
boolean sawCountryPriceBlock = false;
|
||||||
|
for (int i = 0; i < workbook.getNumberOfSheets(); i++)
|
||||||
|
{
|
||||||
|
String sheetName = workbook.getSheetName(i);
|
||||||
|
if (shouldSkipCountryPriceSheet(sheetName))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Sheet sheet = workbook.getSheetAt(i);
|
||||||
|
if (sheet == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (findHeaderCell(sheet, "\u56fd\u5bb6") != null)
|
||||||
|
{
|
||||||
|
sawCountryCol = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
int[] nameHeader = findHeaderCell(sheet, "\u4ea7\u54c1\u540d\u79f0");
|
||||||
|
if (nameHeader == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Row head = sheet.getRow(nameHeader[0]);
|
||||||
|
if (head == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (findColByHeader(head, "\u91cd\u91cf", 0) >= 0)
|
||||||
|
{
|
||||||
|
sawCountryPriceBlock = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (sawCountryCol)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (sawCountryPriceBlock)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Sheet catalog = workbook.getSheet(CATALOG_SHEET);
|
||||||
|
if (catalog == null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (findHeaderCell(catalog, "\u5bf9\u63a5\u4ee3\u7801") != null)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return findHeaderCell(catalog, "\u4ea7\u54c1\u540d\u79f0") != null
|
||||||
|
|| findHeaderCell(catalog, "\u4ea7\u54c1ID") != null;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, List<BmsProductCountry>> parseCountryQuoteExcelByProduct(byte[] bytes, String filename,
|
public Map<String, List<BmsProductCountry>> parseCountryQuoteExcelByProduct(byte[] bytes, String filename,
|
||||||
String countryCode) throws Exception
|
String countryCode) throws Exception
|
||||||
|
|||||||
+12
@@ -881,6 +881,18 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService
|
|||||||
return selectDetailList(q);
|
return selectDetailList(q);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<PrcPriceSetDetail> selectDetailListByVersion(Long psvId)
|
||||||
|
{
|
||||||
|
if (psvId == null)
|
||||||
|
{
|
||||||
|
return new ArrayList<PrcPriceSetDetail>();
|
||||||
|
}
|
||||||
|
PrcPriceSetDetail q = new PrcPriceSetDetail();
|
||||||
|
q.setPsvId(psvId);
|
||||||
|
return selectDetailList(q);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<String, Object> selectDetailOptions(Long psvId)
|
public Map<String, Object> selectDetailOptions(Long psvId)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -45,14 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
ifnull(p.is_del, '0') as is_del,
|
ifnull(p.is_del, '0') as is_del,
|
||||||
p.source_sheet, null as remark, null as tms_id,
|
p.source_sheet, null as remark, null as tms_id,
|
||||||
v.created_by, p.create_time, v.updated_by, p.update_time,
|
v.created_by, p.create_time, v.updated_by, p.update_time,
|
||||||
(select count(distinct ifnull(c.country_code, c.country_name)) from prc_price_set_detail c
|
null as country_count, null as surcharge_count
|
||||||
where ifnull(c.is_del, '0') = '0'
|
|
||||||
and (c.psp_id = p.psp_id or (c.psv_id = p.psv_id and c.product_code = p.product_code))
|
|
||||||
) as country_count,
|
|
||||||
(select count(*) from prc_surcharge_rel r
|
|
||||||
inner join prc_surcharge s on s.sc_id = r.sc_id and ifnull(s.is_del, '0') = '0'
|
|
||||||
where ifnull(r.is_del, '0') = '0'
|
|
||||||
and r.product_id = p.psp_id and r.price_type = 'PRODUCT') as surcharge_count
|
|
||||||
from prc_price_set_product p
|
from prc_price_set_product p
|
||||||
inner join prc_price_set_version v on v.psv_id = p.psv_id
|
inner join prc_price_set_version v on v.psv_id = p.psv_id
|
||||||
</sql>
|
</sql>
|
||||||
@@ -176,6 +169,66 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
|||||||
</choose>
|
</choose>
|
||||||
</select>
|
</select>
|
||||||
|
|
||||||
|
<!-- Dropdown: same filters as list, without per-row country/surcharge count scans -->
|
||||||
|
<select id="selectBmsProductOptions" parameterType="BmsProduct" resultMap="BmsProductResult">
|
||||||
|
select p.psp_id as product_id, p.psv_id, p.price_type, p.product_code, p.product_name, p.service_level, p.cargo_attr,
|
||||||
|
p.dest_region, p.tax_mode,
|
||||||
|
p.effective_time as effective_date, p.expire_time as expire_date, p.status,
|
||||||
|
ifnull(p.is_del, '0') as is_del,
|
||||||
|
null as update_note, null as source_sheet, null as remark, null as tms_id,
|
||||||
|
null as created_by, p.create_time, null as updated_by, p.update_time,
|
||||||
|
null as country_count, null as surcharge_count
|
||||||
|
from prc_price_set_product p
|
||||||
|
inner join prc_price_set_version v on v.psv_id = p.psv_id
|
||||||
|
<where>
|
||||||
|
and p.price_type = 'PRODUCT'
|
||||||
|
and ifnull(p.is_del, '0') = '0'
|
||||||
|
<choose>
|
||||||
|
<when test="psvId != null">
|
||||||
|
AND p.psv_id = #{psvId}
|
||||||
|
</when>
|
||||||
|
<when test="statusGroup != null and statusGroup == 'effect'">
|
||||||
|
AND v.price_set_id is null AND v.status = '1'
|
||||||
|
</when>
|
||||||
|
<when test="statusGroup != null and statusGroup == 'pending'">
|
||||||
|
AND v.price_set_id is null AND v.status in ('0', '3')
|
||||||
|
</when>
|
||||||
|
<when test="statusGroup != null and statusGroup == 'expired'">
|
||||||
|
AND v.status = '2'
|
||||||
|
</when>
|
||||||
|
<otherwise>
|
||||||
|
AND p.psv_id = <include refid="latestProductPsv"/>
|
||||||
|
</otherwise>
|
||||||
|
</choose>
|
||||||
|
<if test="productCode != null and productCode != ''">
|
||||||
|
AND p.product_code like concat('%', #{productCode}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="productName != null and productName != ''">
|
||||||
|
AND p.product_name like concat('%', #{productName}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="taxMode != null and taxMode != ''">
|
||||||
|
AND p.tax_mode = #{taxMode}
|
||||||
|
</if>
|
||||||
|
<if test="status != null and status != ''">
|
||||||
|
AND v.status = #{status}
|
||||||
|
</if>
|
||||||
|
<if test="effectStatus != null and effectStatus != ''">
|
||||||
|
AND v.status = #{effectStatus}
|
||||||
|
</if>
|
||||||
|
<if test="statusGroup != null and statusGroup == 'active'">
|
||||||
|
AND v.status in ('0', '1')
|
||||||
|
</if>
|
||||||
|
<if test="cargoAttr != null and cargoAttr != ''">
|
||||||
|
AND p.cargo_attr like concat('%', #{cargoAttr}, '%')
|
||||||
|
</if>
|
||||||
|
<if test="params != null and params.keyword != null and params.keyword != ''">
|
||||||
|
AND (p.product_code like concat('%', #{params.keyword}, '%')
|
||||||
|
OR p.product_name like concat('%', #{params.keyword}, '%'))
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
order by p.product_code asc, p.psp_id desc
|
||||||
|
</select>
|
||||||
|
|
||||||
<insert id="insertBmsProduct" parameterType="BmsProduct" useGeneratedKeys="true" keyProperty="productId">
|
<insert id="insertBmsProduct" parameterType="BmsProduct" useGeneratedKeys="true" keyProperty="productId">
|
||||||
insert into prc_price_set_product (
|
insert into prc_price_set_product (
|
||||||
price_type, psv_id, product_code, product_name, service_level, cargo_attr,
|
price_type, psv_id, product_code, product_name, service_level, cargo_attr,
|
||||||
|
|||||||
@@ -198,6 +198,15 @@ export function listSetDetailByProduct(psvId, productCode) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** All detail rows for a version (no pagination); one call instead of N byProduct. */
|
||||||
|
export function listSetDetailByVersion(psvId) {
|
||||||
|
return request({
|
||||||
|
url: '/price/set/detail/byVersion',
|
||||||
|
method: 'get',
|
||||||
|
params: { psvId }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
/** 版本明细搜索下拉选项:按版本去重后的 产品/国家/分区 */
|
/** 版本明细搜索下拉选项:按版本去重后的 产品/国家/分区 */
|
||||||
export function listSetDetailOptions(psvId) {
|
export function listSetDetailOptions(psvId) {
|
||||||
return request({
|
return request({
|
||||||
|
|||||||
@@ -125,7 +125,7 @@
|
|||||||
@click="openBatchFee"
|
@click="openBatchFee"
|
||||||
>批量增加费用</el-button>
|
>批量增加费用</el-button>
|
||||||
</el-col>
|
</el-col>
|
||||||
<!-- <el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="primary"
|
type="primary"
|
||||||
plain
|
plain
|
||||||
@@ -133,7 +133,7 @@
|
|||||||
v-hasPermi="['price:billing:chargeWeightEdit']"
|
v-hasPermi="['price:billing:chargeWeightEdit']"
|
||||||
@click="openChargeWeightImport"
|
@click="openChargeWeightImport"
|
||||||
>批量修改计费重</el-button>
|
>批量修改计费重</el-button>
|
||||||
</el-col> -->
|
</el-col>
|
||||||
<el-col :span="1.5">
|
<el-col :span="1.5">
|
||||||
<el-button
|
<el-button
|
||||||
type="info"
|
type="info"
|
||||||
@@ -164,14 +164,14 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #col-action="{ row }">
|
<template #col-action="{ row }">
|
||||||
<el-button link type="primary" icon="View" @click="handleView(row)">查看</el-button>
|
<el-button link type="primary" icon="View" @click="handleView(row)">查看</el-button>
|
||||||
<!-- <el-button
|
<el-button
|
||||||
link
|
link
|
||||||
type="primary"
|
type="primary"
|
||||||
icon="Edit"
|
icon="Edit"
|
||||||
:disabled="row.refundStatus === 'REFUNDED'"
|
:disabled="row.refundStatus === 'REFUNDED'"
|
||||||
v-hasPermi="['price:billing:chargeWeightEdit']"
|
v-hasPermi="['price:billing:chargeWeightEdit']"
|
||||||
@click="openEditChargeWeight(row)"
|
@click="openEditChargeWeight(row)"
|
||||||
>改计费重</el-button> -->
|
>改计费重</el-button>
|
||||||
<el-button
|
<el-button
|
||||||
link
|
link
|
||||||
type="danger"
|
type="danger"
|
||||||
@@ -461,7 +461,7 @@ const columns = [
|
|||||||
{ label: '销售员', prop: 'belongSaler', minWidth: 100, showOverflowTooltip: true },
|
{ label: '销售员', prop: 'belongSaler', minWidth: 100, showOverflowTooltip: true },
|
||||||
{ label: '结算员', prop: 'settlementMan', minWidth: 100, showOverflowTooltip: true },
|
{ label: '结算员', prop: 'settlementMan', minWidth: 100, showOverflowTooltip: true },
|
||||||
{ label: '客服员', prop: 'serviceMan', minWidth: 100, showOverflowTooltip: true },
|
{ label: '客服员', prop: 'serviceMan', minWidth: 100, showOverflowTooltip: true },
|
||||||
{ label: '操作', prop: 'action', align: 'center', width: 150, fixed: 'right', slot: 'action', showInToolbar: false, showOverflowTooltip: false }
|
{ label: '操作', prop: 'action', align: 'center', width: 240, fixed: 'right', slot: 'action', showInToolbar: false, showOverflowTooltip: false }
|
||||||
]
|
]
|
||||||
|
|
||||||
const arrearsStatusOptions = [
|
const arrearsStatusOptions = [
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ const columns = [
|
|||||||
{ label: '订单状态', prop: 'orderStatus', align: 'center', width: 110, slot: 'orderStatus' },
|
{ label: '订单状态', prop: 'orderStatus', align: 'center', width: 110, slot: 'orderStatus' },
|
||||||
{ label: '计费状态', prop: 'billingFailStatus', align: 'center', width: 140, slot: 'billingFailStatus' },
|
{ label: '计费状态', prop: 'billingFailStatus', align: 'center', width: 140, slot: 'billingFailStatus' },
|
||||||
{ label: '计费时间', prop: 'bizDate', align: 'center', width: 170, parseTime: true },
|
{ label: '计费时间', prop: 'bizDate', align: 'center', width: 170, parseTime: true },
|
||||||
{ label: '下单时间', prop: 'orderTime', align: 'center', width: 170, parseTime: true },
|
// { label: '下单时间', prop: 'orderTime', align: 'center', width: 170, parseTime: true },
|
||||||
{ label: '提货时间', prop: 'pickupDate', align: 'center', width: 170, parseTime: true },
|
{ label: '提货时间', prop: 'pickupDate', align: 'center', width: 170, parseTime: true },
|
||||||
{ label: '销售员', prop: 'belongSaler', minWidth: 100, showOverflowTooltip: true },
|
{ label: '销售员', prop: 'belongSaler', minWidth: 100, showOverflowTooltip: true },
|
||||||
{ label: '结算员', prop: 'settlementMan', minWidth: 100, showOverflowTooltip: true },
|
{ label: '结算员', prop: 'settlementMan', minWidth: 100, showOverflowTooltip: true },
|
||||||
|
|||||||
@@ -227,7 +227,7 @@ import {
|
|||||||
surchargeAppliesToRow,
|
surchargeAppliesToRow,
|
||||||
toDetailPayload
|
toDetailPayload
|
||||||
} from '../../utils/priceSet'
|
} from '../../utils/priceSet'
|
||||||
import { getPriceSet, listSetDetailByProduct, importSetDetailPricesAsync, pullSetDetailsFromLibraryAsync, previewPullFromLibrary, previewImportDetailPrices, updateSetDetail, updateSetDetailSurchargeAsync, delSetDetail } from '@/api/price/set'
|
import { getPriceSet, listSetDetailByProduct, listSetDetailByVersion, importSetDetailPricesAsync, pullSetDetailsFromLibraryAsync, previewPullFromLibrary, previewImportDetailPrices, updateSetDetail, updateSetDetailSurchargeAsync, delSetDetail } from '@/api/price/set'
|
||||||
import { listRegionOptions } from '@/api/data/region'
|
import { listRegionOptions } from '@/api/data/region'
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
@@ -437,12 +437,8 @@ async function loadLatestPriorVersionDraft() {
|
|||||||
return row
|
return row
|
||||||
})
|
})
|
||||||
if (!products.length) return false
|
if (!products.length) return false
|
||||||
const chunks = await Promise.all(products.map(p =>
|
const detailRes = await listSetDetailByVersion(prior.psvId)
|
||||||
listSetDetailByProduct(prior.psvId, p.productCode)
|
applyLocalDraft(products, detailRes.data || [])
|
||||||
.then(r => r.data || [])
|
|
||||||
.catch(() => [])
|
|
||||||
))
|
|
||||||
applyLocalDraft(products, chunks.flat())
|
|
||||||
return true
|
return true
|
||||||
} finally {
|
} finally {
|
||||||
pulling.value = false
|
pulling.value = false
|
||||||
|
|||||||
@@ -123,9 +123,21 @@ function toEffMs(v) {
|
|||||||
return Number.isNaN(t) ? NaN : t
|
return Number.isNaN(t) ? NaN : t
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sort by effective time descending; drafts without time last. */
|
/** draft / pending first, then effect, then expired; within group by effective time desc. */
|
||||||
function sortByEffectiveTime(list) {
|
function statusRank(v) {
|
||||||
|
const s = String(v && v.status != null ? v.status : '')
|
||||||
|
if (s === '0') return 0
|
||||||
|
if (s === '3') return 1
|
||||||
|
if (s === '1') return 2
|
||||||
|
if (s === '2') return 3
|
||||||
|
return 9
|
||||||
|
}
|
||||||
|
|
||||||
|
function sortVersions(list) {
|
||||||
return (list || []).slice().sort((a, b) => {
|
return (list || []).slice().sort((a, b) => {
|
||||||
|
const ra = statusRank(a)
|
||||||
|
const rb = statusRank(b)
|
||||||
|
if (ra !== rb) return ra - rb
|
||||||
const ta = toEffMs(a)
|
const ta = toEffMs(a)
|
||||||
const tb = toEffMs(b)
|
const tb = toEffMs(b)
|
||||||
const aNull = Number.isNaN(ta)
|
const aNull = Number.isNaN(ta)
|
||||||
@@ -143,7 +155,7 @@ const filteredVersions = computed(() => {
|
|||||||
const filtered = statusTab.value === 'all'
|
const filtered = statusTab.value === 'all'
|
||||||
? list
|
? list
|
||||||
: list.filter(v => String(v.status) === statusTab.value)
|
: list.filter(v => String(v.status) === statusTab.value)
|
||||||
return sortByEffectiveTime(filtered)
|
return sortVersions(filtered)
|
||||||
})
|
})
|
||||||
|
|
||||||
function detailCount(row) {
|
function detailCount(row) {
|
||||||
|
|||||||
Reference in New Issue
Block a user