使用申请
							
								
								
									
										23
									
								
								sub-operation-service/src/apis/products.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @ -0,0 +1,23 @@ | ||||
| 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: 61 KiB After Width: | Height: | Size: 61 KiB | 
| Before Width: | Height: | Size: 55 KiB After Width: | Height: | Size: 55 KiB | 
| Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB | 
| Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB | 
| Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB | 
| Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB | 
| Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB | 
| Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 62 KiB | 
| Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB | 
| Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB | 
| Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB | 
| Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB | 
| Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB | 
| Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB | 
| Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB | 
| Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB | 
| @ -1,67 +1,100 @@ | ||||
| <template> | ||||
|   <el-page-header> | ||||
|     <template #breadcrumb> | ||||
|       <el-breadcrumb separator="·"> | ||||
|         <el-breadcrumb-item :to="{ path: './page-header.html' }"> 使用申请 </el-breadcrumb-item> | ||||
|         <el-breadcrumb-item>我要申请</el-breadcrumb-item> | ||||
|       </el-breadcrumb> | ||||
|     </template> | ||||
|   </el-page-header> | ||||
|   <el-space class="content-box" wrap> | ||||
|     <el-card v-for="o in 12" :key="o" class="box-card"> | ||||
|       <div style="height: 100%" class="flex-clomn"> | ||||
|         <img :src="url" alt="" class="img" /> | ||||
|         <p>耿马绿色蔬菜</p> | ||||
|         <el-button class="button">我要申请</el-button> | ||||
|   <el-row :gutter="20" class="content-box"> | ||||
|     <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" /> | ||||
|           <div class="flex-1 flex-around"> | ||||
|             <p>{{ product.name }}</p> | ||||
|             <el-button type="success" class="button">我要申请</el-button> | ||||
|           </div> | ||||
|         </div> | ||||
|       </el-card> | ||||
|   </el-space> | ||||
|     </el-col> | ||||
|   </el-row> | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| const goBack = () => { | ||||
|   console.log('go back'); | ||||
| import { ref, onMounted } from 'vue'; | ||||
| import productsApi from '@/apis/products'; | ||||
| import { getAssetsFile } from '@/utils/index.js'; | ||||
| 
 | ||||
| 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), // 确保图片路径正确 | ||||
|       }; | ||||
|     }); | ||||
| 
 | ||||
|     products.value = processedData; | ||||
|   } catch (error) { | ||||
|     console.error('获取商品数据失败:', error); | ||||
|   } | ||||
| }; | ||||
| 
 | ||||
| // 组件挂载时获取数据 | ||||
| onMounted(() => { | ||||
|   fetchProducts(); | ||||
| }); | ||||
| </script> | ||||
| 
 | ||||
| <style scoped lang="scss"> | ||||
| .content-box { | ||||
|   margin: 0; | ||||
|   padding: 0; | ||||
|   box-sizing: border-box; | ||||
|   row-gap: 20px; | ||||
| } | ||||
| 
 | ||||
