修改基础价格版本功能

This commit is contained in:
wuweihua
2026-09-28 15:45:07 +08:00
parent 1083c2876f
commit 32ab61b51c
22 changed files with 831 additions and 132 deletions
+8
View File
@@ -63,3 +63,11 @@ export function delProduct(productIds) {
method: 'delete'
})
}
/** List base-price version options (by effective_date desc) for package create */
export function listProductPriceVersions() {
return request({
url: '/price/product/priceVersions',
method: 'get'
})
}
@@ -95,6 +95,7 @@ import { formatWeightLabel } from '@/views/price/set/utils/priceSet'
const { proxy } = getCurrentInstance()
const columns = [
{ prop: 'versionNo', label: '版本', width: 70, align: 'center', formatter: (row) => row.versionNo || '-' },
{ prop: 'countryName', label: '国家', width: 120, showOverflowTooltip: true },
// { prop: 'countryCode', label: 'ISO2', width: 60, align: 'center' },
{ prop: 'zoneName', label: '分区名称', width: 140, showOverflowTooltip: true, formatter: (row) => row.zoneName || '-' },
@@ -116,12 +116,13 @@ const regionOptions = ref([])
const countryImportQuery = computed(() => ({ countryCode: importCountryCode.value }))
const allImportDesc = [
'适用多国家价表(B2C 小包价表等),按目录 sheet 匹配国家导入。',
'生效日期必填。新版导入时上一版失效日=本次生效日,复制上一版后按国家/分区/重量段匹配:命中更新,未命中插入。',
'请在弹窗底部下载模板,按模板格式整理后上传。相同产品代码+生效日期不覆盖主数据。'
]
const countryImportDesc = [
'选择目的国家后上传专线成本价表,目录中的产品都会记到该国家。',
'邮编、赔偿标准等 sheet 不导入。相同产品代码+生效日期不覆盖主数据,重量段按生效日写入。',
'可在弹窗底部下载模板,按模板格式整理后上传。'
'生效日期必填。新版会复制上一版全部国家明细再与导入行匹配更新/插入;其他国家行会转结到新版。',
'邮编、赔偿标准等 sheet 不导入。可在弹窗底部下载模板。'
]
const columns = [
@@ -7,6 +7,25 @@
<div class="form-hint">显示给客户的套餐对外名称</div>
</el-form-item>
<el-form-item label="基础价格版本" prop="baseVersionNo">
<el-select
v-model="basic.baseVersionNo"
filterable
clearable
placeholder="请选择基础价格版本"
style="width: 100%"
:loading="versionLoading"
>
<el-option
v-for="(item, idx) in versionOptions"
:key="item.versionNo"
:label="versionLabel(item, idx === 0)"
:value="item.versionNo"
/>
</el-select>
<div class="form-hint">创建套餐价格时按此版本从产品库拉取明细;默认最新版本</div>
</el-form-item>
<el-form-item label="计价类型" prop="setType">
<div class="type-row">
<div
@@ -50,19 +69,41 @@
<script setup name="StepBasicInfo">
/**
* 第 1 步 · 基本信息
* 直接读写父级传入的 basic 对象(同一引用),校验规则由本组件维护。
* Step1 basic info. baseVersionNo is pull-only (not persisted).
*/
import { listProductPriceVersions } from '@/api/price/product'
const basic = defineModel({ type: Object, required: true })
const formRef = ref()
const versionLoading = ref(false)
const versionOptions = ref([])
const rules = {
priceSetName: [{ required: true, message: '套餐名称不能为空', trigger: 'blur' }],
baseVersionNo: [{ required: true, message: '请选择基础价格版本', trigger: 'change' }],
setType: [{ required: true, message: '请选择计价类型', trigger: 'change' }],
}
/** 供父级在下一步 / 保存前调用 */
function versionLabel(item, isLatest) {
const no = item.versionNo || '-'
return no
}
async function loadVersions() {
versionLoading.value = true
try {
const res = await listProductPriceVersions()
const list = res.data || []
versionOptions.value = list
if (!basic.value.baseVersionNo && list.length) {
basic.value.baseVersionNo = list[0].versionNo
}
} finally {
versionLoading.value = false
}
}
function validate() {
return new Promise(resolve => {
if (!formRef.value) return resolve(false)
@@ -70,46 +111,20 @@ function validate() {
})
}
onMounted(() => {
loadVersions()
})
defineExpose({ validate })
</script>
<style scoped>
.max-form {
max-width: 760px;
}
.form-hint {
font-size: 12px;
color: #909399;
line-height: 1.4;
margin-top: 4px;
}
.unit {
margin-left: 8px;
color: #909399;
}
.type-row {
display: flex;
gap: 12px;
width: 100%;
}
.type-card {
flex: 1;
border: 1px solid #d9d9d9;
border-radius: 6px;
padding: 14px 16px;
cursor: pointer;
}
.type-card.selected {
border-color: #1890ff;
background: #e6f7ff;
}
.t-title {
font-weight: 600;
margin-bottom: 4px;
}
.t-desc {
font-size: 12px;
color: #909399;
line-height: 1.5;
}
.max-form { max-width: 760px; }
.form-hint { font-size: 12px; color: #909399; line-height: 1.4; margin-top: 4px; }
.unit { margin-left: 8px; color: #909399; }
.type-row { display: flex; gap: 12px; width: 100%; }
.type-card { flex: 1; border: 1px solid #d9d9d9; border-radius: 6px; padding: 14px 16px; cursor: pointer; }
.type-card.selected { border-color: #1890ff; background: #e6f7ff; }
.t-title { font-weight: 600; margin-bottom: 4px; }
.t-desc { font-size: 12px; color: #909399; line-height: 1.5; }
</style>
+1
View File
@@ -220,6 +220,7 @@ function buildPayload() {
setType: basic.setType,
defaultDiscount: basic.setType === 'DISCOUNT' ? basic.defaultDiscount : undefined,
priceSetNote: basic.priceSetNote,
baseVersionNo: basic.baseVersionNo || undefined,
version: {
psvId: copyMode.value ? undefined : version.psvId,
versionNo: version.versionNo
@@ -361,6 +361,7 @@ export function createEmptyBasicInfo() {
defaultDiscount: 88,
effectiveDate: undefined,
expireDate: undefined,
baseVersionNo: undefined,
priceSetNote: ''
}
}