| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æ¥è¡¨éæ©å¨ --> |
| | | <el-card class="report-selector" shadow="never"> |
| | | <el-tabs v-model="activeReport" @tab-change="handleReportChange"> |
| | | <el-tab-pane label="éè´è®¢åæ§è¡æ±æ»è¡¨" name="orderSummary"> |
| | | <template #label> |
| | | <span class="tab-label"> |
| | | <el-icon><Document /></el-icon> |
| | | éè´è®¢åæ§è¡æ±æ»è¡¨ |
| | | </span> |
| | | </template> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="éè´è®¢åæ§è¡æç»è¡¨" name="orderDetail"> |
| | | <template #label> |
| | | <span class="tab-label"> |
| | | <el-icon><List /></el-icon> |
| | | éè´è®¢åæ§è¡æç»è¡¨ |
| | | </span> |
| | | </template> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="éè´ä¸å¡æ±æ»è¡¨" name="businessSummary"> |
| | | <template #label> |
| | | <span class="tab-label"> |
| | | <el-icon><TrendCharts /></el-icon> |
| | | éè´ä¸å¡æ±æ»è¡¨ |
| | | </span> |
| | | </template> |
| | | </el-tab-pane> |
| | | <el-tab-pane label="ä¾åºåä¾è´§æ±æ»è¡¨" name="supplierSummary"> |
| | | <template #label> |
| | | <span class="tab-label"> |
| | | <el-icon><Shop /></el-icon> |
| | | ä¾åºåä¾è´§æ±æ»è¡¨ |
| | | </span> |
| | | </template> |
| | | </el-tab-pane> |
| | | </el-tabs> |
| | | </el-card> |
| | | |
| | | <!-- æ¥è¯¢æ¡ä»¶ --> |
| | | <el-card class="search-card" shadow="never"> |
| | | <el-form :model="searchForm" :inline="true" class="search-form"> |
| | | <el-form-item label="æ¶é´èå´ï¼"> |
| | | <el-date-picker |
| | | v-model="searchForm.dateRange" |
| | | type="daterange" |
| | | range-separator="è³" |
| | | start-placeholder="å¼å§æ¥æ" |
| | | end-placeholder="ç»ææ¥æ" |
| | | format="YYYY-MM-DD" |
| | | value-format="YYYY-MM-DD" |
| | | style="width: 240px" |
| | | /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¾åºåï¼" v-if="activeReport === 'supplierSummary'"> |
| | | <el-select v-model="searchForm.supplierId" placeholder="è¯·éæ©ä¾åºå" clearable style="width: 200px"> |
| | | <el-option |
| | | v-for="supplier in supplierList" |
| | | :key="supplier.id" |
| | | :label="supplier.name" |
| | | :value="supplier.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item label="ååç±»å«ï¼" v-if="activeReport === 'businessSummary'"> |
| | | <el-select v-model="searchForm.categoryId" placeholder="è¯·éæ©ååç±»å«" clearable style="width: 200px"> |
| | | <el-option |
| | | v-for="category in categoryList" |
| | | :key="category.id" |
| | | :label="category.name" |
| | | :value="category.id" |
| | | /> |
| | | </el-select> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="handleSearch" :loading="loading"> |
| | | <el-icon><Search /></el-icon> |
| | | æ¥è¯¢ |
| | | </el-button> |
| | | <el-button @click="resetSearch"> |
| | | <el-icon><Refresh /></el-icon> |
| | | éç½® |
| | | </el-button> |
| | | <el-button type="success" @click="exportReport"> |
| | | <el-icon><Download /></el-icon> |
| | | å¯¼åº |
| | | </el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | </el-card> |
| | | |
| | | <!-- æ¥è¡¨å
容 --> |
| | | <el-card class="report-content" shadow="never"> |
| | | <!-- éè´è®¢åæ§è¡æ±æ»è¡¨ --> |
| | | <div v-if="activeReport === 'orderSummary'" class="report-section"> |
| | | <div class="section-header"> |
| | | <h3>éè´è®¢åæ§è¡æ±æ»è¡¨</h3> |
| | | <div class="summary-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æ»è®¢åæ°ï¼</span> |
| | | <span class="stat-value">{{ orderSummaryStats.totalOrders }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æ»éé¢ï¼</span> |
| | | <span class="stat-value">Â¥{{ orderSummaryStats.totalAmount.toLocaleString() }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">宿çï¼</span> |
| | | <span class="stat-value">{{ orderSummaryStats.completionRate }}%</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table :data="orderSummaryData" border v-loading="loading" stripe> |
| | | <el-table-column label="订åç¼å·" prop="orderNo" width="180" fixed="left" /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" width="150" /> |
| | | <el-table-column label="è®¢åæ¥æ" prop="orderDate" width="120" /> |
| | | <el-table-column label="计å交æ" prop="plannedDelivery" width="120" /> |
| | | <el-table-column label="å®é
交æ" prop="actualDelivery" width="120" /> |
| | | <el-table-column label="订åéé¢" prop="orderAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.orderAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å·²ä»éé¢" prop="paidAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.paidAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å®æç¶æ" prop="status" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="宿ç" prop="completionRate" width="100"> |
| | | <template #default="{ row }">{{ row.completionRate }}%</template> |
| | | </el-table-column> |
| | | <el-table-column label="å»¶è¿å¤©æ°" prop="delayDays" width="100"> |
| | | <template #default="{ row }"> |
| | | <span :class="{ 'delay-text': row.delayDays > 0 }">{{ row.delayDays }}</span> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- éè´è®¢åæ§è¡æç»è¡¨ --> |
| | | <div v-if="activeReport === 'orderDetail'" class="report-section"> |
| | | <div class="section-header"> |
| | | <h3>éè´è®¢åæ§è¡æç»è¡¨</h3> |
| | | <div class="summary-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">æç»æ¡æ°ï¼</span> |
| | | <span class="stat-value">{{ orderDetailStats.totalItems }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">å·²æ¶è´§ï¼</span> |
| | | <span class="stat-value">{{ orderDetailStats.receivedItems }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">å¾
æ¶è´§ï¼</span> |
| | | <span class="stat-value">{{ orderDetailStats.pendingItems }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table :data="orderDetailData" border v-loading="loading" stripe> |
| | | <el-table-column label="订åç¼å·" prop="orderNo" width="150" fixed="left" /> |
| | | <el-table-column label="ååç¼ç " prop="productCode" width="120" /> |
| | | <el-table-column label="åååç§°" prop="productName" width="200" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specification" width="150" /> |
| | | <el-table-column label="åä½" prop="unit" width="80" /> |
| | | <el-table-column label="è®¡åæ°é" prop="plannedQuantity" width="100" /> |
| | | <el-table-column label="å·²æ¶è´§æ°é" prop="receivedQuantity" width="120" /> |
| | | <el-table-column label="å¾
æ¶è´§æ°é" prop="pendingQuantity" width="120" /> |
| | | <el-table-column label="åä»·" prop="unitPrice" width="100"> |
| | | <template #default="{ row }">Â¥{{ row.unitPrice.toFixed(2) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å°è®¡" prop="subtotal" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.subtotal.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¶è´§ç¶æ" prop="status" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getReceiptStatusType(row.status)">{{ getReceiptStatusText(row.status) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æåæ¶è´§æ¥æ" prop="lastReceiptDate" width="120" /> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- éè´ä¸å¡æ±æ»è¡¨ --> |
| | | <div v-if="activeReport === 'businessSummary'" class="report-section"> |
| | | <div class="section-header"> |
| | | <h3>éè´ä¸å¡æ±æ»è¡¨</h3> |
| | | <div class="summary-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">éè´æ»é¢ï¼</span> |
| | | <span class="stat-value">Â¥{{ businessSummaryStats.totalAmount.toLocaleString() }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">ååç§ç±»ï¼</span> |
| | | <span class="stat-value">{{ businessSummaryStats.productTypes }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">ä¾åºåæ°ï¼</span> |
| | | <span class="stat-value">{{ businessSummaryStats.supplierCount }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table :data="businessSummaryData" border v-loading="loading" stripe> |
| | | <el-table-column label="ååç±»å«" prop="category" width="150" fixed="left" /> |
| | | <el-table-column label="ååç¼ç " prop="productCode" width="120" /> |
| | | <el-table-column label="åååç§°" prop="productName" width="200" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specification" width="150" /> |
| | | <el-table-column label="éè´æ°é" prop="purchaseQuantity" width="120" /> |
| | | <el-table-column label="éè´éé¢" prop="purchaseAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.purchaseAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å¹³ååä»·" prop="avgPrice" width="100"> |
| | | <template #default="{ row }">Â¥{{ row.avgPrice.toFixed(2) }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="éè´æ¬¡æ°" prop="purchaseCount" width="100" /> |
| | | <el-table-column label="主è¦ä¾åºå" prop="mainSupplier" width="150" /> |
| | | <el-table-column label="æåéè´æ¥æ" prop="lastPurchaseDate" width="120" /> |
| | | </el-table> |
| | | </div> |
| | | |
| | | <!-- ä¾åºåä¾è´§æ±æ»è¡¨ --> |
| | | <div v-if="activeReport === 'supplierSummary'" class="report-section"> |
| | | <div class="section-header"> |
| | | <h3>ä¾åºåä¾è´§æ±æ»è¡¨</h3> |
| | | <div class="summary-stats"> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">ä¾åºåæ»æ°ï¼</span> |
| | | <span class="stat-value">{{ supplierSummaryStats.totalSuppliers }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">ä¾è´§æ»é¢ï¼</span> |
| | | <span class="stat-value">Â¥{{ supplierSummaryStats.totalAmount.toLocaleString() }}</span> |
| | | </div> |
| | | <div class="stat-item"> |
| | | <span class="stat-label">å¹³åè¯åï¼</span> |
| | | <span class="stat-value">{{ supplierSummaryStats.avgRating.toFixed(1) }}</span> |
| | | </div> |
| | | </div> |
| | | </div> |
| | | |
| | | <el-table :data="supplierSummaryData" border v-loading="loading" stripe> |
| | | <el-table-column label="ä¾åºåç¼ç " prop="supplierCode" width="120" fixed="left" /> |
| | | <el-table-column label="ä¾åºååç§°" prop="supplierName" width="200" /> |
| | | <el-table-column label="è系人" prop="contactPerson" width="120" /> |
| | | <el-table-column label="èç³»çµè¯" prop="phone" width="130" /> |
| | | <el-table-column label="ä¾è´§è®¢åæ°" prop="orderCount" width="120" /> |
| | | <el-table-column label="ä¾è´§éé¢" prop="supplyAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.supplyAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="å·²ä»éé¢" prop="paidAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.paidAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="æªä»éé¢" prop="unpaidAmount" width="120"> |
| | | <template #default="{ row }">Â¥{{ row.unpaidAmount.toLocaleString() }}</template> |
| | | </el-table-column> |
| | | <el-table-column label="ææ¶äº¤è´§ç" prop="onTimeRate" width="120"> |
| | | <template #default="{ row }">{{ row.onTimeRate }}%</template> |
| | | </el-table-column> |
| | | <el-table-column label="è´¨éè¯å" prop="qualityRating" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-rate v-model="row.qualityRating" disabled show-score text-color="#ff9900" /> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="åä½ç¶æ" prop="status" width="100"> |
| | | <template #default="{ row }"> |
| | | <el-tag :type="getSupplierStatusType(row.status)">{{ getSupplierStatusText(row.status) }}</el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | </div> |
| | | </el-card> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import { ref, reactive, onMounted } from 'vue' |
| | | import { ElMessage } from 'element-plus' |
| | | import { Document, List, TrendCharts, Shop, Search, Refresh, Download } from '@element-plus/icons-vue' |
| | | |
| | | // ååºå¼æ°æ® |
| | | const loading = ref(false) |
| | | const activeReport = ref('orderSummary') |
| | | |
| | | // æç´¢è¡¨å |
| | | const searchForm = reactive({ |
| | | dateRange: [], |
| | | supplierId: '', |
| | | categoryId: '' |
| | | }) |
| | | |
| | | // ä¾åºåå表 |
| | | const supplierList = ref([ |
| | | { id: 1, name: 'æ±èåèçµåç§ææéå
¬å¸' }, |
| | | { id: 2, name: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸' }, |
| | | { id: 3, name: 'æ·±å³æºè½è®¾å¤æéå
¬å¸' }, |
| | | { id: 4, name: 'åäº¬æ°ææç§ææéå
¬å¸' }, |
| | | { id: 5, name: '广å·çµåå
å¨ä»¶æéå
¬å¸' } |
| | | ]) |
| | | |
| | | // ååç±»å«å表 |
| | | const categoryList = ref([ |
| | | { id: 1, name: 'çµåå
å¨ä»¶' }, |
| | | { id: 2, name: 'æºæ¢°è®¾å¤' }, |
| | | { id: 3, name: 'åææ' }, |
| | | { id: 4, name: 'åå
¬ç¨å' }, |
| | | { id: 5, name: 'å
è£
ææ' } |
| | | ]) |
| | | |
| | | // ç»è®¡æ°æ® |
| | | const orderSummaryStats = ref({ |
| | | totalOrders: 156, |
| | | totalAmount: 2580000, |
| | | completionRate: 87.5 |
| | | }) |
| | | |
| | | const orderDetailStats = ref({ |
| | | totalItems: 1248, |
| | | receivedItems: 1089, |
| | | pendingItems: 159 |
| | | }) |
| | | |
| | | const businessSummaryStats = ref({ |
| | | totalAmount: 2580000, |
| | | productTypes: 89, |
| | | supplierCount: 25 |
| | | }) |
| | | |
| | | const supplierSummaryStats = ref({ |
| | | totalSuppliers: 25, |
| | | totalAmount: 2580000, |
| | | avgRating: 4.2 |
| | | }) |
| | | |
| | | // éè´è®¢åæ§è¡æ±æ»è¡¨æ°æ® |
| | | const orderSummaryData = ref([ |
| | | { |
| | | orderNo: 'PO20241201001', |
| | | supplierName: 'æ±èåèçµåç§ææéå
¬å¸', |
| | | orderDate: '2024-12-01', |
| | | plannedDelivery: '2024-12-15', |
| | | actualDelivery: '2024-12-14', |
| | | orderAmount: 125000, |
| | | paidAmount: 100000, |
| | | status: 'completed', |
| | | completionRate: 100, |
| | | delayDays: -1 |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201002', |
| | | supplierName: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸', |
| | | orderDate: '2024-12-02', |
| | | plannedDelivery: '2024-12-20', |
| | | actualDelivery: '2024-12-22', |
| | | orderAmount: 280000, |
| | | paidAmount: 140000, |
| | | status: 'partial', |
| | | completionRate: 75, |
| | | delayDays: 2 |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201003', |
| | | supplierName: 'æ·±å³æºè½è®¾å¤æéå
¬å¸', |
| | | orderDate: '2024-12-03', |
| | | plannedDelivery: '2024-12-25', |
| | | actualDelivery: '', |
| | | orderAmount: 180000, |
| | | paidAmount: 0, |
| | | status: 'pending', |
| | | completionRate: 0, |
| | | delayDays: 0 |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201004', |
| | | supplierName: 'åäº¬æ°ææç§ææéå
¬å¸', |
| | | orderDate: '2024-12-04', |
| | | plannedDelivery: '2024-12-18', |
| | | actualDelivery: '2024-12-18', |
| | | orderAmount: 95000, |
| | | paidAmount: 95000, |
| | | status: 'completed', |
| | | completionRate: 100, |
| | | delayDays: 0 |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201005', |
| | | supplierName: '广å·çµåå
å¨ä»¶æéå
¬å¸', |
| | | orderDate: '2024-12-05', |
| | | plannedDelivery: '2024-12-28', |
| | | actualDelivery: '', |
| | | orderAmount: 220000, |
| | | paidAmount: 0, |
| | | status: 'pending', |
| | | completionRate: 0, |
| | | delayDays: 0 |
| | | } |
| | | ]) |
| | | |
| | | // éè´è®¢åæ§è¡æç»è¡¨æ°æ® |
| | | const orderDetailData = ref([ |
| | | { |
| | | orderNo: 'PO20241201001', |
| | | productCode: 'EL001', |
| | | productName: 'çµé»å¨ 1KΩ ±5%', |
| | | specification: '1/4W 碳èçµé»', |
| | | unit: '个', |
| | | plannedQuantity: 1000, |
| | | receivedQuantity: 1000, |
| | | pendingQuantity: 0, |
| | | unitPrice: 0.15, |
| | | subtotal: 150, |
| | | status: 'completed', |
| | | lastReceiptDate: '2024-12-14' |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201001', |
| | | productCode: 'EL002', |
| | | productName: 'çµå®¹å¨ 100μF', |
| | | specification: '25V éçµè§£çµå®¹', |
| | | unit: '个', |
| | | plannedQuantity: 500, |
| | | receivedQuantity: 500, |
| | | pendingQuantity: 0, |
| | | unitPrice: 0.85, |
| | | subtotal: 425, |
| | | status: 'completed', |
| | | lastReceiptDate: '2024-12-14' |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201002', |
| | | productCode: 'ME001', |
| | | productName: 'ç²¾å¯è½´æ¿', |
| | | specification: '6205-2RS æ·±æ²çè½´æ¿', |
| | | unit: '个', |
| | | plannedQuantity: 200, |
| | | receivedQuantity: 150, |
| | | pendingQuantity: 50, |
| | | unitPrice: 25.5, |
| | | subtotal: 5100, |
| | | status: 'partial', |
| | | lastReceiptDate: '2024-12-20' |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201002', |
| | | productCode: 'ME002', |
| | | productName: 'ä¸éé¢èºä¸', |
| | | specification: 'M8Ã20 304ä¸éé¢', |
| | | unit: '个', |
| | | plannedQuantity: 1000, |
| | | receivedQuantity: 1000, |
| | | pendingQuantity: 0, |
| | | unitPrice: 0.8, |
| | | subtotal: 800, |
| | | status: 'completed', |
| | | lastReceiptDate: '2024-12-20' |
| | | }, |
| | | { |
| | | orderNo: 'PO20241201003', |
| | | productCode: 'SM001', |
| | | productName: 'æºè½ä¼ æå¨', |
| | | specification: 'æ¸©åº¦ä¼ æå¨ DS18B20', |
| | | unit: '个', |
| | | plannedQuantity: 300, |
| | | receivedQuantity: 0, |
| | | pendingQuantity: 300, |
| | | unitPrice: 12.5, |
| | | subtotal: 3750, |
| | | status: 'pending', |
| | | lastReceiptDate: '' |
| | | } |
| | | ]) |
| | | |
| | | // éè´ä¸å¡æ±æ»è¡¨æ°æ® |
| | | const businessSummaryData = ref([ |
| | | { |
| | | category: 'çµåå
å¨ä»¶', |
| | | productCode: 'EL001', |
| | | productName: 'çµé»å¨ 1KΩ ±5%', |
| | | specification: '1/4W 碳èçµé»', |
| | | purchaseQuantity: 5000, |
| | | purchaseAmount: 750, |
| | | avgPrice: 0.15, |
| | | purchaseCount: 8, |
| | | mainSupplier: 'æ±èåèçµåç§ææéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-01' |
| | | }, |
| | | { |
| | | category: 'çµåå
å¨ä»¶', |
| | | productCode: 'EL002', |
| | | productName: 'çµå®¹å¨ 100μF', |
| | | specification: '25V éçµè§£çµå®¹', |
| | | purchaseQuantity: 2500, |
| | | purchaseAmount: 2125, |
| | | avgPrice: 0.85, |
| | | purchaseCount: 6, |
| | | mainSupplier: 'æ±èåèçµåç§ææéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-01' |
| | | }, |
| | | { |
| | | category: 'æºæ¢°è®¾å¤', |
| | | productCode: 'ME001', |
| | | productName: 'ç²¾å¯è½´æ¿', |
| | | specification: '6205-2RS æ·±æ²çè½´æ¿', |
| | | purchaseQuantity: 800, |
| | | purchaseAmount: 20400, |
| | | avgPrice: 25.5, |
| | | purchaseCount: 4, |
| | | mainSupplier: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-02' |
| | | }, |
| | | { |
| | | category: 'æºæ¢°è®¾å¤', |
| | | productCode: 'ME002', |
| | | productName: 'ä¸éé¢èºä¸', |
| | | specification: 'M8Ã20 304ä¸éé¢', |
| | | purchaseQuantity: 5000, |
| | | purchaseAmount: 4000, |
| | | avgPrice: 0.8, |
| | | purchaseCount: 12, |
| | | mainSupplier: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-02' |
| | | }, |
| | | { |
| | | category: 'æºè½è®¾å¤', |
| | | productCode: 'SM001', |
| | | productName: 'æºè½ä¼ æå¨', |
| | | specification: 'æ¸©åº¦ä¼ æå¨ DS18B20', |
| | | purchaseQuantity: 1200, |
| | | purchaseAmount: 15000, |
| | | avgPrice: 12.5, |
| | | purchaseCount: 5, |
| | | mainSupplier: 'æ·±å³æºè½è®¾å¤æéå
¬å¸', |
| | | lastPurchaseDate: '2024-12-03' |
| | | } |
| | | ]) |
| | | |
| | | // ä¾åºåä¾è´§æ±æ»è¡¨æ°æ® |
| | | const supplierSummaryData = ref([ |
| | | { |
| | | supplierCode: 'SUP001', |
| | | supplierName: 'æ±èåèçµåç§ææéå
¬å¸', |
| | | contactPerson: 'å¼ ç»ç', |
| | | phone: '0512-88888888', |
| | | orderCount: 45, |
| | | supplyAmount: 850000, |
| | | paidAmount: 680000, |
| | | unpaidAmount: 170000, |
| | | onTimeRate: 95, |
| | | qualityRating: 4.5, |
| | | status: 'active' |
| | | }, |
| | | { |
| | | supplierCode: 'SUP002', |
| | | supplierName: '䏿µ·ç²¾å¯æºæ¢°å¶é æéå
¬å¸', |
| | | contactPerson: 'ææ»', |
| | | phone: '021-66666666', |
| | | orderCount: 32, |
| | | supplyAmount: 1200000, |
| | | paidAmount: 900000, |
| | | unpaidAmount: 300000, |
| | | onTimeRate: 88, |
| | | qualityRating: 4.2, |
| | | status: 'active' |
| | | }, |
| | | { |
| | | supplierCode: 'SUP003', |
| | | supplierName: 'æ·±å³æºè½è®¾å¤æéå
¬å¸', |
| | | contactPerson: 'çå·¥ç¨å¸', |
| | | phone: '0755-77777777', |
| | | orderCount: 28, |
| | | supplyAmount: 680000, |
| | | paidAmount: 400000, |
| | | unpaidAmount: 280000, |
| | | onTimeRate: 92, |
| | | qualityRating: 4.3, |
| | | status: 'active' |
| | | }, |
| | | { |
| | | supplierCode: 'SUP004', |
| | | supplierName: 'åäº¬æ°ææç§ææéå
¬å¸', |
| | | contactPerson: 'éå士', |
| | | phone: '010-55555555', |
| | | orderCount: 18, |
| | | supplyAmount: 320000, |
| | | paidAmount: 250000, |
| | | unpaidAmount: 70000, |
| | | onTimeRate: 85, |
| | | qualityRating: 4.0, |
| | | status: 'active' |
| | | }, |
| | | { |
| | | supplierCode: 'SUP005', |
| | | supplierName: '广å·çµåå
å¨ä»¶æéå
¬å¸', |
| | | contactPerson: 'åç»ç', |
| | | phone: '020-44444444', |
| | | orderCount: 22, |
| | | supplyAmount: 480000, |
| | | paidAmount: 200000, |
| | | unpaidAmount: 280000, |
| | | onTimeRate: 78, |
| | | qualityRating: 3.8, |
| | | status: 'warning' |
| | | } |
| | | ]) |
| | | |
| | | // æ¹æ³ |
| | | const handleReportChange = (tabName) => { |
| | | activeReport.value = tabName |
| | | handleSearch() |
| | | } |
| | | |
| | | const handleSearch = () => { |
| | | loading.value = true |
| | | // 模æAPIè°ç¨ |
| | | setTimeout(() => { |
| | | loading.value = false |
| | | ElMessage.success('æ¥è¯¢å®æ') |
| | | }, 1000) |
| | | } |
| | | |
| | | const resetSearch = () => { |
| | | Object.assign(searchForm, { |
| | | dateRange: [], |
| | | supplierId: '', |
| | | categoryId: '' |
| | | }) |
| | | handleSearch() |
| | | } |
| | | |
| | | const exportReport = () => { |
| | | ElMessage.success('导åºåè½å¼åä¸...') |
| | | } |
| | | |
| | | // ç¶æç¸å
³æ¹æ³ |
| | | const getStatusType = (status) => { |
| | | const statusMap = { |
| | | completed: 'success', |
| | | partial: 'warning', |
| | | pending: 'info' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | const getStatusText = (status) => { |
| | | const statusMap = { |
| | | completed: '已宿', |
| | | partial: 'é¨å宿', |
| | | pending: 'å¾
æ§è¡' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | |
| | | const getReceiptStatusType = (status) => { |
| | | const statusMap = { |
| | | completed: 'success', |
| | | partial: 'warning', |
| | | pending: 'info' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | const getReceiptStatusText = (status) => { |
| | | const statusMap = { |
| | | completed: 'å·²æ¶è´§', |
| | | partial: 'é¨åæ¶è´§', |
| | | pending: 'å¾
æ¶è´§' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | |
| | | const getSupplierStatusType = (status) => { |
| | | const statusMap = { |
| | | active: 'success', |
| | | warning: 'warning', |
| | | inactive: 'info' |
| | | } |
| | | return statusMap[status] || 'info' |
| | | } |
| | | |
| | | const getSupplierStatusText = (status) => { |
| | | const statusMap = { |
| | | active: 'æ£å¸¸åä½', |
| | | warning: 'éå
³æ³¨', |
| | | inactive: 'æååä½' |
| | | } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | |
| | | onMounted(() => { |
| | | // 设置é»è®¤æ¶é´èå´ä¸ºæè¿30天 |
| | | const endDate = new Date() |
| | | const startDate = new Date() |
| | | startDate.setDate(startDate.getDate() - 30) |
| | | |
| | | searchForm.dateRange = [ |
| | | startDate.toISOString().split('T')[0], |
| | | endDate.toISOString().split('T')[0] |
| | | ] |
| | | }) |
| | | </script> |
| | | |
| | | <style scoped> |
| | | .app-container { |
| | | padding: 20px; |
| | | background-color: #f5f7fa; |
| | | min-height: 100vh; |
| | | } |
| | | |
| | | .page-header { |
| | | text-align: center; |
| | | margin-bottom: 20px; |
| | | padding: 20px; |
| | | background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); |
| | | border-radius: 10px; |
| | | color: white; |
| | | } |
| | | |
| | | .page-header h2 { |
| | | margin: 0 0 10px 0; |
| | | font-size: 28px; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | .page-header p { |
| | | margin: 0; |
| | | font-size: 16px; |
| | | opacity: 0.9; |
| | | } |
| | | |
| | | .report-selector { |
| | | margin-bottom: 20px; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .tab-label { |
| | | display: flex; |
| | | align-items: center; |
| | | gap: 8px; |
| | | } |
| | | |
| | | .search-card { |
| | | margin-bottom: 20px; |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .search-form { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | .report-content { |
| | | border-radius: 8px; |
| | | } |
| | | |
| | | .report-section { |
| | | min-height: 400px; |
| | | } |
| | | |
| | | .section-header { |
| | | display: flex; |
| | | justify-content: space-between; |
| | | align-items: center; |
| | | margin-bottom: 20px; |
| | | padding-bottom: 15px; |
| | | border-bottom: 2px solid #e4e7ed; |
| | | } |
| | | |
| | | .section-header h3 { |
| | | margin: 0; |
| | | font-size: 20px; |
| | | font-weight: 600; |
| | | color: #303133; |
| | | } |
| | | |
| | | .summary-stats { |
| | | display: flex; |
| | | gap: 30px; |
| | | } |
| | | |
| | | .stat-item { |
| | | display: flex; |
| | | flex-direction: column; |
| | | align-items: center; |
| | | } |
| | | |
| | | .stat-label { |
| | | font-size: 14px; |
| | | color: #606266; |
| | | margin-bottom: 5px; |
| | | } |
| | | |
| | | .stat-value { |
| | | font-size: 18px; |
| | | font-weight: 600; |
| | | color: #409EFF; |
| | | } |
| | | |
| | | .delay-text { |
| | | color: #F56C6C; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | :deep(.el-table) { |
| | | border-radius: 8px; |
| | | overflow: hidden; |
| | | } |
| | | |
| | | :deep(.el-table th) { |
| | | background-color: #f8f9fa; |
| | | color: #606266; |
| | | font-weight: 600; |
| | | } |
| | | |
| | | :deep(.el-table--striped .el-table__body tr.el-table__row--striped td) { |
| | | background-color: #fafafa; |
| | | } |
| | | |
| | | :deep(.el-tabs__header) { |
| | | margin-bottom: 0; |
| | | } |
| | | |
| | | :deep(.el-tabs__nav-wrap) { |
| | | padding: 0 20px; |
| | | } |
| | | |
| | | :deep(.el-tabs__item) { |
| | | font-size: 16px; |
| | | font-weight: 500; |
| | | } |
| | | |
| | | :deep(.el-tabs__item.is-active) { |
| | | color: #409EFF; |
| | | } |
| | | |
| | | :deep(.el-rate) { |
| | | display: flex; |
| | | align-items: center; |
| | | } |
| | | |
| | | :deep(.el-rate__text) { |
| | | margin-left: 8px; |
| | | font-size: 14px; |
| | | color: #606266; |
| | | } |
| | | </style> |