|   .box-card { | ||||
|     box-shadow: none; | ||||
|     width: 224px; | ||||
| .box-card { | ||||
|   width: 100%; | ||||
|   height: 334px; | ||||
|     background: #ffffff; | ||||
|   border-radius: 16px; | ||||
|     padding: 8; | ||||
|   padding: 0; | ||||
|   box-shadow: none; | ||||
| 
 | ||||
|     .flex-clomn { | ||||
|   .flex-column { | ||||
|     height: 100%; | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|       gap: 8; | ||||
|     justify-content: space-between; | ||||
|     align-items: center; | ||||
|     padding: 0; | ||||
|   } | ||||
|     p { | ||||
|       text-align: center; | ||||
| 
 | ||||
|   .flex-around { | ||||
|     display: flex; | ||||
|     flex-direction: column; | ||||
|     justify-content: space-around; | ||||
|     align-items: center; | ||||
|   } | ||||
| 
 | ||||
|   .flex-1 { | ||||
|     flex: 1; | ||||
|   } | ||||
| 
 | ||||
|   .flex-column p { | ||||
|     margin: 0; | ||||
|     font-size: 20px; | ||||
|     font-weight: 700; | ||||
|   } | ||||
| 
 | ||||
|   .img { | ||||
|       width: 182px; | ||||
|       height: 182px; | ||||
|     width: 100%; | ||||
|     aspect-ratio: 1 / 1; | ||||
|     object-fit: cover; | ||||
|     border-radius: 8px; | ||||
|   } | ||||
| 
 | ||||
|   .button { | ||||
|     width: 96px; | ||||
|     height: 40px; | ||||
|       background: #25bf82; | ||||
|       border-radius: 8px; | ||||
|       align-self: center; | ||||
|       color: #fff; | ||||
|   } | ||||
|   } | ||||
|   // .content-box::-webkit-scrollbar { | ||||
|   //   display: none; /* 隐藏滚动条 */ | ||||
|   // } | ||||
| } | ||||
| </style> | ||||
|  | ||||
| @ -1,179 +1,180 @@ | ||||
| <template> | ||||
|   <div class="usage-monitor"> | ||||
|     <!-- 状态筛选 --> | ||||
|     <el-tabs v-model="activeStatus" class="mb-24"> | ||||
|     <!-- 顶部 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="notListed" /> | ||||
|         <el-tab-pane label="未上架" name="offShelf" /> | ||||
|         <el-tab-pane label="已失效" name="expired" /> | ||||
|       </el-tabs> | ||||
| 
 | ||||
|     <!-- 商品列表 --> | ||||
|     <el-row :gutter="16"> | ||||
|       <el-col v-for="product in filteredProducts" :key="product.id" :xs="24" :sm="12" :md="8" :lg="6" class="mb-16"> | ||||
|         <el-card class="product-card"> | ||||
|           <!-- 商品状态 --> | ||||
|           <div class="status-tag"> | ||||
|             <el-tag :type="statusMap[product.status]" size="small"> | ||||
|               {{ product.statusLabel }} | ||||
|             </el-tag> | ||||
|     </div> | ||||
| 
 | ||||
|           <!-- 商品信息 --> | ||||
|           <div class="product-content"> | ||||
|             <h4 class="product-name">{{ product.name }}</h4> | ||||
|     <!-- 列表内容 --> | ||||
|     <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="sales-info"> | ||||
|               <div class="data-item"> | ||||
|                 <span class="label">月售</span> | ||||
|                 <span class="value">{{ product.monthlySales }}</span> | ||||
|               </div> | ||||
|               <div class="data-item"> | ||||
|                 <span class="label">库存</span> | ||||
|                 <span class="value">{{ product.stock }}</span> | ||||
|               </div> | ||||
|         <!-- 名称 + 月售/库存 --> | ||||
|         <div class="item-info"> | ||||
|           <div class="item-name">{{ p.name }}</div> | ||||
|           <div class="item-stats">月售 {{ p.monthlySales }} · 库存 {{ p.stock }}</div> | ||||
|         </div> | ||||
| 
 | ||||
|             <div class="price"> | ||||
|               {{ product.price }} | ||||
|             </div> | ||||
|           </div> | ||||
|         <!-- 价格 --> | ||||
|         <div class="item-price">¥ {{ p.price }} /kg</div> | ||||
| 
 | ||||
|         <!-- 操作按钮 --> | ||||
|           <div class="product-actions"> | ||||
|             <el-button v-if="product.status !== 'expired'" size="small" @click="handleInspect(product)">抽查</el-button> | ||||
|             <el-button v-if="product.status === 'onSale'" size="small" type="danger" plain @click="handleRevoke(product)">取消授权</el-button> | ||||
|         <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> | ||||
|         </el-card> | ||||
|       </el-col> | ||||
|     </el-row> | ||||
|   </div> | ||||
| </template> | ||||
| 
 | ||||
| <script setup> | ||||
| import { ref, computed } from 'vue'; | ||||
| 
 | ||||
| const activeStatus = ref('onSale'); | ||||
| const activeTab = ref('onSale'); | ||||
| 
 | ||||
| // 状态映射配置,用于 el-tag 的样式 | ||||
| const statusMap = { | ||||
|   onSale: 'success', | ||||
|   notListed: 'info', | ||||
|   expired: 'danger', | ||||
| const tabLabels = { | ||||
|   onSale: '在售中', | ||||
|   offShelf: '未上架', | ||||
|   expired: '已失效', | ||||
| }; | ||||
| 
 | ||||
| // 商品数据,这里保持与原型图中的展示一致 | ||||
| // 示例数据,替换为真实接口数据 | ||||
| const products = ref([ | ||||
|   { | ||||
|     id: 1, | ||||
|     name: '耿马镇沙瓢西红柿', | ||||
|     name: '耿马镇沙疆西红柿', | ||||
|     img: 'https://via.placeholder.com/80', | ||||
|     monthlySales: 999, | ||||
|     stock: 10000, | ||||
|     price: '¥3.0/kg', | ||||
|     price: 3.0, | ||||
|     status: 'onSale', | ||||
|     statusLabel: '在售中', | ||||
|   }, | ||||
|   { | ||||
|     id: 2, | ||||
|     name: '昭通乡土黄瓜', | ||||
|     monthlySales: 750, | ||||
|     stock: 8500, | ||||
|     price: '¥2.5/kg', | ||||
|     name: '耿马镇沙疆土豆', | ||||
|     img: 'https://via.placeholder.com/80', | ||||
|     monthlySales: 123, | ||||
|     stock: 5000, | ||||
|     price: 2.5, | ||||
|     status: 'onSale', | ||||
|     statusLabel: '在售中', | ||||
|   }, | ||||
|   { | ||||
|     id: 3, | ||||
|     name: '昆明有机苹果', | ||||
|     monthlySales: 450, | ||||
|     stock: 5000, | ||||
|     price: '¥6.0/kg', | ||||
|     status: 'notListed', // 修改为 notListed,对应“未上架” | ||||
|     statusLabel: '未上架', | ||||
|   }, | ||||
|   { | ||||
|     id: 4, | ||||
|     name: '楚雄散养鸡蛋', | ||||
|     monthlySales: 1200, | ||||
|     stock: 20000, | ||||
|     price: '¥8.0/斤', | ||||
|     status: 'onSale', | ||||
|     statusLabel: '在售中', | ||||
|     name: '彩椒南瓜混合', | ||||
|     img: 'https://via.placeholder.com/80', | ||||
|     monthlySales: 456, | ||||
|     stock: 8000, | ||||
|     price: 4.2, | ||||
|     status: 'offShelf', | ||||
|   }, | ||||
|   // … 更多数据 | ||||
| ]); | ||||
| 
 | ||||
| // 根据当前选择状态过滤商品列表 | ||||
| const filteredProducts = computed(() => { | ||||
|   return products.value.filter((item) => item.status === activeStatus.value); | ||||
| }); | ||||
| // 根据当前 Tab 过滤 | ||||
| const filteredProducts = computed(() => products.value.filter((p) => p.status === activeTab.value)); | ||||
| 
 | ||||
| // 操作处理逻辑 | ||||
| const handleInspect = (product) => { | ||||
|   console.log('抽查商品:', product); | ||||
| // 操作回调 | ||||
| const onInspect = (p) => { | ||||
|   console.log('抽查商品', p); | ||||
| }; | ||||
| const onRevoke = (p) => { | ||||
|   console.log('取消授权', p); | ||||
| }; | ||||
| 
 | ||||
| const handleRevoke = (product) => { | ||||
|   console.log('取消授权:', product); | ||||
| // 状态文字的颜色 | ||||
| const statusClass = (tab) => { | ||||
|   if (tab === 'offShelf') return 'text-warning'; | ||||
|   if (tab === 'expired') return 'text-danger'; | ||||
|   return 'text-success'; | ||||
| }; | ||||
| </script> | ||||
| 
 | ||||
| <style lang="scss" scoped> | ||||
| <style scoped lang="scss"> | ||||
| .usage-monitor { | ||||
|   padding: 20px; | ||||
|   background: #fff; | ||||
| 
 | ||||
|   .mb-24 { | ||||
|     margin-bottom: 24px; | ||||
|   } | ||||
| 
 | ||||
|   .product-card { | ||||
|     position: relative; | ||||
|     margin-bottom: 16px; | ||||
|     transition: box-shadow 0.3s; | ||||
| 
 | ||||
|     &:hover { | ||||
|       box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); | ||||
|     } | ||||
| 
 | ||||
|     .status-tag { | ||||
|       position: absolute; | ||||
|       top: 12px; | ||||
|       right: 12px; | ||||
|     } | ||||
| 
 | ||||
|     .product-content { | ||||
|       .product-name { | ||||
|         margin: 0 0 12px; | ||||
|         font-size: 16px; | ||||
|         color: #303133; | ||||
|       } | ||||
| 
 | ||||
|       .sales-info { | ||||
|   .tabs-wrapper { | ||||
|     display: flex; | ||||
|         gap: 20px; | ||||
|         margin-bottom: 12px; | ||||
|     justify-content: center; | ||||
|     margin-bottom: 24px; | ||||
| 
 | ||||
|         .data-item { | ||||
|           .label { | ||||
|             color: #909399; | ||||
|             margin-right: 4px; | ||||
|     .centered-tabs { | ||||
|       width: 600px; /* 根据实际需要调整宽度 */ | ||||
|       .el-tabs__header { | ||||
|         justify-content: center; | ||||
|       } | ||||
|           .value { | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   .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; | ||||
|       } | ||||
| 
 | ||||
|       .item-img { | ||||
|         width: 80px; | ||||
|         height: 80px; | ||||
|         object-fit: cover; | ||||
|         border-radius: 8px; | ||||
|       } | ||||
| 
 | ||||
|       .item-info { | ||||
|         padding-left: 16px; | ||||
|         .item-name { | ||||
|           font-size: 16px; | ||||
|           font-weight: 500; | ||||
|           margin-bottom: 8px; | ||||
|         } | ||||
|         .item-stats { | ||||
|           color: #909399; | ||||
|           font-size: 14px; | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       .price { | ||||
|         color: #f56c6c; | ||||
|       .item-price { | ||||
|         font-size: 18px; | ||||
|         font-weight: 600; | ||||
|       } | ||||
|         color: #67c23a; | ||||
|         text-align: right; | ||||
|         padding: 0 16px; | ||||
|       } | ||||
| 
 | ||||
|     .product-actions { | ||||
|       margin-top: 16px; | ||||
|       .item-actions { | ||||
|         display: flex; | ||||
|         gap: 8px; | ||||
|       justify-content: flex-end; | ||||
|       } | ||||
| 
 | ||||
|       .item-status { | ||||
|         text-align: right; | ||||
|         font-size: 14px; | ||||
|         &.text-success { | ||||
|           color: #67c23a; | ||||
|         } | ||||
|         &.text-warning { | ||||
|           color: #e6a23c; | ||||
|         } | ||||
|         &.text-danger { | ||||
|           color: #f56c6c; | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -6,7 +6,7 @@ | ||||
|         <el-menu v-model:default-active="activeMenu" class="aside-menu" @select="handleMenuSelect"> | ||||
|           <el-menu-item index="1"> | ||||
|             <el-icon><Document /></el-icon> | ||||
|             <span>申请</span> | ||||
|             <span>使用申请</span> | ||||
|           </el-menu-item> | ||||
| 
 | ||||
|           <el-menu-item index="2"> | ||||
|  | ||||