Files
BMS/bms-front/src/views/price/label/components/LabelVersionProductDrawer.vue
T
2026-11-10 16:21:07 +08:00

178 lines
6.2 KiB
Vue

<template>
<el-drawer
:model-value="visible"
:title="title"
size="78%"
destroy-on-close
append-to-body
@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>
</div>
<el-table
v-loading="loading"
:data="filteredRows"
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">
<template #default="{ row }">{{ termText(row) }}</template>
</el-table-column>
<el-table-column label="状态" 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">
<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>
</template>
</el-table-column>
</el-table>
<el-drawer v-model="detailVisible" :title="detailTitle" size="78%" destroy-on-close append-to-body>
<pay-config-detail v-loading="detailLoading" :product="detail" :editable="false" />
<template #footer>
<el-button @click="detailVisible = false">关闭</el-button>
</template>
</el-drawer>
</el-drawer>
</template>
<script setup>
import { listLabelProducts, getLabelProduct, removeLabelProducts } from '@/api/price/label'
import PayConfigDetail from '@/views/price/basic/pay/components/PayConfigDetail.vue'
const props = defineProps({
visible: { type: Boolean, default: false },
priceSetId: { type: [Number, String], default: null },
version: { type: Object, default: null }
})
const emit = defineEmits(['update:visible', 'changed'])
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 title = computed(() => {
const v = props.version || {}
const label = v.versionLabel || (v.versionNo != null ? `V${v.versionNo}` : '')
return label ? `版本明细 · ${label}` : '版本明细'
})
const detailTitle = computed(() => {
if (!detail.value) return '产品明细'
const no = detail.value.versionNo ? `第 ${detail.value.versionNo} 版` : ''
return `${detail.value.productName || '产品'} ${no}`.trim()
})
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()
return text.includes(kw)
})
})
function formatHour(val) {
if (!val) return ''
const text = String(val).replace('T', ' ')
if (text.length >= 16) return text.slice(0, 13) + ':00'
if (text.length >= 10) return text.slice(0, 10) + ' 00:00'
return text
}
function termText(row) {
const start = formatHour(row.termStart || row.effectiveDate || '')
const end = row.termEnd ? formatHour(row.termEnd) : '不限'
if (!start) return '未设置'
return start + ' ~ ' + end
}
function termStatusText(status) {
const map = { '0': '待生效', '1': '生效', '2': '已失效' }
return map[String(status)] || '-'
}
function termStatusTag(status) {
const map = { '0': 'warning', '1': 'success', '2': 'danger' }
return map[String(status)] || 'info'
}
function onSelect(selection) {
selectedIds.value = (selection || []).map(item => item.productId).filter(Boolean)
}
async function load() {
if (!props.priceSetId || props.version?.versionNo == null) {
rows.value = []
return
}
loading.value = true
try {
const res = await listLabelProducts(props.priceSetId, props.version.versionNo)
rows.value = res.data || []
} finally {
loading.value = false
}
}
async function openProduct(row) {
detailVisible.value = true
detailLoading.value = true
detail.value = null
try {
const res = await getLabelProduct(row.productId, row.termId)
detail.value = res.data || null
} finally {
detailLoading.value = false
}
}
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(() => {})
}
watch(() => [props.visible, props.priceSetId, props.version?.versionNo], ([vis]) => {
if (vis) load()
}, { immediate: true })
</script>
<style scoped>
.toolbar {
display: flex;
gap: 12px;
margin-bottom: 12px;
align-items: center;
}
</style>