diff --git a/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/PriceLogController.java b/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/PriceLogController.java index 5f20894b..b3e3a765 100644 --- a/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/PriceLogController.java +++ b/bms-back/bms-admin/src/main/java/com/bms/web/controller/monitor/PriceLogController.java @@ -37,13 +37,14 @@ public class PriceLogController extends BaseController @RequestParam(value = "priceKind", required = false) String priceKind, @RequestParam(value = "productCode", required = false) String productCode, @RequestParam(value = "updateTime", required = false) String updateTime, - @RequestParam(value = "updateTimePrefix", required = false) String updateTimePrefix) + @RequestParam(value = "updateTimePrefix", required = false) String updateTimePrefix, + @RequestParam(value = "countryKeyword", required = false) String countryKeyword) { PageDomain pageDomain = TableSupport.buildPageRequest(); int pageNum = pageDomain.getPageNum() == null ? 1 : pageDomain.getPageNum().intValue(); int pageSize = pageDomain.getPageSize() == null ? 10 : pageDomain.getPageSize().intValue(); BillSearchPage page = billSearchStore.search(EsLogType.PRICE_CHANGE, bizId, status, psvId, priceKind, - productCode, updateTime, updateTimePrefix, pageNum, pageSize); + productCode, updateTime, updateTimePrefix, countryKeyword, pageNum, pageSize); TableDataInfo rsp = new TableDataInfo(); rsp.setCode(HttpStatus.SUCCESS); rsp.setMsg("查询成功"); diff --git a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/impl/BmsCustomerLogServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/impl/BmsCustomerLogServiceImpl.java index fbc69aae..22a501a9 100644 --- a/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/impl/BmsCustomerLogServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/customer/customerinfo/service/impl/BmsCustomerLogServiceImpl.java @@ -450,6 +450,11 @@ public class BmsCustomerLogServiceImpl implements IBmsCustomerLogService realChanges.add(c); } } + // Rebind/update with no field diff: skip empty UPDATE noise (full package save upsert) + if (existing != null && realChanges.isEmpty()) + { + return; + } saveLog(bind.getCustomerId(), customer == null ? null : customer.getCustomerCode(), customer == null ? null : customer.getCustomerName(), BmsCustomerLog.MODULE_PRICE_SET, newSet.getPriceSetName(), diff --git a/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcPriceSetDetailMapper.java b/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcPriceSetDetailMapper.java index 38b8bfb0..a63c77c1 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcPriceSetDetailMapper.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/mapper/PrcPriceSetDetailMapper.java @@ -44,6 +44,9 @@ public interface PrcPriceSetDetailMapper public int countByPsvId(Long psvId); + /** Count detail rows including soft-deleted (for deleted-version tab). */ + public int countByPsvIdAll(Long psvId); + public int copyDetailsFromVersion(@Param("srcPsvId") Long srcPsvId, @Param("newPsvId") Long newPsvId); /** Copy version effective time, expire time and status onto catalog detail rows. */ diff --git a/bms-back/bms-system/src/main/java/com/bms/price/search/EsBillSearchStore.java b/bms-back/bms-system/src/main/java/com/bms/price/search/EsBillSearchStore.java index 85338de6..1259609e 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/search/EsBillSearchStore.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/search/EsBillSearchStore.java @@ -173,6 +173,15 @@ public class EsBillSearchStore implements IBillSearchStore @Override public BillSearchPage search(String logType, String bizId, String status, Long psvId, String priceKind, String productCode, String updateTime, String updateTimePrefix, int pageNum, int pageSize) + { + return search(logType, bizId, status, psvId, priceKind, productCode, updateTime, updateTimePrefix, + null, pageNum, pageSize); + } + + @Override + public BillSearchPage search(String logType, String bizId, String status, Long psvId, String priceKind, + String productCode, String updateTime, String updateTimePrefix, String countryKeyword, + int pageNum, int pageSize) { BillSearchPage page = new BillSearchPage(); if (pageNum < 1) @@ -197,7 +206,7 @@ public class EsBillSearchStore implements IBillSearchStore sort.add(sortItem); body.put("sort", sort); body.put("query", buildQuery(logType, bizId, status, psvId, priceKind, productCode, updateTime, - updateTimePrefix)); + updateTimePrefix, countryKeyword)); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_JSON); HttpEntity entity = new HttpEntity(body.toJSONString(), headers); @@ -378,7 +387,7 @@ public class EsBillSearchStore implements IBillSearchStore } private JSONObject buildQuery(String logType, String bizId, String status, Long psvId, String priceKind, - String productCode, String updateTime, String updateTimePrefix) + String productCode, String updateTime, String updateTimePrefix, String countryKeyword) { JSONArray filters = new JSONArray(); addTerm(filters, "logType", logType); @@ -387,6 +396,7 @@ public class EsBillSearchStore implements IBillSearchStore addPsvIdFilter(filters, psvId); addTerm(filters, "request.priceKind", priceKind); addProductCodeFilter(filters, productCode); + addCountryKeywordFilter(filters, countryKeyword); addUpdateTimeFilter(filters, updateTime); addUpdateTimePrefixFilter(filters, updateTimePrefix); if (filters.isEmpty()) @@ -430,6 +440,65 @@ public class EsBillSearchStore implements IBillSearchStore filters.add(boolWrap); } + /** Match country code / name (exact or contains). */ + private void addCountryKeywordFilter(JSONArray filters, String countryKeyword) + { + if (StringUtils.isEmpty(countryKeyword)) + { + return; + } + String kw = countryKeyword.trim(); + String wild = "*" + escapeWildcard(kw) + "*"; + JSONArray should = new JSONArray(); + addShouldTerm(should, "request.bizKeys.countryCode.keyword", kw); + addShouldTerm(should, "request.bizKeys.countryCode", kw); + addShouldWildcard(should, "request.bizKeys.countryCode.keyword", wild); + addShouldWildcard(should, "request.bizKeys.countryCode", wild); + addShouldWildcard(should, "request.bizKeys.countryName.keyword", wild); + addShouldWildcard(should, "request.bizKeys.countryName", wild); + JSONObject matchName = new JSONObject(); + JSONObject matchField = new JSONObject(); + matchField.put("query", kw); + matchName.put("request.bizKeys.countryName", matchField); + JSONObject matchWrap = new JSONObject(); + matchWrap.put("match", matchName); + should.add(matchWrap); + + JSONObject inner = new JSONObject(); + inner.put("should", should); + inner.put("minimum_should_match", Integer.valueOf(1)); + JSONObject boolWrap = new JSONObject(); + boolWrap.put("bool", inner); + filters.add(boolWrap); + } + + private void addShouldTerm(JSONArray should, String field, String value) + { + JSONObject term = new JSONObject(); + term.put(field, value); + JSONObject wrap = new JSONObject(); + wrap.put("term", term); + should.add(wrap); + } + + private void addShouldWildcard(JSONArray should, String field, String value) + { + JSONObject wild = new JSONObject(); + wild.put(field, value); + JSONObject wrap = new JSONObject(); + wrap.put("wildcard", wild); + should.add(wrap); + } + + private static String escapeWildcard(String raw) + { + if (raw == null) + { + return ""; + } + return raw.replace("\\", "\\\\").replace("*", "\\*").replace("?", "\\?"); + } + private void addUpdateTimeFilter(JSONArray filters, String updateTime) { if (StringUtils.isEmpty(updateTime)) diff --git a/bms-back/bms-system/src/main/java/com/bms/price/search/IBillSearchStore.java b/bms-back/bms-system/src/main/java/com/bms/price/search/IBillSearchStore.java index e5294582..155e17bc 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/search/IBillSearchStore.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/search/IBillSearchStore.java @@ -38,6 +38,17 @@ public interface IBillSearchStore default BillSearchPage search(String logType, String bizId, String status, Long psvId, String priceKind, String productCode, String updateTime, String updateTimePrefix, int pageNum, int pageSize) + { + return search(logType, bizId, status, psvId, priceKind, productCode, updateTime, updateTimePrefix, + null, pageNum, pageSize); + } + + /** + * Search with optional countryKeyword (matches bizKeys.countryCode / countryName). + */ + default BillSearchPage search(String logType, String bizId, String status, Long psvId, String priceKind, + String productCode, String updateTime, String updateTimePrefix, String countryKeyword, + int pageNum, int pageSize) { return search(logType, bizId, status, pageNum, pageSize); } diff --git a/bms-back/bms-system/src/main/java/com/bms/price/search/PriceChangeEsLog.java b/bms-back/bms-system/src/main/java/com/bms/price/search/PriceChangeEsLog.java index b363a165..744b7b77 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/search/PriceChangeEsLog.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/search/PriceChangeEsLog.java @@ -152,11 +152,31 @@ public final class PriceChangeEsLog keys.put("countryCode", d.getCountryCode()); keys.put("countryName", d.getCountryName()); keys.put("zoneCode", d.getZoneCode()); + keys.put("zoneName", d.getZoneName()); keys.put("weightMin", d.getWeightMin()); keys.put("weightMax", d.getWeightMax()); + keys.put("weightLabel", weightBandOf(d)); return keys; } + /** Display weight band for sales detail logs (e.g. 0<W≤0.5). */ + public static String weightBandOf(PrcPriceSetDetail d) + { + if (d == null) + { + return ""; + } + if (StringUtils.isNotEmpty(d.getWeightLabel())) + { + return d.getWeightLabel(); + } + if (d.getWeightMin() == null && d.getWeightMax() == null) + { + return ""; + } + return stringify(d.getWeightMin()) + " bizKeys, List> changes) { diff --git a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcPriceSetServiceImpl.java b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcPriceSetServiceImpl.java index e5d908c9..6c05e563 100644 --- a/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcPriceSetServiceImpl.java +++ b/bms-back/bms-system/src/main/java/com/bms/price/service/impl/PrcPriceSetServiceImpl.java @@ -53,6 +53,11 @@ import com.bms.price.search.PriceChangeEsLog; import com.bms.price.service.IPrcPriceExcelFileService; import com.bms.price.service.IPrcPriceSetService; import com.bms.price.task.PrcPriceSetSaveAsyncRunner; +import com.bms.customer.customerinfo.domain.BmsCustomer; +import com.bms.customer.customerinfo.domain.BmsCustomerPriceSet; +import com.bms.customer.customerinfo.domain.BmsPriceSetOption; +import com.bms.customer.customerinfo.service.IBmsCustomerLogService; +import com.bms.customer.customerinfo.service.IBmsCustomerService; /** * 价格套餐 服务层实现 @@ -130,6 +135,12 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService @Autowired private IBillSearchStore billSearchStore; + @Autowired + private IBmsCustomerLogService customerLogService; + + @Autowired + private IBmsCustomerService bmsCustomerService; + @Override public PrcPriceSet selectPrcPriceSetById(Long priceSetId) { @@ -2511,7 +2522,12 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService } try { - return customerMapper.insertPrcCustomerPriceSet(customer); + int rows = customerMapper.insertPrcCustomerPriceSet(customer); + if (rows > 0) + { + logCustomerPriceSetBind(null, customer, db); + } + return rows; } catch (Exception e) { @@ -2610,6 +2626,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService } validateCustomer(row, db); customerMapper.updatePrcCustomerPriceSet(row); + logCustomerPriceSetBind(existing, row, db); replaced++; } else @@ -2630,6 +2647,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService } throw e; } + logCustomerPriceSetBind(null, row, db); inserted++; } } @@ -2657,12 +2675,30 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService assertChildEditable(db); customer.setPriceSetId(old.getPriceSetId()); validateCustomer(customer, db); - return customerMapper.updatePrcCustomerPriceSet(customer); + int rows = customerMapper.updatePrcCustomerPriceSet(customer); + if (rows > 0) + { + if (customer.getCustomerId() == null) + { + customer.setCustomerId(old.getCustomerId()); + } + if (StringUtils.isEmpty(customer.getCustomerCode())) + { + customer.setCustomerCode(old.getCustomerCode()); + } + if (StringUtils.isEmpty(customer.getCustomerName())) + { + customer.setCustomerName(old.getCustomerName()); + } + logCustomerPriceSetBind(old, customer, db); + } + return rows; } @Override public int deleteCustomerByIds(Long[] customerPricesetIds) { + List snapshots = new ArrayList(); for (Long id : customerPricesetIds) { PrcCustomerPriceSet old = customerMapper.selectPrcCustomerPriceSetById(id); @@ -2675,8 +2711,17 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService { throw new ServiceException(MessageUtils.message("price.set.customer.unbindAudit")); } + snapshots.add(old); } - return customerMapper.deletePrcCustomerPriceSetByIds(customerPricesetIds); + int rows = customerMapper.deletePrcCustomerPriceSetByIds(customerPricesetIds); + if (rows > 0) + { + for (PrcCustomerPriceSet snapshot : snapshots) + { + logCustomerPriceSetUnbind(snapshot); + } + } + return rows; } private void replaceChildren(PrcPriceSet set) @@ -2747,6 +2792,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService c.setUpdateBy(set.getUpdateBy()); customerMapper.updatePrcCustomerPriceSet(c); keepIds.add(hit.getCustomerPricesetId()); + logCustomerPriceSetBind(hit, c, set); } else { @@ -2757,6 +2803,7 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService { keepIds.add(c.getCustomerPricesetId()); } + logCustomerPriceSetBind(null, c, set); } } catch (Exception e) @@ -2778,10 +2825,99 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService } if (!orphanIds.isEmpty()) { + for (Long orphanId : orphanIds) + { + PrcCustomerPriceSet snapshot = byId.get(orphanId); + if (snapshot != null) + { + logCustomerPriceSetUnbind(snapshot); + } + } customerMapper.deletePrcCustomerPriceSetByIds(orphanIds.toArray(new Long[0])); } } + /** Write customer biz log for package bind / rebind (visible in customer info Logs). */ + private void logCustomerPriceSetBind(PrcCustomerPriceSet existing, PrcCustomerPriceSet bind, PrcPriceSet set) + { + if (customerLogService == null || bind == null || set == null) + { + return; + } + BmsCustomer customer = resolveCustomerForLog(bind); + if (customer == null && bind.getCustomerId() != null) + { + customer = new BmsCustomer(); + customer.setCustomerId(bind.getCustomerId()); + customer.setCustomerCode(bind.getCustomerCode()); + customer.setCustomerName(bind.getCustomerName()); + } + BmsCustomerPriceSet existingLog = toBmsCustomerPriceSet(existing, resolvePriceSetName(existing)); + BmsCustomerPriceSet bindLog = toBmsCustomerPriceSet(bind, set.getPriceSetName()); + if (bindLog.getCustomerId() == null && customer != null) + { + bindLog.setCustomerId(customer.getCustomerId()); + } + BmsPriceSetOption option = new BmsPriceSetOption(); + option.setPriceSetId(set.getPriceSetId()); + option.setPriceSetCode(set.getPriceSetCode()); + option.setPriceSetName(set.getPriceSetName()); + customerLogService.recordPriceSetBind(customer, existingLog, bindLog, option); + } + + private void logCustomerPriceSetUnbind(PrcCustomerPriceSet bind) + { + if (customerLogService == null || bind == null) + { + return; + } + BmsCustomerPriceSet snapshot = toBmsCustomerPriceSet(bind, resolvePriceSetName(bind)); + customerLogService.recordPriceSetUnbind(snapshot); + } + + private BmsCustomer resolveCustomerForLog(PrcCustomerPriceSet bind) + { + if (bind == null || bmsCustomerService == null) + { + return null; + } + if (bind.getCustomerId() != null) + { + return bmsCustomerService.selectBmsCustomerByCustomerId(bind.getCustomerId()); + } + return null; + } + + private String resolvePriceSetName(PrcCustomerPriceSet bind) + { + if (bind == null || bind.getPriceSetId() == null) + { + return null; + } + PrcPriceSet set = setMapper.selectPrcPriceSetById(bind.getPriceSetId()); + return set == null ? null : set.getPriceSetName(); + } + + private BmsCustomerPriceSet toBmsCustomerPriceSet(PrcCustomerPriceSet src, String priceSetName) + { + if (src == null) + { + return null; + } + BmsCustomerPriceSet dest = new BmsCustomerPriceSet(); + dest.setCustomerPricesetId(src.getCustomerPricesetId()); + dest.setPriceSetId(src.getPriceSetId()); + dest.setCustomerId(src.getCustomerId()); + dest.setCustomerCode(src.getCustomerCode()); + dest.setCustomerName(src.getCustomerName()); + dest.setBindPriority(src.getBindPriority()); + dest.setPrBegindate(src.getPrBegindate()); + dest.setPrEnddate(src.getPrEnddate()); + dest.setPriceSetNote(src.getPriceSetNote()); + dest.setPriceSetName(priceSetName); + return dest; + } + private void reportSaveProgress(PrcPriceSet set, int percent, String message) { if (set == null || StringUtils.isEmpty(set.getSaveTaskId()) || saveAsyncRunner == null) @@ -3482,6 +3618,22 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService { fillVersionChildren(version); } + // Soft-deleted EFFECT versions for the "deleted" tab (status may still be EFFECT) + PrcPriceSetVersion dq = new PrcPriceSetVersion(); + dq.setPriceSetId(priceSetId); + dq.setPriceType(com.bms.price.domain.PriceType.SALES); + dq.setIsDel("1"); + List deleted = versionMapper.selectPrcPriceSetVersionList(dq); + if (deleted != null) + { + for (PrcPriceSetVersion version : deleted) + { + version.setProducts(new ArrayList()); + version.setDetails(new ArrayList()); + version.setDetailCount(Integer.valueOf(detailMapper.countByPsvIdAll(version.getPsvId()))); + versions.add(version); + } + } set.setVersions(versions); PrcPriceSetVersion current = pickCurrentVersion(versions); set.setVersion(current); @@ -3508,14 +3660,23 @@ public class PrcPriceSetServiceImpl implements IPrcPriceSetService { return null; } + PrcPriceSetVersion firstAlive = null; for (PrcPriceSetVersion v : versions) { + if (v == null || "1".equals(v.getIsDel())) + { + continue; + } + if (firstAlive == null) + { + firstAlive = v; + } if (VER_EFFECT.equals(v.getStatus())) { return v; } } - return versions.get(0); + return firstAlive; } private void saveOrUpdateVersion(PrcPriceSet set) diff --git a/bms-back/bms-system/src/main/resources/mapper/price/PrcPriceSetDetailMapper.xml b/bms-back/bms-system/src/main/resources/mapper/price/PrcPriceSetDetailMapper.xml index ca58274a..2726b699 100644 --- a/bms-back/bms-system/src/main/resources/mapper/price/PrcPriceSetDetailMapper.xml +++ b/bms-back/bms-system/src/main/resources/mapper/price/PrcPriceSetDetailMapper.xml @@ -158,6 +158,10 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" select count(1) from prc_price_set_detail where psv_id = #{psvId} and ifnull(is_del, '0') = '0' + + - and ifnull(is_del, '0') = '0' + + + and ifnull(is_del, '0') = #{isDel} + + + and ifnull(is_del, '0') = '0' + + AND price_set_id = #{priceSetId} diff --git a/bms-front/src/views/price/set/components/detail/SetVersionPriceLogDrawer.vue b/bms-front/src/views/price/set/components/detail/SetVersionPriceLogDrawer.vue index fb6c2970..c082b89c 100644 --- a/bms-front/src/views/price/set/components/detail/SetVersionPriceLogDrawer.vue +++ b/bms-front/src/views/price/set/components/detail/SetVersionPriceLogDrawer.vue @@ -9,9 +9,13 @@ >
- - - + 查询 重置
@@ -36,11 +40,6 @@ - - -
- +
- +
+ + 查询 + 重置 +
+ + + + + + + - + - - - - - + + @@ -32,9 +32,12 @@ + + + @@ -49,27 +52,27 @@ @click="emit('view-price-log', row)" >变更记录 编辑 启动 修改生效时间 (props.versions || []).filter(v => !isDeletedVersion(v))) +const deletedVersions = computed(() => (props.versions || []).filter(v => isDeletedVersion(v))) + const counts = computed(() => { - const map = { all: 0, '0': 0, '3': 0, '1': 0, '2': 0 } - ;(props.versions || []).forEach(v => { + const map = { all: 0, pending: 0, '1': 0, '2': 0, del: 0 } + activeVersions.value.forEach(v => { map.all++ const s = String(v.status == null ? '' : v.status) - if (map[s] != null) map[s]++ + if (s === '0' || s === '3') map.pending++ + else if (map[s] != null) map[s]++ }) + map.del = deletedVersions.value.length return map }) function tabLabel(key) { const labels = { all: '全部', - '0': '草稿', - '3': '待生效', + pending: '待生效', '1': '已生效', - '2': '已失效' + '2': '已失效', + del: '已删除' } return labels[key] + ' (' + (counts.value[key] || 0) + ')' } -const hasDraft = computed(() => (props.versions || []).some(v => isDraftVersion(v))) +const hasDraft = computed(() => activeVersions.value.some(v => isDraftVersion(v))) function toEffMs(v) { if (!v || !v.effectiveTime) return NaN @@ -166,10 +184,21 @@ function sortVersions(list) { } const filteredVersions = computed(() => { - const list = props.versions || [] - const filtered = statusTab.value === 'all' - ? list - : list.filter(v => String(v.status) === statusTab.value) + if (statusTab.value === 'del') { + return sortVersions(deletedVersions.value) + } + const list = activeVersions.value + let filtered + if (statusTab.value === 'all') { + filtered = list + } else if (statusTab.value === 'pending') { + filtered = list.filter(v => { + const s = String(v.status) + return s === '0' || s === '3' + }) + } else { + filtered = list.filter(v => String(v.status) === statusTab.value) + } return sortVersions(filtered) }) diff --git a/bms-front/src/views/price/set/detail.vue b/bms-front/src/views/price/set/detail.vue index f286563c..d6856f38 100644 --- a/bms-front/src/views/price/set/detail.vue +++ b/bms-front/src/views/price/set/detail.vue @@ -299,6 +299,7 @@ function findPrevVersionEffectiveTime(row) { let prev = null for (const v of versions) { if (!v || v.psvId == null || String(v.psvId) === String(row.psvId)) continue + if (String(v.isDel) === '1') continue const vs = Number(v.versionSeq) || 0 if (vs >= curSeq || !v.effectiveTime) continue if (!prev || vs > (Number(prev.versionSeq) || 0)) prev = v @@ -312,6 +313,7 @@ function collectActivateBoundaryTimes(excludePsvId) { const seen = new Set() for (const v of set.value.versions || []) { if (!v || v.psvId == null || String(v.psvId) === String(excludePsvId)) continue + if (String(v.isDel) === '1') continue ;[v.effectiveTime, v.expireTime].forEach(t => { const n = t ? normalizeToHour(t) : '' if (!n || seen.has(n)) return @@ -449,7 +451,7 @@ function submitActivate() { function onCreateVersion() { const priceSetId = set.value.priceSetId if (priceSetId == null) return - const hasDraft = (set.value.versions || []).some(v => v && String(v.status) === '0') + const hasDraft = (set.value.versions || []).some(v => v && String(v.isDel) !== '1' && String(v.status) === '0') if (hasDraft) { proxy.$modal.msgWarning('已有草稿版本,请先启动或删除后再新建') return