Files
BMS/bms-front/src/views/price/basic/components/CatalogVersionTable.vue
T
2026-11-02 09:00:38 +08:00

208 lines
6.3 KiB
Vue

<template>
<div class="catalog-ver">
<div class="ver-head">
<div class="ver-title">
<i class="ver-bar" />
<span class="ver-text">{{ title }}</span>
<el-tag size="small" type="info" effect="plain" round>{{ filteredVersions.length }}</el-tag>
</div>
<el-button
type="primary"
plain
size="small"
:disabled="hasDraft"
v-hasPermi="[createPerm]"
@click="emit('create')"
>{{ createLabel }}</el-button>
</div>
<el-tabs v-model="statusTab" class="ver-tabs">
<el-tab-pane :label="tabLabel('all')" name="all" />
<el-tab-pane :label="tabLabel('pending')" name="pending" />
<el-tab-pane :label="tabLabel('1')" name="1" />
<el-tab-pane :label="tabLabel('2')" name="2" />
</el-tabs>
<el-table v-loading="loading" :data="filteredVersions" border :empty-text="emptyText" @row-click="onRowClick">
<el-table-column :label="colNo" width="120">
<template #default="{ row }">
<el-button link type="primary" @click.stop="emit('view-products', row)">{{ row.versionNo || '-' }}</el-button>
</template>
</el-table-column>
<el-table-column :label="colEff" min-width="170">
<template #default="{ row }">{{ row.effectiveTime || '-' }}</template>
</el-table-column>
<el-table-column :label="colExp" min-width="170">
<template #default="{ row }">{{ row.expireTime || '-' }}</template>
</el-table-column>
<el-table-column :label="colStatus" width="100" align="center">
<template #default="{ row }">
<el-tag :type="versionStatusTag(row.status)" size="small">{{ versionStatusLabel(row.status) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="colProducts" prop="productCount" width="90" align="center" />
<el-table-column :label="colRows" prop="detailCount" width="100" align="center" />
<el-table-column :label="colAction" width="420" align="center" fixed="right">
<template #default="{ row }">
<el-button link type="primary" @click.stop="emit('view-products', row)">{{ labViewProducts }}</el-button>
<el-button link type="primary" @click.stop="emit('view-attach', row)" v-hasPermi="[queryPerm]">{{ labViewAttach }}</el-button>
<el-button
v-if="showEditButton(row)"
link
type="primary"
@click.stop="emit('edit', row)"
>{{ labEdit }}</el-button>
<el-button
v-if="isDraftVersion(row)"
link
type="success"
@click.stop="emit('activate', row)"
v-hasPermi="[editPerm]"
>{{ labStart }}</el-button>
<el-button
v-if="isDraftVersion(row) || isPendingVersion(row) || isEffectVersion(row)"
link
type="danger"
:loading="isRemoving(row)"
:disabled="removingPsvId != null"
@click.stop="emit('remove', row)"
v-hasPermi="[removePerm]"
>{{ labDelete }}</el-button>
</template>
</el-table-column>
</el-table>
</div>
</template>
<script setup name="CatalogVersionTable">
import {
versionStatusLabel,
versionStatusTag,
isDraftVersion,
isPendingVersion,
isEffectVersion,
isExpiredVersion,
isPriceEditableVersion
} from '@/views/price/set/utils/priceSet'
import { checkPermi } from '@/utils/permission'
const props = defineProps({
versions: { type: Array, default: () => [] },
loading: { type: Boolean, default: false },
title: { type: String, required: true },
createLabel: { type: String, required: true },
createPerm: { type: String, required: true },
editPerm: { type: String, required: true },
removePerm: { type: String, required: true },
queryPerm: { type: String, required: true },
removingPsvId: { type: [Number, String], default: null }
})
const emit = defineEmits(['create', 'edit', 'view-products', 'view-attach', 'activate', 'remove'])
const colNo = '版本号'
const colEff = '生效时间'
const colExp = '失效时间'
const colStatus = '状态'
const colProducts = '产品数'
const colRows = '明细行数'
const colAction = '操作'
const emptyText = '暂无版本'
const labViewProducts = '查看产品'
const labViewAttach = '查看附件'
const labEdit = '编辑'
const labStart = '启动'
const labDelete = '删除'
const statusTab = ref('all')
const counts = computed(() => {
const map = { all: 0, pending: 0, '1': 0, '2': 0 }
;(props.versions || []).forEach(v => {
map.all++
const st = String(v.status == null ? '' : v.status)
if (st === '0' || st === '3') map.pending++
else if (map[st] != null) map[st]++
})
return map
})
function tabLabel(key) {
const labels = {
all: '全部',
pending: '待生效',
'1': '已生效',
'2': '已失效'
}
return labels[key] + ' (' + (counts.value[key] || 0) + ')'
}
const hasDraft = computed(() => (props.versions || []).some(v => isDraftVersion(v)))
const filteredVersions = computed(() => {
const list = props.versions || []
if (statusTab.value === 'all') return list
if (statusTab.value === 'pending') {
return list.filter(v => {
const st = String(v.status == null ? '' : v.status)
return st === '0' || st === '3'
})
}
return list.filter(v => String(v.status) === statusTab.value)
})
function showEditButton(row) {
if (!checkPermi([props.editPerm])) return false
// draft / pending / effect / expired can edit
return isPriceEditableVersion(row) || isEffectVersion(row) || isExpiredVersion(row)
}
function isRemoving(row) {
return props.removingPsvId != null && row && String(props.removingPsvId) === String(row.psvId)
}
function onRowClick(row) {
emit('view-products', row)
}
</script>
<style scoped>
.catalog-ver {
background: #fff;
border: 1px solid var(--el-border-color-lighter);
border-radius: 8px;
padding: 12px 16px 16px;
}
.ver-head {
display: flex;
align-items: center;
justify-content: space-between;
gap: 12px;
margin-bottom: 4px;
}
.ver-title {
display: flex;
align-items: center;
gap: 8px;
min-width: 0;
}
.ver-bar {
width: 3px;
height: 14px;
border-radius: 2px;
background: #52c41a;
flex: none;
}
.ver-text {
font-size: 15px;
font-weight: 600;
color: #303133;
}
.ver-tabs {
margin-bottom: 8px;
}
.ver-tabs :deep(.el-tabs__header) {
margin-bottom: 8px;
}
</style>