2025-05-20 08:53:11 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div class="usage-monitor">
|
2025-05-20 13:32:43 +08:00
|
|
|
|
<!-- 顶部 TabPane,居中显示 -->
|
|
|
|
|
<div class="tabs-wrapper">
|
|
|
|
|
<el-tabs v-model="activeTab" type="card" class="centered-tabs">
|
|
|
|
|
<el-tab-pane label="在售中" name="onSale" />
|
|
|
|
|
<el-tab-pane label="未上架" name="offShelf" />
|
|
|
|
|
<el-tab-pane label="已失效" name="expired" />
|
|
|
|
|
</el-tabs>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 列表内容 -->
|
|
|
|
|
<div class="list-wrapper">
|
|
|
|
|
<div v-for="(p, idx) in filteredProducts" :key="p.id" class="list-item" :class="{ 'has-border': idx > 0 }">
|
|
|
|
|
<!-- 商品图 -->
|
|
|
|
|
<img class="item-img" :src="p.img" alt="商品图" />
|
|
|
|
|
|
|
|
|
|
<!-- 名称 + 月售/库存 -->
|
|
|
|
|
<div class="item-info">
|
|
|
|
|
<div class="item-name">{{ p.name }}</div>
|
|
|
|
|
<div class="item-stats">月售 {{ p.monthlySales }} · 库存 {{ p.stock }}</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 价格 -->
|
|
|
|
|
<div class="item-price">¥ {{ p.price }} /kg</div>
|
|
|
|
|
|
|
|
|
|
<!-- 操作按钮 -->
|
|
|
|
|
<div class="item-actions">
|
|
|
|
|
<el-button size="small" @click="onInspect(p)">抽查</el-button>
|
|
|
|
|
<el-button size="small" type="danger" @click="onRevoke(p)">取消授权</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- 右侧状态 -->
|
|
|
|
|
<div class="item-status" :class="statusClass(activeTab)">
|
|
|
|
|
{{ tabLabels[activeTab] }}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2025-05-20 08:53:11 +08:00
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, computed } from 'vue';
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
const activeTab = ref('onSale');
|
2025-05-20 08:53:11 +08:00
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
const tabLabels = {
|
|
|
|
|
onSale: '在售中',
|
|
|
|
|
offShelf: '未上架',
|
|
|
|
|
expired: '已失效',
|
2025-05-20 08:53:11 +08:00
|
|
|
|
};
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
// 示例数据,替换为真实接口数据
|
2025-05-20 08:53:11 +08:00
|
|
|
|
const products = ref([
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
2025-05-20 13:32:43 +08:00
|
|
|
|
name: '耿马镇沙疆西红柿',
|
|
|
|
|
img: 'https://via.placeholder.com/80',
|
2025-05-20 08:53:11 +08:00
|
|
|
|
monthlySales: 999,
|
|
|
|
|
stock: 10000,
|
2025-05-20 13:32:43 +08:00
|
|
|
|
price: 3.0,
|
2025-05-20 08:53:11 +08:00
|
|
|
|
status: 'onSale',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 2,
|
2025-05-20 13:32:43 +08:00
|
|
|
|
name: '耿马镇沙疆土豆',
|
|
|
|
|
img: 'https://via.placeholder.com/80',
|
|
|
|
|
monthlySales: 123,
|
|
|
|
|
stock: 5000,
|
|
|
|
|
price: 2.5,
|
2025-05-20 08:53:11 +08:00
|
|
|
|
status: 'onSale',
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 3,
|
2025-05-20 13:32:43 +08:00
|
|
|
|
name: '彩椒南瓜混合',
|
|
|
|
|
img: 'https://via.placeholder.com/80',
|
|
|
|
|
monthlySales: 456,
|
|
|
|
|
stock: 8000,
|
|
|
|
|
price: 4.2,
|
|
|
|
|
status: 'offShelf',
|
2025-05-20 08:53:11 +08:00
|
|
|
|
},
|
2025-05-20 13:32:43 +08:00
|
|
|
|
// … 更多数据
|
2025-05-20 08:53:11 +08:00
|
|
|
|
]);
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
// 根据当前 Tab 过滤
|
|
|
|
|
const filteredProducts = computed(() => products.value.filter((p) => p.status === activeTab.value));
|
2025-05-20 08:53:11 +08:00
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
// 操作回调
|
|
|
|
|
const onInspect = (p) => {
|
|
|
|
|
console.log('抽查商品', p);
|
|
|
|
|
};
|
|
|
|
|
const onRevoke = (p) => {
|
|
|
|
|
console.log('取消授权', p);
|
2025-05-20 08:53:11 +08:00
|
|
|
|
};
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
// 状态文字的颜色
|
|
|
|
|
const statusClass = (tab) => {
|
|
|
|
|
if (tab === 'offShelf') return 'text-warning';
|
|
|
|
|
if (tab === 'expired') return 'text-danger';
|
|
|
|
|
return 'text-success';
|
2025-05-20 08:53:11 +08:00
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
<style scoped lang="scss">
|
2025-05-20 08:53:11 +08:00
|
|
|
|
.usage-monitor {
|
|
|
|
|
padding: 20px;
|
2025-05-20 13:32:43 +08:00
|
|
|
|
background: #fff;
|
2025-05-20 08:53:11 +08:00
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
.tabs-wrapper {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
2025-05-20 08:53:11 +08:00
|
|
|
|
margin-bottom: 24px;
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
.centered-tabs {
|
|
|
|
|
width: 600px; /* 根据实际需要调整宽度 */
|
|
|
|
|
.el-tabs__header {
|
|
|
|
|
justify-content: center;
|
|
|
|
|
}
|
2025-05-20 08:53:11 +08:00
|
|
|
|
}
|
2025-05-20 13:32:43 +08:00
|
|
|
|
}
|
2025-05-20 08:53:11 +08:00
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
.list-wrapper {
|
|
|
|
|
.list-item {
|
|
|
|
|
display: grid;
|
|
|
|
|
grid-template-columns: 80px 1fr auto auto 80px;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding: 16px 0;
|
|
|
|
|
&.has-border {
|
|
|
|
|
border-top: 1px solid #ebeef5;
|
|
|
|
|
}
|
2025-05-20 08:53:11 +08:00
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
.item-img {
|
|
|
|
|
width: 80px;
|
|
|
|
|
height: 80px;
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
border-radius: 8px;
|
2025-05-20 08:53:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
.item-info {
|
|
|
|
|
padding-left: 16px;
|
|
|
|
|
.item-name {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: 500;
|
|
|
|
|
margin-bottom: 8px;
|
|
|
|
|
}
|
|
|
|
|
.item-stats {
|
|
|
|
|
color: #909399;
|
|
|
|
|
font-size: 14px;
|
2025-05-20 08:53:11 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
.item-price {
|
2025-05-20 08:53:11 +08:00
|
|
|
|
font-size: 18px;
|
|
|
|
|
font-weight: 600;
|
2025-05-20 13:32:43 +08:00
|
|
|
|
color: #67c23a;
|
|
|
|
|
text-align: right;
|
|
|
|
|
padding: 0 16px;
|
2025-05-20 08:53:11 +08:00
|
|
|
|
}
|
|
|
|
|
|
2025-05-20 13:32:43 +08:00
|
|
|
|
.item-actions {
|
|
|
|
|
display: flex;
|
|
|
|
|
gap: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.item-status {
|
|
|
|
|
text-align: right;
|
|
|
|
|
font-size: 14px;
|
|
|
|
|
&.text-success {
|
|
|
|
|
color: #67c23a;
|
|
|
|
|
}
|
|
|
|
|
&.text-warning {
|
|
|
|
|
color: #e6a23c;
|
|
|
|
|
}
|
|
|
|
|
&.text-danger {
|
|
|
|
|
color: #f56c6c;
|
|
|
|
|
}
|
|
|
|
|
}
|
2025-05-20 08:53:11 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|