修改产品价格显示
This commit is contained in:
@@ -2,9 +2,6 @@
|
||||
<el-drawer v-model="visible" size="920px" :title="title" append-to-body>
|
||||
<div class="mb8" style="display: flex; align-items: center; gap: 12px">
|
||||
<el-input v-model="keyword" placeholder="搜索国家(中文名 / ISO2)" clearable style="width: 260px" />
|
||||
<!-- <el-select v-model="status" placeholder="状态(全部)" clearable style="width: 160px">
|
||||
<el-option v-for="d in bms_product_effect_status" :key="d.value" :label="d.label" :value="d.value" />
|
||||
</el-select> -->
|
||||
</div>
|
||||
<simple-table
|
||||
:data="filteredList"
|
||||
@@ -29,8 +26,6 @@
|
||||
import SimpleTable from '@/components/SimpleTable'
|
||||
import { listProductCountries } from '@/api/price/product'
|
||||
|
||||
const { bms_product_effect_status } = useDict('bms_product_effect_status')
|
||||
|
||||
const columns = [
|
||||
{ prop: 'countryName', label: '国家', width: 90, showOverflowTooltip: true },
|
||||
{ prop: 'countryCode', label: 'ISO2', width: 60, align: 'center' },
|
||||
@@ -48,7 +43,7 @@ const columns = [
|
||||
{ prop: 'leadTime', label: '时效', width: 100, showOverflowTooltip: true },
|
||||
{ prop: 'effectiveDate', label: '生效日期', width: 110, align: 'center' },
|
||||
{ prop: 'expireDate', label: '失效日期', width: 110, align: 'center', formatter: (row) => row.expireDate || '长期' },
|
||||
{ prop: 'effectStatus', label: '状态', width: 90, align: 'center', dict: 'bms_product_effect_status' }
|
||||
{ prop: 'status', label: '状态', width: 90, align: 'center', dict: 'bms_product_effect_status' }
|
||||
]
|
||||
|
||||
const visible = ref(false)
|
||||
@@ -64,19 +59,24 @@ const filteredList = computed(() => {
|
||||
return list.value.filter(r => {
|
||||
if (kw && !(String(r.countryName || '').toLowerCase().includes(kw) ||
|
||||
String(r.countryCode || '').toLowerCase().includes(kw))) return false
|
||||
if (st && r.effectStatus !== st) return false
|
||||
if (st && String(r.status) !== String(st)) return false
|
||||
return true
|
||||
})
|
||||
})
|
||||
|
||||
function formatEffDate(v) {
|
||||
if (!v) return undefined
|
||||
return String(v).slice(0, 10)
|
||||
}
|
||||
|
||||
function open(row) {
|
||||
title.value = row.productCode + ' \u00b7 ' + row.productName + ' \u00b7 \u56fd\u5bb6\u670d\u52a1\u660e\u7ec6'
|
||||
title.value = row.productCode + ' · ' + row.productName + ' · 国家服务明细'
|
||||
visible.value = true
|
||||
loading.value = true
|
||||
list.value = []
|
||||
keyword.value = ''
|
||||
status.value = ''
|
||||
listProductCountries(row.productCode).then(res => {
|
||||
listProductCountries(row.productCode, formatEffDate(row.effectiveDate), row.productId).then(res => {
|
||||
list.value = (res.data || []).slice().sort((a, b) => {
|
||||
return String(a.countryCode || '').localeCompare(String(b.countryCode || ''))
|
||||
})
|
||||
|
||||
@@ -85,6 +85,15 @@ const schemas = computed(() => [
|
||||
component: 'date',
|
||||
placeholder: '选择日期',
|
||||
span: 12,
|
||||
width: '100%',
|
||||
rules: [{ required: true, message: '生效日期不能为空', trigger: 'change' }]
|
||||
},
|
||||
{
|
||||
label: '失效日期',
|
||||
prop: 'expireDate',
|
||||
component: 'date',
|
||||
placeholder: '选择日期',
|
||||
span: 12,
|
||||
width: '100%'
|
||||
},
|
||||
{
|
||||
@@ -116,6 +125,7 @@ function emptyForm() {
|
||||
updateNote: undefined,
|
||||
taxMode: 'TAX_INCLUDED',
|
||||
effectiveDate: undefined,
|
||||
expireDate: undefined,
|
||||
status: '0',
|
||||
remark: undefined
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ function open(row) {
|
||||
surchargePool.value = res.rows || []
|
||||
})
|
||||
if (row && row.productCode) {
|
||||
listProductCountries(row.productCode).then(res => {
|
||||
listProductCountries(row.productCode, undefined, row.productId).then(res => {
|
||||
countryList.value = res.data || []
|
||||
})
|
||||
}
|
||||
|
||||
@@ -5,14 +5,24 @@
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="mb16"
|
||||
title="Excel 导入:上传威狮B2C小包价表.xlsx。入库产品目录 + 各产品 sheet 的国家×重量段(运费/挂号费/尺寸/尾程/时效);不导入退件重派、申报说明、赔偿标准。"
|
||||
title="Excel 导入:相同产品代码+生效日期不覆盖;不同生效日期新增一条产品。同时入库国家×重量段(运费/挂号费/尺寸/尾程/时效)。"
|
||||
/>
|
||||
|
||||
<el-tabs v-model="effectTab" class="mb8" @tab-change="onTabChange">
|
||||
<el-tab-pane
|
||||
v-for="t in statusTabs"
|
||||
:key="t.name"
|
||||
:label="t.label"
|
||||
:name="t.name"
|
||||
/>
|
||||
</el-tabs>
|
||||
|
||||
<basic-table
|
||||
ref="tableRef"
|
||||
:columns="columns"
|
||||
:search-columns="searchColumns"
|
||||
:query="queryList"
|
||||
:extra-params="extraParams"
|
||||
row-key="productId"
|
||||
>
|
||||
<template #toolbar="{ selection, ids }">
|
||||
@@ -35,7 +45,7 @@
|
||||
</template>
|
||||
|
||||
<template #col-status="{ row }">
|
||||
<dict-tag :options="bms_product_effect_status" :value="resolveEffectStatus(row)" />
|
||||
<dict-tag :options="bms_product_effect_status" :value="row.status" />
|
||||
</template>
|
||||
|
||||
<template #col-action="{ row }">
|
||||
@@ -54,9 +64,7 @@
|
||||
title="产品 Excel 导入"
|
||||
action="/price/product/importData"
|
||||
width="560px"
|
||||
:default-update-support="true"
|
||||
update-support-label="是否更新已存在的产品主数据"
|
||||
update-support-hint="国家明细:新生效日晚于上次则保留历史,上次失效日=本次生效日"
|
||||
:show-update-support="false"
|
||||
@success="() => tableRef.refresh()"
|
||||
/>
|
||||
</div>
|
||||
@@ -78,6 +86,41 @@ const countryRef = ref()
|
||||
const surchargeRef = ref()
|
||||
const importRef = ref()
|
||||
|
||||
const TAB_ACTIVE = 'active'
|
||||
const TAB_PENDING = 'pending'
|
||||
const TAB_EXPIRED = 'expired'
|
||||
|
||||
const effectTab = ref(TAB_ACTIVE)
|
||||
|
||||
const statusTabs = computed(() => [
|
||||
{ name: TAB_ACTIVE, code: '1', label: dictLabel('1', 'ACTIVE') },
|
||||
{ name: TAB_PENDING, code: '0', label: dictLabel('0', 'PENDING') },
|
||||
{ name: TAB_EXPIRED, code: '2', label: dictLabel('2', 'EXPIRED') }
|
||||
])
|
||||
|
||||
const extraParams = computed(() => ({ status: tabToStatus(effectTab.value) }))
|
||||
|
||||
function dictLabel(code, legacy) {
|
||||
const list = bms_product_effect_status.value || []
|
||||
const hit = list.find(d => String(d.value) === code || String(d.value) === legacy)
|
||||
return hit?.label || code
|
||||
}
|
||||
|
||||
function tabToStatus(name) {
|
||||
if (name === TAB_ACTIVE || name === 'ACTIVE' || name === '1') return '1'
|
||||
if (name === TAB_PENDING || name === 'PENDING' || name === '0') return '0'
|
||||
if (name === TAB_EXPIRED || name === 'EXPIRED' || name === '2') return '2'
|
||||
return '1'
|
||||
}
|
||||
|
||||
function onTabChange(name) {
|
||||
effectTab.value = String(name || TAB_ACTIVE)
|
||||
nextTick(() => {
|
||||
tableRef.value?.clearSelection()
|
||||
tableRef.value?.reload()
|
||||
})
|
||||
}
|
||||
|
||||
const columns = [
|
||||
{ prop: 'productCode', label: '产品代码', minWidth: 110 },
|
||||
{ prop: 'productName', label: '产品名称', minWidth: 140, showOverflowTooltip: true },
|
||||
@@ -86,6 +129,7 @@ const columns = [
|
||||
{ prop: 'destRegion', label: '目的区域', width: 90, align: 'center' },
|
||||
{ prop: 'taxMode', label: '税模式', width: 90, align: 'center', dict: 'bms_tax_mode' },
|
||||
{ prop: 'effectiveDate', label: '生效日期', width: 120, align: 'center' },
|
||||
{ prop: 'expireDate', label: '失效日期', width: 120, align: 'center' },
|
||||
{ prop: 'countryCount', label: '国家数', width: 80, align: 'center' },
|
||||
{ prop: 'surchargeCount', label: '附加费数', width: 90, align: 'center' },
|
||||
{ prop: 'status', label: '状态', width: 90, align: 'center', slot: 'status' },
|
||||
@@ -103,35 +147,15 @@ const searchColumns = [
|
||||
dict: 'bms_tax_mode',
|
||||
placeholder: '税模式',
|
||||
clearable: true
|
||||
},
|
||||
{
|
||||
prop: 'effectStatus',
|
||||
label: '状态',
|
||||
component: 'select',
|
||||
dict: 'bms_product_effect_status',
|
||||
placeholder: '请选择状态',
|
||||
clearable: true
|
||||
}
|
||||
]
|
||||
|
||||
function queryList(params) {
|
||||
return listProduct(params)
|
||||
}
|
||||
|
||||
function todayStr() {
|
||||
return new Date().toISOString().slice(0, 10)
|
||||
}
|
||||
|
||||
/** ACTIVE已生效 / PENDING待生效 / EXPIRED已失效 */
|
||||
function resolveEffectStatus(row) {
|
||||
if (!row) return 'PENDING'
|
||||
if (row.status === '1') return 'EXPIRED'
|
||||
if (!row.effectiveDate) return 'PENDING'
|
||||
return String(row.effectiveDate).slice(0, 10) <= todayStr() ? 'ACTIVE' : 'PENDING'
|
||||
return listProduct({ ...params, status: tabToStatus(effectTab.value) })
|
||||
}
|
||||
|
||||
function isProductActive(row) {
|
||||
return resolveEffectStatus(row) === 'ACTIVE'
|
||||
return row && String(row.status) === '1'
|
||||
}
|
||||
|
||||
function handleAdd() {
|
||||
|
||||
@@ -95,7 +95,9 @@
|
||||
<el-descriptions-item label="套餐编号">{{ result.priceSetCode || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="套餐名称">{{ result.priceSetName || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="套餐类型">{{ result.setType || '-' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="币种">{{ result.currency || 'RMB' }}</el-descriptions-item>
|
||||
<el-descriptions-item label="币种">
|
||||
<dict-tag :options="bms_currency" :value="displayCurrency(result.currency)" />
|
||||
</el-descriptions-item>
|
||||
<el-descriptions-item label="运费单价">{{ formatMoney(result.freightRate) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="折扣前单价">{{ formatMoney(result.baseFreightRate) }}</el-descriptions-item>
|
||||
<el-descriptions-item label="折扣%">{{ result.discountPercent != null ? result.discountPercent : '-' }}</el-descriptions-item>
|
||||
@@ -130,7 +132,11 @@
|
||||
<span>{{ formatMoney(row.amount) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="币种" width="80" align="center" prop="currency" />
|
||||
<el-table-column label="币种" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :options="bms_currency" :value="displayCurrency(row.currency)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="取值方式" width="110" align="center">
|
||||
<template #default="{ row }">{{ roundModeLabel(row.roundMode) }}</template>
|
||||
</el-table-column>
|
||||
@@ -209,7 +215,11 @@
|
||||
<el-table-column label="金额" min-width="120" align="right">
|
||||
<template #default="{ row }">{{ formatMoney(row.amount) }}</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="币种" width="80" align="center" prop="currency" />
|
||||
<el-table-column label="币种" width="90" align="center">
|
||||
<template #default="{ row }">
|
||||
<dict-tag :options="bms_currency" :value="displayCurrency(row.currency)" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="说明" min-width="160" show-overflow-tooltip>
|
||||
<template #default="{ row }">{{ row.remark || '-' }}</template>
|
||||
</el-table-column>
|
||||
@@ -225,7 +235,7 @@ import { quoteBilling, listQuote, getQuote } from '@/api/price/billing'
|
||||
import { listProduct, listProductCountries } from '@/api/price/product'
|
||||
|
||||
const { proxy } = getCurrentInstance()
|
||||
const { bms_fee_type } = useDict('bms_fee_type')
|
||||
const { bms_fee_type, bms_currency } = useDict('bms_fee_type', 'bms_currency')
|
||||
const formRef = ref()
|
||||
const historyTableRef = ref()
|
||||
const loading = ref(false)
|
||||
@@ -411,6 +421,11 @@ function feeTypeLabel(type) {
|
||||
return found ? found.label : ''
|
||||
}
|
||||
|
||||
function displayCurrency(v) {
|
||||
if (!v || v === 'RMB' || v === 'rmb') return 'CNY'
|
||||
return v
|
||||
}
|
||||
|
||||
function displayFeeName(row) {
|
||||
const typeLabel = feeTypeLabel(row.feeType)
|
||||
const name = String(row.feeName || row.fee_name || '').trim()
|
||||
|
||||
@@ -219,7 +219,7 @@
|
||||
:closable="false"
|
||||
show-icon
|
||||
class="mb12"
|
||||
title="套餐创建后处于草稿状态,可暂不绑定客户。优先级数字越小越优先(1 = 最高)。同一客户可绑定多个套餐。"
|
||||
title="套餐创建后处于草稿状态,可暂不绑定客户。一个客户只能绑定一个套餐。"
|
||||
/>
|
||||
<el-table :data="form.customers" border empty-text="暂未绑定客户">
|
||||
<el-table-column label="客户ID" min-width="120">
|
||||
@@ -597,6 +597,11 @@ function saveAndSubmit() {
|
||||
}
|
||||
|
||||
function doSave(submit) {
|
||||
const ids = (form.customers || []).filter(c => c.customerId).map(c => String(c.customerId))
|
||||
if (new Set(ids).size !== ids.length) {
|
||||
proxy.$modal.msgError('该客户已绑定套餐,一个客户只能绑定一个套餐')
|
||||
return
|
||||
}
|
||||
saving.value = true
|
||||
savePriceSet(buildPayload(submit)).then(res => {
|
||||
form.priceSetId = res.data
|
||||
|
||||
@@ -158,7 +158,7 @@
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div class="rel-hint">优先级数字越小越优先;同一客户绑定多个套餐时,按优先级 → 生效日期依次命中。</div>
|
||||
<div class="rel-hint">一个客户只能绑定一个套餐;解绑后可绑定其他套餐。</div>
|
||||
</el-card>
|
||||
|
||||
<el-dialog :title="detailTitle" v-model="detailOpen" width="560px" append-to-body>
|
||||
|
||||
Reference in New Issue
Block a user