2025-05-21 13:44:54 +08:00
|
|
|
|
<template>
|
|
|
|
|
<div class="auth-management">
|
|
|
|
|
<!-- 统计卡片 -->
|
|
|
|
|
<el-row :gutter="20">
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-card shadow="hover" style="border-radius: 24px" :body-class="'card-body'">
|
|
|
|
|
<div class="card-left">
|
|
|
|
|
<img :src="getAssetsFile('images/brand/1532.png')" alt="" />
|
|
|
|
|
<div class="card-content flex-1 flex-column">
|
|
|
|
|
<div class="stat-number">999 <span>件</span></div>
|
|
|
|
|
<div class="stat-label">授权产品</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-right">
|
|
|
|
|
<img :src="getAssetsFile('images/brand/cardLeft.png')" alt="" />
|
|
|
|
|
<p>较上月上涨 <span>7</span> 件</p>
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
</el-col>
|
|
|
|
|
<el-col :span="12">
|
|
|
|
|
<el-card shadow="hover" style="border-radius: 24px" :body-class="'card-body'">
|
|
|
|
|
<div class="card-left">
|
|
|
|
|
<img :src="getAssetsFile('images/brand/1533.png')" alt="" />
|
|
|
|
|
<div class="card-content flex-1 flex-column">
|
|
|
|
|
<div class="stat-number">999 <span>件</span></div>
|
|
|
|
|
<div class="stat-label">授权产品</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="card-right">
|
|
|
|
|
<img :src="getAssetsFile('images/brand/cardRight.png')" alt="" />
|
|
|
|
|
<p>较上月上涨 <span>7</span> 件</p>
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
</el-col>
|
|
|
|
|
</el-row>
|
|
|
|
|
|
|
|
|
|
<!-- 产品列表 -->
|
|
|
|
|
<el-card shadow="hover" style="border-radius: 16px" class="product-card">
|
|
|
|
|
<!-- 状态筛选 -->
|
|
|
|
|
<el-tabs v-model="activeStatus" class="tabs-wrapper">
|
|
|
|
|
<el-tab-pane label="已授权" name="authorized" />
|
|
|
|
|
<el-tab-pane label="审批中" name="approving" />
|
|
|
|
|
<el-tab-pane label="已失效" name="expired" />
|
|
|
|
|
</el-tabs>
|
|
|
|
|
<div class="product-list">
|
|
|
|
|
<div v-for="(product, index) in filteredProducts" :key="product.id" class="product-item" :class="{ 'border-top': index > 0 }">
|
|
|
|
|
<div class="product-info">
|
|
|
|
|
<img class="product-img" :src="product.img" alt="product" />
|
|
|
|
|
<div class="product-text">
|
|
|
|
|
<span class="product-name">{{ product.name }}</span>
|
|
|
|
|
<div class="detail-item">
|
|
|
|
|
<label>检测批次:</label>
|
|
|
|
|
<span>{{ product.batch }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="detail-item">
|
|
|
|
|
<label>授权期限:</label>
|
|
|
|
|
<span>{{ product.duration }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="detail-item">
|
|
|
|
|
<label>到期时间:</label>
|
|
|
|
|
<span class="text-expire">{{ product.expireDate }}</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div class="product-action">
|
2025-05-22 10:38:36 +08:00
|
|
|
|
<el-tag :class="statusClass(activeStatus)" :type="statusTypeMap[product.status]">{{ product.statusLabel }}</el-tag>
|
2025-05-21 13:44:54 +08:00
|
|
|
|
<el-button
|
|
|
|
|
v-if="product.status === 'authorized'"
|
|
|
|
|
type="primary"
|
|
|
|
|
plain
|
|
|
|
|
:icon="Edit"
|
|
|
|
|
size="large"
|
|
|
|
|
style="border-radius: 8px"
|
|
|
|
|
@click="handleCertificate(product)"
|
|
|
|
|
>
|
|
|
|
|
授权证书
|
|
|
|
|
</el-button>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</el-card>
|
|
|
|
|
<!-- 证书预览 -->
|
|
|
|
|
<el-dialog v-model="certificateDialogVisible" title="授权证书" width="30%" destroy-on-close>
|
|
|
|
|
<div style="display: flex; justify-content: center">
|
|
|
|
|
<el-image
|
|
|
|
|
:src="currentCertificateImg"
|
|
|
|
|
fit="contain"
|
|
|
|
|
style="max-width: 600px; width: 80%"
|
|
|
|
|
:preview-src-list="[currentCertificateImg]"
|
|
|
|
|
:z-index="9999"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</el-dialog>
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script setup>
|
|
|
|
|
import { ref, computed } from 'vue';
|
|
|
|
|
import { getAssetsFile } from '@/utils/index.js';
|
|
|
|
|
import { getProducts } from '@/apis/brand';
|
|
|
|
|
import { Edit } from '@element-plus/icons-vue';
|
|
|
|
|
|
|
|
|
|
const activeStatus = ref('authorized');
|
|
|
|
|
|
|
|
|
|
const statusTypeMap = {
|
|
|
|
|
authorized: 'success',
|
|
|
|
|
approving: 'warning',
|
|
|
|
|
expired: 'danger',
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const products = ref([
|
|
|
|
|
{
|
|
|
|
|
id: 1,
|
|
|
|
|
name: '耿马镇沙疆西红柿',
|
|
|
|
|
batch: '10021',
|
|
|
|
|
duration: '6个月',
|
|
|
|
|
expireDate: '2025.01.01',
|
|
|
|
|
status: 'authorized',
|
|
|
|
|
statusLabel: '已授权',
|
|
|
|
|
img: getAssetsFile('images/brand/product4.png'),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 2,
|
|
|
|
|
name: '孟弄乡沙地土豆',
|
|
|
|
|
batch: '10022',
|
|
|
|
|
duration: '6个月',
|
|
|
|
|
expireDate: '2025.01.02',
|
|
|
|
|
status: 'authorized',
|
|
|
|
|
statusLabel: '已授权',
|
|
|
|
|
img: getAssetsFile('images/brand/product6.png'),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 3,
|
|
|
|
|
name: '芒洪乡水果彩椒',
|
|
|
|
|
batch: '10021',
|
|
|
|
|
duration: '6个月',
|
|
|
|
|
expireDate: '2025.01.01',
|
|
|
|
|
status: 'authorized',
|
|
|
|
|
statusLabel: '已授权',
|
|
|
|
|
img: getAssetsFile('images/brand/product2.png'),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 4,
|
|
|
|
|
name: '耿马镇沙疆西红柿',
|
|
|
|
|
batch: '10021',
|
|
|
|
|
duration: '6个月',
|
|
|
|
|
expireDate: '2025.01.01',
|
|
|
|
|
status: 'approving',
|
|
|
|
|
statusLabel: '审批中',
|
|
|
|
|
img: getAssetsFile('images/brand/product4.png'),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 5,
|
|
|
|
|
name: '孟弄乡沙地土豆',
|
|
|
|
|
batch: '10022',
|
|
|
|
|
duration: '6个月',
|
|
|
|
|
expireDate: '2025.01.02',
|
|
|
|
|
status: 'approving',
|
|
|
|
|
statusLabel: '审批中',
|
|
|
|
|
img: getAssetsFile('images/brand/product6.png'),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
id: 6,
|
|
|
|
|
name: '芒洪乡水果彩椒',
|
|
|
|
|
batch: '10021',
|
|
|
|
|
duration: '6个月',
|
|
|
|
|
expireDate: '2025.01.01',
|
|
|
|
|
status: 'expired',
|
|
|
|
|
statusLabel: '已失效',
|
|
|
|
|
img: getAssetsFile('images/brand/product2.png'),
|
|
|
|
|
},
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const statusClass = (tab) => {
|
|
|
|
|
if (tab === 'approving') return 'text-warning status-tag';
|
|
|
|
|
if (tab === 'expired') return 'text-danger status-tag';
|
|
|
|
|
return 'text-success status-tag';
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const filteredProducts = computed(() => products.value.filter((p) => p.status === activeStatus.value));
|
|
|
|
|
const certificateDialogVisible = ref(false);
|
|
|
|
|
const currentCertificateImg = ref('');
|
|
|
|
|
|
|
|
|
|
const handleCertificate = (product) => {
|
|
|
|
|
console.log('查看证书:', product);
|
|
|
|
|
// 假设每个产品都有一个证书图片路径字段,临时写死
|
|
|
|
|
currentCertificateImg.value = getAssetsFile('images/brand/sqzs.png'); // 你可以换成真实字段,如 product.certificate
|
|
|
|
|
certificateDialogVisible.value = true;
|
|
|
|
|
};
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
.auth-management {
|
|
|
|
|
padding: 0 20px 0 0;
|
|
|
|
|
height: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
.product-card {
|
|
|
|
|
flex: 1;
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
}
|
|
|
|
|
:deep(.el-card__body) {
|
|
|
|
|
height: 100%;
|
|
|
|
|
}
|
|
|
|
|
.product-list {
|
2025-05-22 10:38:36 +08:00
|
|
|
|
height: calc(100% - 40px);
|
2025-05-21 13:44:54 +08:00
|
|
|
|
overflow: auto;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-list::-webkit-scrollbar {
|
|
|
|
|
display: none;
|
|
|
|
|
}
|
|
|
|
|
:deep(.card-body) {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding: 0;
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.card-left:deep(img) {
|
|
|
|
|
width: 88px;
|
|
|
|
|
display: block;
|
|
|
|
|
aspect-ratio: 1/1;
|
|
|
|
|
padding: 20px;
|
|
|
|
|
margin: 0;
|
|
|
|
|
}
|
|
|
|
|
.card-right:deep(img) {
|
|
|
|
|
width: 133px;
|
|
|
|
|
height: 80px;
|
|
|
|
|
display: block;
|
|
|
|
|
// padding: 20px;
|
|
|
|
|
margin: 0;
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
.card-left {
|
|
|
|
|
width: 50%;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
|
|
|
|
|
.card-content {
|
|
|
|
|
height: 88px;
|
|
|
|
|
// background-color: #fafafa;
|
|
|
|
|
|
|
|
|
|
span {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
text-align: left;
|
|
|
|
|
color: #000000;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.stat-number {
|
|
|
|
|
font-size: 32px;
|
|
|
|
|
font-weight: 600;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
text-align: left;
|
|
|
|
|
color: #000000;
|
|
|
|
|
}
|
|
|
|
|
.stat-label {
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
text-align: left;
|
|
|
|
|
color: #999999;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.card-right {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
width: 50%;
|
|
|
|
|
|
|
|
|
|
p {
|
|
|
|
|
margin: 0;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
text-align: left;
|
|
|
|
|
color: #000000;
|
|
|
|
|
span {
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
text-align: left;
|
|
|
|
|
color: #25bf82;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.tabs-wrapper {
|
|
|
|
|
width: 100%;
|
|
|
|
|
display: flex;
|
|
|
|
|
align-items: center;
|
|
|
|
|
background-color: #fff;
|
|
|
|
|
|
|
|
|
|
:deep(.el-tabs__item) {
|
|
|
|
|
font-size: 24px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
border: 1 solid #f000;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
.flex {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: row;
|
|
|
|
|
}
|
|
|
|
|
.flex-column {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
}
|
|
|
|
|
.flex-1 {
|
|
|
|
|
flex: 1;
|
|
|
|
|
}
|
|
|
|
|
.flex-space-between {
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-item {
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: center;
|
|
|
|
|
padding: 20px 0;
|
|
|
|
|
|
|
|
|
|
.product-info {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex: 1;
|
|
|
|
|
|
|
|
|
|
.product-img {
|
|
|
|
|
width: 110px;
|
|
|
|
|
aspect-ratio: 1 / 1;
|
|
|
|
|
object-fit: cover;
|
|
|
|
|
padding: 8px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-text {
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
align-items: center;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
|
|
|
|
|
.product-name {
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
text-align: left;
|
|
|
|
|
color: #000000;
|
|
|
|
|
}
|
|
|
|
|
.detail-item {
|
|
|
|
|
width: 100%;
|
|
|
|
|
font-size: 16px;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
font-weight: 400;
|
|
|
|
|
text-align: left;
|
|
|
|
|
color: #999999;
|
|
|
|
|
|
|
|
|
|
span {
|
|
|
|
|
color: #000000;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.product-action {
|
|
|
|
|
width: 200px;
|
|
|
|
|
height: 110px;
|
|
|
|
|
padding: 8px;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
justify-content: space-between;
|
|
|
|
|
align-items: end;
|
|
|
|
|
|
|
|
|
|
.status-tag {
|
|
|
|
|
text-align: right;
|
|
|
|
|
font-size: 20px;
|
|
|
|
|
font-weight: 700;
|
|
|
|
|
.text-success {
|
|
|
|
|
color: #67c23a;
|
|
|
|
|
}
|
|
|
|
|
.text-warning {
|
|
|
|
|
color: #e6a23c;
|
|
|
|
|
}
|
|
|
|
|
.text-danger {
|
|
|
|
|
color: #f56c6c;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|