运营云公共品牌
| @ -31,6 +31,14 @@ export default defineConfig(({ command, mode }) => { | ||||
|         'Access-Control-Allow-Origin': '*', | ||||
|       }, | ||||
|       proxy: { | ||||
|         // 仅 Brand 模块走子应用 DevServer
 | ||||
|         '/api/brand': { | ||||
|           target: 'http://localhost:9526', | ||||
|           changeOrigin: true, | ||||
|           // 如果想去掉 /api/brand 前缀(比如子应用实际监听的是 /brand/...),
 | ||||
|           // 可以加一个 rewrite:
 | ||||
|           // rewrite: path => path.replace(/^\/api\/brand/, '/brand'),
 | ||||
|         }, | ||||
|         [VITE_APP_BASE_API]: { | ||||
|           target: VITE_APP_BASE_URL, | ||||
|           changeOrigin: true, | ||||
|  | ||||
							
								
								
									
										21
									
								
								sub-operation-service/src/apis/brand.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,21 @@ | ||||
| // src/apis/brand.js
 | ||||
| import axios from '@/utils/axios'; | ||||
| 
 | ||||
| export const getProducts = (params) => { | ||||
|   return axios.get('/api/brand/products', { | ||||
|     params, | ||||
|     apisType: 'mock', | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
| export const getApplyList = () => { | ||||
|   return axios.get('/api/brand/apply-list', { | ||||
|     apisType: 'mock', | ||||
|   }); | ||||
| }; | ||||
| 
 | ||||
| export const getMonitorList = () => { | ||||
|   return axios.get('/api/brand/monitor-list', { | ||||
|     apisType: 'mock', | ||||
|   }); | ||||
| }; | ||||
| @ -1,23 +0,0 @@ | ||||
| export default { | ||||
|   // 模拟获取商品列表
 | ||||
|   getProducts: () => { | ||||
|     return new Promise((resolve) => { | ||||
|       setTimeout(() => { | ||||
|         resolve([ | ||||
|           { id: 1, name: '耿马绿色蔬菜', imageUrl: 'images/brand/11.png' }, | ||||
|           { id: 2, name: '云南高山茶', imageUrl: 'images/brand/12.png' }, | ||||
|           { id: 3, name: '新疆大枣', imageUrl: 'images/brand/13.png' }, | ||||
|           { id: 4, name: '东北大米', imageUrl: 'images/brand/14.png' }, | ||||
|           { id: 5, name: '山东苹果', imageUrl: 'images/brand/15.png' }, | ||||
|           { id: 6, name: '四川泡菜', imageUrl: 'images/brand/16.png' }, | ||||
|           { id: 7, name: '江苏阳澄湖大闸蟹', imageUrl: 'images/brand/11.png' }, | ||||
|           { id: 8, name: '海南椰子', imageUrl: 'images/brand/12.png' }, | ||||
|           { id: 9, name: '广东早茶', imageUrl: 'images/brand/13.png' }, | ||||
|           { id: 10, name: '北京烤鸭', imageUrl: 'images/brand/14.png' }, | ||||
|           { id: 11, name: '西藏青稞酒', imageUrl: 'images/brand/15.png' }, | ||||
|           { id: 12, name: '青海牦牛肉', imageUrl: 'images/brand/16.png' }, | ||||
|         ]); | ||||
|       }, 500); // 模拟网络延迟
 | ||||
|     }); | ||||
|   }, | ||||
| }; | ||||
| Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 2.5 KiB | 
| Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 3.7 KiB | 
| Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/brand/cardLeft.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 4.3 KiB | 
							
								
								
									
										
											BIN
										
									
								
								sub-operation-service/src/assets/images/brand/cardRight.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						| After Width: | Height: | Size: 5.8 KiB | 
							
								
								
									
										136
									
								
								sub-operation-service/src/mock/brand.mock.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,136 @@ | ||||
| // src/mock/brand.mock.js
 | ||||
| export default [ | ||||
|   { | ||||
|     url: '/api/brand/products', | ||||
|     method: 'get', | ||||
|     response: () => ({ | ||||
|       code: 200, | ||||
|       data: products, | ||||
|     }), | ||||
|   }, | ||||
|   { | ||||
|     url: '/api/brand/apply-list', | ||||
|     method: 'get', | ||||
|     response: () => ({ | ||||
|       code: 200, | ||||
|       data: applyData, | ||||
|     }), | ||||
|   }, | ||||
|   { | ||||
|     url: '/api/brand/monitor-list', | ||||
|     method: 'get', | ||||
|     response: () => ({ | ||||
|       code: 200, | ||||
|       data: monitor, | ||||
|     }), | ||||
|   }, | ||||
| ]; | ||||
| 
 | ||||
| const products = [ | ||||
|   { | ||||
|     id: 1, | ||||
|     name: '耿马镇沙疆西红柿', | ||||
|     batch: '10021', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.01', | ||||
|     status: 'authorized', | ||||
|     statusLabel: '已授权', | ||||
|     img: 'images/brand/product4.png', | ||||
|   }, | ||||
|   { | ||||
|     id: 2, | ||||
|     name: '孟弄乡沙地土豆', | ||||
|     batch: '10022', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.02', | ||||
|     status: 'authorized', | ||||
|     statusLabel: '已授权', | ||||
|     img: 'images/brand/product6.png', | ||||
|   }, | ||||
|   { | ||||
|     id: 3, | ||||
|     name: '芒洪乡水果彩椒', | ||||
|     batch: '10021', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.01', | ||||
|     status: 'authorized', | ||||
|     statusLabel: '已授权', | ||||
|     img: 'images/brand/product2.png', | ||||
|   }, | ||||
|   { | ||||
|     id: 4, | ||||
|     name: '耿马镇沙疆西红柿', | ||||
|     batch: '10021', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.01', | ||||
|     status: 'approving', | ||||
|     statusLabel: '审批中', | ||||
|     img: 'images/brand/product4.png', | ||||
|   }, | ||||
|   { | ||||
|     id: 5, | ||||
|     name: '孟弄乡沙地土豆', | ||||
|     batch: '10022', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.02', | ||||
|     status: 'approving', | ||||
|     statusLabel: '审批中', | ||||
|     img: 'images/brand/product6.png', | ||||
|   }, | ||||
|   { | ||||
|     id: 6, | ||||
|     name: '芒洪乡水果彩椒', | ||||
|     batch: '10021', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.01', | ||||
|     status: 'expired', | ||||
|     statusLabel: '已失效', | ||||
|     img: 'images/brand/product2.png', | ||||
|   }, | ||||
| ]; | ||||
| 
 | ||||
| const applyData = [ | ||||
|   { id: 1, name: '耿马绿色蔬菜', imageUrl: 'images/brand/11.png' }, | ||||
|   { id: 2, name: '云南高山茶', imageUrl: 'images/brand/12.png' }, | ||||
|   { id: 3, name: '新疆大枣', imageUrl: 'images/brand/13.png' }, | ||||
|   { id: 4, name: '东北大米', imageUrl: 'images/brand/14.png' }, | ||||
|   { id: 5, name: '山东苹果', imageUrl: 'images/brand/15.png' }, | ||||
|   { id: 6, name: '四川泡菜', imageUrl: 'images/brand/16.png' }, | ||||
|   { id: 7, name: '江苏阳澄湖大闸蟹', imageUrl: 'images/brand/11.png' }, | ||||
|   { id: 8, name: '海南椰子', imageUrl: 'images/brand/12.png' }, | ||||
|   { id: 9, name: '广东早茶', imageUrl: 'images/brand/13.png' }, | ||||
|   { id: 10, name: '北京烤鸭', imageUrl: 'images/brand/14.png' }, | ||||
|   { id: 11, name: '西藏青稞酒', imageUrl: 'images/brand/15.png' }, | ||||
|   { id: 12, name: '青海牦牛肉', imageUrl: 'images/brand/16.png' }, | ||||
| ]; | ||||
| 
 | ||||
| const monitor = [ | ||||
|   { | ||||
|     id: 1, | ||||
|     name: '耿马镇沙疆西红柿', | ||||
|     img: 'images/brand/product4.png', | ||||
|     monthlySales: 999, | ||||
|     stock: 10000, | ||||
|     price: 3.0, | ||||
|     status: 'onSale', | ||||
|   }, | ||||
|   { | ||||
|     id: 2, | ||||
|     name: '耿马镇沙疆土豆', | ||||
|     img: 'images/brand/product6.png', | ||||
|     monthlySales: 123, | ||||
|     stock: 5000, | ||||
|     price: 2.5, | ||||
|     status: 'onSale', | ||||
|   }, | ||||
|   { | ||||
|     id: 3, | ||||
|     name: '彩椒南瓜混合', | ||||
|     img: 'images/brand/product1.png', | ||||
|     monthlySales: 456, | ||||
|     stock: 8000, | ||||
|     price: 4.2, | ||||
|     status: 'offShelf', | ||||
|   }, | ||||
|   // … 更多数据
 | ||||
| ]; | ||||
| @ -66,7 +66,7 @@ export const constantRoutes = [ | ||||
|         name: 'userOrders', | ||||
|         meta: { title: '我的订单' }, | ||||
|       }, | ||||
|        { | ||||
|       { | ||||
|         path: '/sub-operation-service/userLands', | ||||
|         component: () => import('@/views/userCenter/userLands.vue'), | ||||
|         name: 'userLands', | ||||
| @ -184,17 +184,54 @@ export const constantRoutes = [ | ||||
|     path: '/sub-operation-service/brand', | ||||
|     name: 'brand', | ||||
|     component: Layout, | ||||
|     redirect: '/sub-operation-service/brand/index', | ||||
|     redirect: '/sub-operation-service/brand/apply', // 默认页
 | ||||
|     meta: { title: '公共品牌' }, | ||||
|     children: [ | ||||
|       { | ||||
|         path: '/sub-operation-service/brand/index', | ||||
|         path: 'apply', | ||||
|         component: () => import('@/views/brand/index.vue'), | ||||
|         name: 'brandMain', | ||||
|         meta: { title: '公共品牌首页' }, | ||||
|         children: [ | ||||
|           { | ||||
|             path: '', | ||||
|             component: () => import('@/views/brand/components/ApplyList.vue'), | ||||
|             name: 'brandApplyList', | ||||
|             meta: { title: '使用申请' }, | ||||
|           }, | ||||
|           { | ||||
|             path: ':id', | ||||
|             component: () => import('@/views/brand/components/ApplyDetail.vue'), | ||||
|             name: 'brandApplyDetail', | ||||
|             meta: { title: '产品申请' }, | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|       { | ||||
|         path: 'auth', | ||||
|         component: () => import('@/views/brand/index.vue'), | ||||
|         children: [ | ||||
|           { | ||||
|             path: '', | ||||
|             component: () => import('@/views/brand/components/Auth.vue'), | ||||
|             name: 'brandAuth', | ||||
|             meta: { title: '授权管理' }, | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|       { | ||||
|         path: 'monitor', | ||||
|         component: () => import('@/views/brand/index.vue'), | ||||
|         children: [ | ||||
|           { | ||||
|             path: '', | ||||
|             component: () => import('@/views/brand/components/Monitor.vue'), | ||||
|             name: 'brandMonitor', | ||||
|             meta: { title: '使用监管' }, | ||||
|           }, | ||||
|         ], | ||||
|       }, | ||||
|     ], | ||||
|   }, | ||||
| 
 | ||||
|   { | ||||
|     path: '/sub-operation-service/ecommerce', | ||||
|     name: 'ecommerce', | ||||
|  | ||||
| @ -50,6 +50,10 @@ publicAxios.interceptors.request.use(async (config) => { | ||||
|       config.headers['Content-Type'] = config.uploadType; | ||||
|       break; | ||||
|     } | ||||
|     case 'mock': { | ||||
|       config.baseURL = ''; // 不走 VITE_APP_BASE_API,直接请求 mock 路径
 | ||||
|       break; | ||||
|     } | ||||
|     default: { | ||||
|       config.baseURL = VITE_APP_BASE_API; | ||||
|     } | ||||
|  | ||||
							
								
								
									
										129
									
								
								sub-operation-service/src/views/brand/components/ApplyDetail.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,129 @@ | ||||
| <template> | ||||
|   <div class="container"> | ||||
|     <el-breadcrumb separator="·"> | ||||
|       <el-breadcrumb-item style="cursor: pointer" @click="backToList">使用申请</el-breadcrumb-item> | ||||
|       <el-breadcrumb-item><a href="#">我要申请</a></el-breadcrumb-item> | ||||
|     </el-breadcrumb> | ||||
| 
 | ||||
|     <img :src="getAssetsFile('images/brand/11.png')" alt="" class="img" /> | ||||
| 
 | ||||
|     <el-form label-width="120px" class="form"> | ||||
|       <h1 style="margin: 20px 0 20px 50px">请选择溯源农产品申请</h1> | ||||
|       <el-form-item label="检查批次"> | ||||
|         <el-select v-model="batch" placeholder="请选择农产品批次" :width="200"> | ||||
|           <el-option label="批次A" value="A" /> | ||||
|           <el-option label="批次B" value="B" /> | ||||
|         </el-select> | ||||
|       </el-form-item> | ||||
| 
 | ||||
|       <el-form-item label="溯源码"> | ||||
|         <el-button type="primary" @click="uploadTraceCode"> | ||||
|           <template #icon> | ||||
|             <i class="el-icon-upload"></i> | ||||
|           </template> | ||||
|           点击上传 | ||||
|         </el-button> | ||||
|       </el-form-item> | ||||
| 
 | ||||
|       <el-form-item label="产品名称"> | ||||
|         <el-input v-model="productName" placeholder="自动获取..." disabled /> | ||||
|       </el-form-item> | ||||
| 
 | ||||
|       <el-form-item label="检测时间"> | ||||
|         <el-input v-model="detectTime" placeholder="自动获取..." disabled /> | ||||
|       </el-form-item> | ||||
| 
 | ||||
|       <el-form-item label="检测站"> | ||||
|         <el-input v-model="station" placeholder="自动获取..." disabled /> | ||||
|       </el-form-item> | ||||
| 
 | ||||
|       <el-form-item label="产地信息"> | ||||
|         <el-input v-model="origin" placeholder="自动获取..." disabled /> | ||||
|       </el-form-item> | ||||
| 
 | ||||
|       <el-form-item> | ||||
|         <el-button type="primary" style="border-radius: 8px" @click="submit">提交</el-button> | ||||
|       </el-form-item> | ||||
|     </el-form> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { useRouter, useRoute } from 'vue-router'; | ||||
| import { ref, onMounted } from 'vue'; | ||||
| import { ElMessage } from 'element-plus'; | ||||
| import { getAssetsFile } from '@/utils/index.js'; | ||||
| 
 | ||||
| const router = useRouter(); | ||||
| const route = useRoute(); | ||||
| 
 | ||||
| const productId = route.params.id; | ||||
| const product = ref({ name: '加载中...', id: productId }); | ||||
| 
 | ||||
| onMounted(() => { | ||||
|   // 模拟加载产品数据 | ||||
|   product.value = { | ||||
|     id: productId, | ||||
|     name: productId == 1 ? '有机苹果' : '绿色蔬菜', | ||||
|   }; | ||||
| }); | ||||
| 
 | ||||
| const batch = ref(''); | ||||
| const productName = ref(''); | ||||
| const detectTime = ref(''); | ||||
| const station = ref(''); | ||||
| const origin = ref(''); | ||||
| 
 | ||||
| function backToList() { | ||||
|   router.push(`/sub-operation-service/brand/apply`); | ||||
| } | ||||
| 
 | ||||
| function uploadTraceCode() { | ||||
|   console.log('上传溯源码'); | ||||
| } | ||||
| 
 | ||||
| function submit() { | ||||
|   console.log('提交申请:', { | ||||
|     product: product.value, | ||||
|     batch: batch.value, | ||||
|     detectTime: detectTime.value, | ||||
|     station: station.value, | ||||
|     origin: origin.value, | ||||
|   }); | ||||
|   ElMessage.success('提交成功!'); | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style scoped lang="scss"> | ||||
| .container { | ||||
|   padding: 20px; | ||||
|   background-color: #fff; | ||||
|   position: relative; | ||||
|   height: 100%; | ||||
| 
 | ||||
|   :deep(.el-breadcrumb__inner a) { | ||||
|     color: #25bf82; | ||||
|   } | ||||
| } | ||||
| .img { | ||||
|   width: 200px; | ||||
|   height: 200px; | ||||
|   position: absolute; | ||||
|   top: 60px; | ||||
|   left: 20px; | ||||
| } | ||||
| 
 | ||||
| .form { | ||||
|   margin-top: 20px; | ||||
|   width: 60%; | ||||
|   margin: 0 auto; | ||||
| } | ||||
| :deep(.form .el-form-item__content) { | ||||
|   max-width: 300px; | ||||
| } | ||||
| 
 | ||||
| :deep(.form .el-input, .form .el-select) { | ||||
|   width: 100%; | ||||
|   max-width: 300px; | ||||
| } | ||||
| </style> | ||||
| @ -3,10 +3,10 @@ | ||||
|     <el-col v-for="product in products" :key="product.id" :span="6"> | ||||
|       <el-card class="box-card" :body-style="{ padding: '8px', height: '100%' }"> | ||||
|         <div class="flex-column"> | ||||
|           <img :src="product.img" alt="商品图" class="img" /> | ||||
|           <img :src="getAssetsFile(product.imageUrl)" alt="商品图" class="img" /> | ||||
|           <div class="flex-1 flex-around"> | ||||
|             <p>{{ product.name }}</p> | ||||
|             <el-button type="success" class="button">我要申请</el-button> | ||||
|             <el-button type="success" class="button" @click="gotoApplication(product.id)">我要申请</el-button> | ||||
|           </div> | ||||
|         </div> | ||||
|       </el-card> | ||||
| @ -16,32 +16,25 @@ | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref, onMounted } from 'vue'; | ||||
| import productsApi from '@/apis/products'; | ||||
| import { getApplyList } from '@/apis/brand'; | ||||
| import { getAssetsFile } from '@/utils/index.js'; | ||||
| import { useRouter } from 'vue-router'; | ||||
| const router = useRouter(); | ||||
| 
 | ||||
| const url = 'https://via.placeholder.com/182'; | ||||
| const products = ref([]); | ||||
| 
 | ||||
| // 获取商品数据 | ||||
| const fetchProducts = async () => { | ||||
|   try { | ||||
|     const data = await productsApi.getProducts(); | ||||
|     const processedData = data.map((item) => { | ||||
|       return { | ||||
|         ...item, | ||||
|         img: getAssetsFile(item.imageUrl), // 确保图片路径正确 | ||||
|       }; | ||||
|     }); | ||||
| getApplyList().then((res) => { | ||||
|   products.value = res.data; | ||||
| }); | ||||
| 
 | ||||
|     products.value = processedData; | ||||
|   } catch (error) { | ||||
|     console.error('获取商品数据失败:', error); | ||||
|   } | ||||
| }; | ||||
| function gotoApplication(id) { | ||||
|   router.push(`/sub-operation-service/brand/apply/${id}`); | ||||
| } | ||||
| 
 | ||||
| // 组件挂载时获取数据 | ||||
| onMounted(() => { | ||||
|   fetchProducts(); | ||||
|   getApplyList; | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| @ -95,6 +88,7 @@ onMounted(() => { | ||||
|   .button { | ||||
|     width: 96px; | ||||
|     height: 40px; | ||||
|     border-radius: 8px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
							
								
								
									
										390
									
								
								sub-operation-service/src/views/brand/components/Auth.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,390 @@ | ||||
| <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"> | ||||
|             <el-tag :class="statusClass(activeTab)" :type="statusTypeMap[product.status]">{{ product.statusLabel }}</el-tag> | ||||
|             <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 { | ||||
|   height: 100%; | ||||
|   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> | ||||
| @ -1,202 +0,0 @@ | ||||
| <template> | ||||
|   <div class="auth-management"> | ||||
|     <!-- 统计卡片 --> | ||||
|     <el-row :gutter="20" class="mb-24"> | ||||
|       <el-col :span="12"> | ||||
|         <el-card shadow="hover" class="stat-card"> | ||||
|           <div class="stat-icon green-bg">✔</div> | ||||
|           <div> | ||||
|             <div class="stat-number">999 件</div> | ||||
|             <div class="stat-label">授权产品</div> | ||||
|           </div> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|       <el-col :span="12"> | ||||
|         <el-card shadow="hover" class="stat-card"> | ||||
|           <div class="stat-icon red-bg">⚠</div> | ||||
|           <div> | ||||
|             <div class="stat-number text-warning">199 件</div> | ||||
|             <div class="stat-label">临期产品</div> | ||||
|           </div> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|     </el-row> | ||||
| 
 | ||||
|     <!-- 状态筛选 --> | ||||
|     <el-tabs v-model="activeStatus" class="mb-24"> | ||||
|       <el-tab-pane label="已授权" name="authorized" /> | ||||
|       <el-tab-pane label="审批中" name="approving" /> | ||||
|       <el-tab-pane label="已失效" name="expired" /> | ||||
|     </el-tabs> | ||||
| 
 | ||||
|     <!-- 产品列表 --> | ||||
|     <el-card shadow="never"> | ||||
|       <div v-for="(product, index) in products" :key="product.id" class="product-item" :class="{ 'border-top': index > 0 }"> | ||||
|         <img class="product-img" src="https://via.placeholder.com/80" alt="product" /> | ||||
|         <div class="product-info"> | ||||
|           <div class="product-header"> | ||||
|             <el-tag :type="statusMap[product.status]">{{ product.statusLabel }}</el-tag> | ||||
|             <span class="product-name">{{ product.name }}</span> | ||||
|           </div> | ||||
|           <div class="product-details"> | ||||
|             <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> | ||||
|         <el-button type="primary" plain size="small" @click="handleCertificate(product)"> 授权证书 </el-button> | ||||
|       </div> | ||||
|     </el-card> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref } from 'vue'; | ||||
| 
 | ||||
| const activeStatus = ref('authorized'); | ||||
| 
 | ||||
| const statusMap = { | ||||
|   authorized: 'success', | ||||
|   approving: 'warning', | ||||
|   expired: 'danger', | ||||
| }; | ||||
| 
 | ||||
| const products = ref([ | ||||
|   { | ||||
|     id: 1, | ||||
|     name: '耿马镇沙疆西红柿', | ||||
|     batch: '10021', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.01', | ||||
|     status: 'authorized', | ||||
|     statusLabel: '已授权', | ||||
|   }, | ||||
|   { | ||||
|     id: 2, | ||||
|     name: '孟弄乡沙地土豆', | ||||
|     batch: '10022', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.02', | ||||
|     status: 'authorized', | ||||
|     statusLabel: '已授权', | ||||
|   }, | ||||
|   { | ||||
|     id: 3, | ||||
|     name: '芒洪乡水果彩椒', | ||||
|     batch: '10021', | ||||
|     duration: '6个月', | ||||
|     expireDate: '2025.01.01', | ||||
|     status: 'authorized', | ||||
|     statusLabel: '已授权', | ||||
|   }, | ||||
| ]); | ||||
| 
 | ||||
| const handleCertificate = (product) => { | ||||
|   console.log('查看证书:', product); | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| .auth-management { | ||||
|   padding: 20px; | ||||
| 
 | ||||
|   .stat-card { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     padding: 20px; | ||||
|     .stat-icon { | ||||
|       width: 50px; | ||||
|       height: 50px; | ||||
|       font-size: 24px; | ||||
|       color: white; | ||||
|       border-radius: 50%; | ||||
|       display: flex; | ||||
|       align-items: center; | ||||
|       justify-content: center; | ||||
|       margin-right: 16px; | ||||
|     } | ||||
|     .green-bg { | ||||
|       background-color: #67c23a; | ||||
|     } | ||||
|     .red-bg { | ||||
|       background-color: #f56c6c; | ||||
|     } | ||||
|     .stat-number { | ||||
|       font-size: 20px; | ||||
|       font-weight: 600; | ||||
|       &.text-warning { | ||||
|         color: #e6a23c; | ||||
|       } | ||||
|     } | ||||
|     .stat-label { | ||||
|       color: #606266; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .product-item { | ||||
|     display: flex; | ||||
|     align-items: center; | ||||
|     padding: 20px 0; | ||||
|     &.border-top { | ||||
|       border-top: 1px solid #ebeef5; | ||||
|     } | ||||
| 
 | ||||
|     .product-img { | ||||
|       width: 80px; | ||||
|       height: 80px; | ||||
|       object-fit: cover; | ||||
|       border-radius: 12px; | ||||
|       margin-right: 20px; | ||||
|     } | ||||
| 
 | ||||
|     .product-info { | ||||
|       flex: 1; | ||||
| 
 | ||||
|       .product-header { | ||||
|         display: flex; | ||||
|         align-items: center; | ||||
|         margin-bottom: 12px; | ||||
| 
 | ||||
|         .product-name { | ||||
|           margin-left: 12px; | ||||
|           font-weight: 500; | ||||
|           font-size: 16px; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       .product-details { | ||||
|         display: grid; | ||||
|         grid-template-columns: repeat(3, 1fr); | ||||
|         gap: 20px; | ||||
| 
 | ||||
|         .detail-item { | ||||
|           label { | ||||
|             color: #909399; | ||||
|           } | ||||
|           .text-expire { | ||||
|             color: #e6a23c; | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| 
 | ||||
|     .el-button { | ||||
|       align-self: flex-end; | ||||
|       margin-left: 20px; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .mb-24 { | ||||
|     margin-bottom: 24px; | ||||
|   } | ||||
| } | ||||
| </style> | ||||
| @ -1,13 +1,12 @@ | ||||
| <template> | ||||
|   <div class="usage-monitor"> | ||||
|     <!-- 顶部 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> | ||||
| 
 | ||||
|     <el-tabs v-model="activeTab" class="tabs-wrapper"> | ||||
|       <el-tab-pane label="在售中" name="onSale" /> | ||||
|       <el-tab-pane label="未上架" name="offShelf" /> | ||||
|       <el-tab-pane label="已失效" name="expired" /> | ||||
|     </el-tabs> | ||||
| 
 | ||||
|     <!-- 列表内容 --> | ||||
|     <div class="list-wrapper"> | ||||
| @ -19,20 +18,17 @@ | ||||
|         <div class="item-info"> | ||||
|           <div class="item-name">{{ p.name }}</div> | ||||
|           <div class="item-stats">月售 {{ p.monthlySales }} · 库存 {{ p.stock }}</div> | ||||
|           <div class="item-price">¥ {{ p.price }} /kg</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 class="item-buttom"> | ||||
|           <div class="item-status" :class="statusClass(activeTab)"> | ||||
|             {{ tabLabels[activeTab] }} | ||||
|           </div> | ||||
|           <div class="item-actions"> | ||||
|             <el-button size="large" class="button" @click="onInspect(p)">抽查</el-button> | ||||
|             <el-button size="large" class="button" type="danger" @click="onRevoke(p)">取消授权</el-button> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
| @ -41,6 +37,8 @@ | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref, computed } from 'vue'; | ||||
| import { getAssetsFile } from '@/utils/index.js'; | ||||
| import { getMonitorList } from '@/apis/brand'; | ||||
| 
 | ||||
| const activeTab = ref('onSale'); | ||||
| 
 | ||||
| @ -55,7 +53,7 @@ const products = ref([ | ||||
|   { | ||||
|     id: 1, | ||||
|     name: '耿马镇沙疆西红柿', | ||||
|     img: 'https://via.placeholder.com/80', | ||||
|     img: getAssetsFile('images/brand/product4.png'), | ||||
|     monthlySales: 999, | ||||
|     stock: 10000, | ||||
|     price: 3.0, | ||||
| @ -64,7 +62,7 @@ const products = ref([ | ||||
|   { | ||||
|     id: 2, | ||||
|     name: '耿马镇沙疆土豆', | ||||
|     img: 'https://via.placeholder.com/80', | ||||
|     img: getAssetsFile('images/brand/product6.png'), | ||||
|     monthlySales: 123, | ||||
|     stock: 5000, | ||||
|     price: 2.5, | ||||
| @ -73,7 +71,7 @@ const products = ref([ | ||||
|   { | ||||
|     id: 3, | ||||
|     name: '彩椒南瓜混合', | ||||
|     img: 'https://via.placeholder.com/80', | ||||
|     img: getAssetsFile('images/brand/product1.png'), | ||||
|     monthlySales: 456, | ||||
|     stock: 8000, | ||||
|     price: 4.2, | ||||
| @ -105,42 +103,42 @@ const statusClass = (tab) => { | ||||
| .usage-monitor { | ||||
|   padding: 20px; | ||||
|   background: #fff; | ||||
|   border-radius: 16px; | ||||
|   height: 100%; | ||||
| 
 | ||||
|   .tabs-wrapper { | ||||
|     width: 100%; | ||||
|     display: flex; | ||||
|     justify-content: center; | ||||
|     margin-bottom: 24px; | ||||
|     align-items: center; | ||||
|     background-color: #fff; | ||||
| 
 | ||||
|     .centered-tabs { | ||||
|       width: 600px; /* 根据实际需要调整宽度 */ | ||||
|       .el-tabs__header { | ||||
|         justify-content: center; | ||||
|       } | ||||
|     :deep(.el-tabs__item) { | ||||
|       font-size: 24px; | ||||
|       font-weight: 700; | ||||
|       // border: 1 solid #f000; | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .list-wrapper { | ||||
|     .list-item { | ||||
|       display: grid; | ||||
|       grid-template-columns: 80px 1fr auto auto 80px; | ||||
|       display: flex; | ||||
|       justify-content: start; | ||||
|       align-items: center; | ||||
|       padding: 16px 0; | ||||
|       &.has-border { | ||||
|         border-top: 1px solid #ebeef5; | ||||
|       } | ||||
|       padding: 20px 0; | ||||
| 
 | ||||
|       .item-img { | ||||
|         width: 80px; | ||||
|         height: 80px; | ||||
|         width: 120px; | ||||
|         height: 120px; | ||||
|         object-fit: cover; | ||||
|         border-radius: 8px; | ||||
|       } | ||||
| 
 | ||||
|       .item-info { | ||||
|         padding-left: 16px; | ||||
|         // background-color: #909399; | ||||
|         .item-name { | ||||
|           font-size: 16px; | ||||
|           font-weight: 500; | ||||
|           font-size: 20px; | ||||
|           font-weight: 700; | ||||
|           margin-bottom: 8px; | ||||
|         } | ||||
|         .item-stats { | ||||
| @ -150,21 +148,37 @@ const statusClass = (tab) => { | ||||
|       } | ||||
| 
 | ||||
|       .item-price { | ||||
|         font-size: 18px; | ||||
|         font-weight: 600; | ||||
|         font-size: 28px; | ||||
|         font-weight: 700; | ||||
|         color: #67c23a; | ||||
|         text-align: right; | ||||
|         padding: 0 16px; | ||||
|         text-align: left; | ||||
|         padding-top: 8px; | ||||
|       } | ||||
| 
 | ||||
|       .item-buttom { | ||||
|         display: flex; | ||||
|         flex-direction: column; | ||||
|         justify-content: space-between; | ||||
|         height: 110px; | ||||
|         flex: 1; | ||||
|       } | ||||
| 
 | ||||
|       .item-actions { | ||||
|         display: flex; | ||||
|         justify-content: flex-end; | ||||
|         gap: 8px; | ||||
| 
 | ||||
|         .button { | ||||
|           font-size: 20px; | ||||
|           font-weight: 400; | ||||
|           border-radius: 8px; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       .item-status { | ||||
|         text-align: right; | ||||
|         font-size: 14px; | ||||
|         font-size: 20px; | ||||
|         font-weight: 700; | ||||
|         &.text-success { | ||||
|           color: #67c23a; | ||||
|         } | ||||
| @ -3,50 +3,51 @@ | ||||
|     <el-container class="brand-layout-container"> | ||||
|       <el-aside class="brand-aside-menu"> | ||||
|         <!-- 菜单部分 --> | ||||
|         <el-menu v-model:default-active="activeMenu" class="aside-menu" @select="handleMenuSelect"> | ||||
|           <el-menu-item index="1"> | ||||
|             <el-icon><Document /></el-icon> | ||||
|         <el-menu :default-active="activeMenu" class="aside-menu" @select="handleSelect"> | ||||
|           <el-menu-item index="apply"> | ||||
|             <img :src="getAssetsFile('images/brand/Apply.png')" class="menu-icon" alt="申请图标" /> | ||||
|             <span>使用申请</span> | ||||
|           </el-menu-item> | ||||
| 
 | ||||
|           <el-menu-item index="2"> | ||||
|             <el-icon><Lock /></el-icon> | ||||
|           <el-menu-item index="auth"> | ||||
|             <img :src="getAssetsFile('images/brand/autho.png')" class="menu-icon" alt="" /> | ||||
|             <span>授权管理</span> | ||||
|           </el-menu-item> | ||||
| 
 | ||||
|           <el-menu-item index="3"> | ||||
|             <el-icon><Monitor /></el-icon> | ||||
|           <el-menu-item index="monitor"> | ||||
|             <img :src="getAssetsFile('images/brand/supervision.png')" class="menu-icon" alt="" /> | ||||
|             <span>使用监管</span> | ||||
|           </el-menu-item> | ||||
|         </el-menu> | ||||
|       </el-aside> | ||||
| 
 | ||||
|       <el-main class="brand-main"> | ||||
|         <component :is="currentComponent" /> | ||||
|         <router-view /> | ||||
|       </el-main> | ||||
|     </el-container> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { Document, Lock, Monitor } from '@element-plus/icons-vue'; | ||||
| import { ref, shallowRef } from 'vue'; | ||||
| import ApplyManagement from './components/ApplyManagement.vue'; | ||||
| import AuthManagement from './components/AuthManagement.vue'; | ||||
| import UsageMonitor from './components/UsageMonitor.vue'; | ||||
| // 响应式状态 | ||||
| const activeMenu = ref('1'); | ||||
| const currentComponent = shallowRef(ApplyManagement); | ||||
| import { computed } from 'vue'; | ||||
| import { useRoute, useRouter } from 'vue-router'; | ||||
| import { getAssetsFile } from '@/utils/index.js'; | ||||
| 
 | ||||
| const router = useRouter(); | ||||
| const route = useRoute(); | ||||
| 
 | ||||
| // 激活菜单项 | ||||
| const activeMenu = computed(() => { | ||||
|   const path = route.path; | ||||
|   if (path.includes('/apply')) return 'apply'; | ||||
|   if (path.includes('/auth')) return 'auth'; | ||||
|   if (path.includes('/monitor')) return 'monitor'; | ||||
|   return ''; | ||||
| }); | ||||
| // 菜单切换处理 | ||||
| const handleMenuSelect = (index) => { | ||||
|   const components = { | ||||
|     1: ApplyManagement, | ||||
|     2: AuthManagement, | ||||
|     3: UsageMonitor, | ||||
|   }; | ||||
|   currentComponent.value = components[index]; | ||||
| }; | ||||
| function handleSelect(index) { | ||||
|   router.push(`/sub-operation-service/brand/${index}`); | ||||
| } | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| @ -69,6 +70,9 @@ const handleMenuSelect = (index) => { | ||||
|           line-height: 48px; | ||||
|           margin: 4px 8px; | ||||
|           border-radius: 4px; | ||||
|           font-size: 20px; | ||||
|           font-weight: 400; | ||||
|           text-align: left; | ||||
|           &:hover { | ||||
|             background-color: #f5f7fa; | ||||
|           } | ||||
| @ -78,6 +82,12 @@ const handleMenuSelect = (index) => { | ||||
|             font-size: 18px; | ||||
|             vertical-align: middle; | ||||
|           } | ||||
|           .menu-icon { | ||||
|             width: 1.5em; | ||||
|             height: 1.5em; | ||||
|             margin-right: 8px; | ||||
|             vertical-align: -0.15em; | ||||
|           } | ||||
|           span { | ||||
|             vertical-align: middle; | ||||
|           } | ||||
|  | ||||