From 0ad2c4106d6f570e0ca63c8fe5093e6f97492534 Mon Sep 17 00:00:00 2001
From: maven <2163098428@qq.com>
Date: 星期六, 11 十月 2025 17:44:10 +0800
Subject: [PATCH] yys 1.修改销售出库-煤种选中问题 2.采购管理增加车牌字段
---
src/views/productionControl/stockMaterialBoard/index.vue | 636 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 636 insertions(+), 0 deletions(-)
diff --git a/src/views/productionControl/stockMaterialBoard/index.vue b/src/views/productionControl/stockMaterialBoard/index.vue
new file mode 100644
index 0000000..721ddb5
--- /dev/null
+++ b/src/views/productionControl/stockMaterialBoard/index.vue
@@ -0,0 +1,636 @@
+<template>
+ <div class="stock-material-board">
+ <div class="page-header">
+ <h2>搴撳瓨涓庣墿鏂欑湅鏉�</h2>
+ </div>
+
+ <!-- 鎼滅储琛ㄥ崟 -->
+ <el-card class="search-form-card" shadow="never">
+ <el-form :inline="true" :model="searchParams" class="search-form">
+ <el-form-item label="鏃堕棿鑼冨洿">
+ <el-date-picker
+ v-model="searchParams.dateRange"
+ type="daterange"
+ range-separator="鑷�"
+ start-placeholder="寮�濮嬫棩鏈�"
+ end-placeholder="缁撴潫鏃ユ湡"
+ :shortcuts="dateShortcuts"
+ />
+ </el-form-item>
+ <el-form-item label="鐓ょ">
+ <el-input v-model="searchParams.coalType" placeholder="璇疯緭鍏ョ叅绉�" clearable />
+ </el-form-item>
+ <el-form-item label="杞︽缂栫爜">
+ <el-input v-model="searchParams.trainCode" placeholder="璇疯緭鍏ヨ溅娆$紪鐮�" clearable />
+ </el-form-item>
+ <el-form-item>
+ <el-button type="primary" @click="handleSearch" :loading="loading">鏌ヨ</el-button>
+ <el-button @click="handleReset">閲嶇疆</el-button>
+ <el-button @click="handleRefresh">鍒锋柊</el-button>
+ </el-form-item>
+ </el-form>
+ </el-card>
+
+ <!-- 缁熻鍗$墖 -->
+ <div class="stats-cards">
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-download" />
+ </div>
+ <div class="card-content">
+ <div class="card-title">浠婃棩鍏ュ簱鎬婚噺</div>
+ <div class="card-value">{{ todayInStock.toFixed(2) }} 鍚�</div>
+ <div class="card-percentage" :class="{ positive: todayInStockPercentage > 0, negative: todayInStockPercentage < 0 }">
+ <i v-if="todayInStockPercentage > 0" class="el-icon-caret-top" />
+ <i v-else-if="todayInStockPercentage < 0" class="el-icon-caret-bottom" />
+ {{ Math.abs(todayInStockPercentage).toFixed(1) }}%
+ </div>
+ </div>
+ </div>
+
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-upload" />
+ </div>
+ <div class="card-content">
+ <div class="card-title">浠婃棩鍑哄簱鎬婚噺</div>
+ <div class="card-value">{{ todayOutStock.toFixed(2) }} 鍚�</div>
+ <div class="card-percentage" :class="{ positive: todayOutStockPercentage > 0, negative: todayOutStockPercentage < 0 }">
+ <i v-if="todayOutStockPercentage > 0" class="el-icon-caret-top" />
+ <i v-else-if="todayOutStockPercentage < 0" class="el-icon-caret-bottom" />
+ {{ Math.abs(todayOutStockPercentage).toFixed(1) }}%
+ </div>
+ </div>
+ </div>
+
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-takeaway-box" />
+ </div>
+ <div class="card-content">
+ <div class="card-title">浠婃棩棰嗘枡鎬婚噺</div>
+ <div class="card-value">{{ todayMaterialPick.toFixed(2) }} 鍚�</div>
+ <div class="card-percentage" :class="{ positive: todayMaterialPickPercentage > 0, negative: todayMaterialPickPercentage < 0 }">
+ <i v-if="todayMaterialPickPercentage > 0" class="el-icon-caret-top" />
+ <i v-else-if="todayMaterialPickPercentage < 0" class="el-icon-caret-bottom" />
+ {{ Math.abs(todayMaterialPickPercentage).toFixed(1) }}%
+ </div>
+ </div>
+ </div>
+
+ <div class="stat-card">
+ <div class="card-icon">
+ <i class="el-icon-shopping-cart-full" />
+ </div>
+ <div class="card-content">
+ <div class="card-title">褰撳墠搴撳瓨鎬婚噺</div>
+ <div class="card-value">{{ currentTotalStock.toFixed(2) }} 鍚�</div>
+ </div>
+ </div>
+ </div>
+
+ <!-- 鍒嗙被鏁版嵁灞曠ず -->
+ <el-card class="category-cards" shadow="never">
+ <template #header>
+ <div class="card-header">
+ <span>鍒嗙被鏁版嵁缁熻</span>
+ </div>
+ </template>
+
+ <!-- 鐓ょ鍒嗙被 -->
+ <div class="category-section">
+ <h3 class="category-title"><i class="el-icon-menu"></i> 鐓ょ鍒嗗竷</h3>
+ <div class="category-items">
+ <div v-for="item in coalTypeData" :key="item.name" class="category-item">
+ <span class="item-name">{{ item.name }}</span>
+ <div class="item-bar">
+ <div class="item-progress" :style="{ width: item.percentage + '%' }"></div>
+ </div>
+ <span class="item-value">{{ item.value.toFixed(2) }} 鍚� ({{ item.percentage.toFixed(1) }}%)</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- 浜у湴鍒嗙被 -->
+ <div class="category-section">
+ <h3 class="category-title"><i class="el-icon-location"></i> 浜у湴鍒嗗竷</h3>
+ <div class="category-items">
+ <div v-for="item in originData" :key="item.name" class="category-item">
+ <span class="item-name">{{ item.name }}</span>
+ <div class="item-bar">
+ <div class="item-progress" :style="{ width: item.percentage + '%' }"></div>
+ </div>
+ <span class="item-value">{{ item.value.toFixed(2) }} 鍚� ({{ item.percentage.toFixed(1) }}%)</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- 鐑�煎垎绫� -->
+ <div class="category-section">
+ <h3 class="category-title"><i class="el-icon-fire"></i> 鐑�煎垎甯�</h3>
+ <div class="category-items">
+ <div v-for="item in calorificData" :key="item.name" class="category-item">
+ <span class="item-name">{{ item.name }}</span>
+ <div class="item-bar">
+ <div class="item-progress" :style="{ width: item.percentage + '%' }"></div>
+ </div>
+ <span class="item-value">{{ item.value.toFixed(2) }} 鍚� ({{ item.percentage.toFixed(1) }}%)</span>
+ </div>
+ </div>
+ </div>
+
+ <!-- 杞︽缂栫爜鍒嗙被 -->
+ <div class="category-section">
+ <h3 class="category-title"><i class="el-icon-train"></i> 杞︽缂栫爜缁熻</h3>
+ <el-table :data="trainCodeData" style="width: 100%">
+ <el-table-column prop="trainCode" label="杞︽缂栫爜" width="160" />
+ <el-table-column prop="count" label="娆℃暟" width="100" align="right" />
+ <el-table-column prop="totalQuantity" label="鎬婚噺(鍚�)" width="120" align="right">
+ <template #default="scope">{{ scope.row.totalQuantity.toFixed(2) }}</template>
+ </el-table-column>
+ </el-table>
+ </div>
+ </el-card>
+
+ <!-- 鏈�杩戜氦鏄撹褰� -->
+ <el-card class="transactions-card" shadow="never">
+ <template #header>
+ <div class="card-header">
+ <span>鏈�杩戜氦鏄撹褰�</span>
+ </div>
+ </template>
+ <el-table v-loading="loading" :data="recentTransactions" style="width: 100%">
+ <el-table-column prop="code" label="缂栫爜" width="160" />
+ <el-table-column prop="type" label="绫诲瀷" width="80">
+ <template #default="scope">
+ <span class="type-tag"
+ :class="{
+ 'type-in': scope.row.type === '鍏ュ簱',
+ 'type-out': scope.row.type === '鍑哄簱',
+ 'type-pick': scope.row.type === '棰嗘枡'
+ }">
+ {{ scope.row.type }}
+ </span>
+ </template>
+ </el-table-column>
+ <el-table-column prop="coalType" label="鐓ょ" width="100" />
+ <el-table-column prop="origin" label="浜у湴" width="100" />
+ <el-table-column prop="calorificValue" label="鐑��" width="120" />
+ <el-table-column prop="quantity" label="鏁伴噺(鍚�)" width="120" />
+ <el-table-column prop="trainCode" label="杞︽缂栫爜" width="120" />
+ <el-table-column prop="createTime" label="鍒涘缓鏃堕棿" width="180" />
+ </el-table>
+ </el-card>
+ </div>
+</template>
+
+<script setup>
+import { ref, onMounted } from 'vue'
+import { ElMessage } from 'element-plus'
+
+// 鎼滅储鍙傛暟
+const searchParams = ref({
+ dateRange: [],
+ coalType: '',
+ trainCode: ''
+})
+
+// 鏃ユ湡蹇嵎閫夐」
+const dateShortcuts = [
+ {
+ text: '浠婂ぉ',
+ value: () => {
+ const end = new Date()
+ const start = new Date()
+ return [start, end]
+ }
+ },
+ {
+ text: '鏄ㄥぉ',
+ value: () => {
+ const end = new Date()
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24)
+ return [start, end]
+ }
+ },
+ {
+ text: '杩�7澶�',
+ value: () => {
+ const end = new Date()
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+ return [start, end]
+ }
+ },
+ {
+ text: '杩�30澶�',
+ value: () => {
+ const end = new Date()
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24 * 30)
+ return [start, end]
+ }
+ },
+ {
+ text: '鏈湀',
+ value: () => {
+ const end = new Date()
+ const start = new Date(end.getFullYear(), end.getMonth(), 1)
+ return [start, end]
+ }
+ }
+]
+
+// 缁熻鏁版嵁
+const todayInStock = ref(1250.75)
+const todayInStockPercentage = ref(5.2)
+const todayOutStock = ref(890.30)
+const todayOutStockPercentage = ref(-2.1)
+const todayMaterialPick = ref(320.45)
+const todayMaterialPickPercentage = ref(10.3)
+const currentTotalStock = ref(15680.95)
+
+// 鍒嗙被鏁版嵁 - 鐓ょ鍒嗗竷
+const coalTypeData = ref([
+ { name: '鐑熺叅', value: 4500, percentage: 30.0 },
+ { name: '鏃犵儫鐓�', value: 3200, percentage: 21.3 },
+ { name: '瑜愮叅', value: 2800, percentage: 18.7 },
+ { name: '璐叅', value: 2500, percentage: 16.7 },
+ { name: '鐦︾叅', value: 2680, percentage: 17.9 }
+])
+
+// 鍒嗙被鏁版嵁 - 浜у湴鍒嗗竷
+const originData = ref([
+ { name: '灞辫タ', value: 5200, percentage: 33.1 },
+ { name: '鍐呰挋鍙�', value: 3800, percentage: 24.2 },
+ { name: '闄曡タ', value: 2900, percentage: 18.5 },
+ { name: '鏂扮枂', value: 2100, percentage: 13.4 },
+ { name: '璐靛窞', value: 1680, percentage: 10.7 }
+])
+
+// 鍒嗙被鏁版嵁 - 鐑�煎垎甯�
+const calorificData = ref([
+ { name: '4000-4500', value: 2800, percentage: 17.9 },
+ { name: '4500-5000', value: 4200, percentage: 26.8 },
+ { name: '5000-5500', value: 5600, percentage: 35.7 },
+ { name: '5500-6000', value: 2500, percentage: 16.0 },
+ { name: '6000+', value: 580, percentage: 3.7 }
+])
+
+// 鍒嗙被鏁版嵁 - 杞︽缂栫爜缁熻
+const trainCodeData = ref([
+ { trainCode: 'C12345', count: 12, totalQuantity: 4200.5 },
+ { trainCode: 'C12346', count: 8, totalQuantity: 2800.2 },
+ { trainCode: 'C12347', count: 10, totalQuantity: 3500.0 },
+ { trainCode: 'C12348', count: 7, totalQuantity: 2450.8 },
+ { trainCode: 'C12349', count: 5, totalQuantity: 1800.3 }
+])
+
+// 妯℃嫙鏁版嵁 - 鏈�杩戜氦鏄撹褰�
+const recentTransactions = ref([
+ { code: 'RK20230507001', type: '鍏ュ簱', coalType: '鐑熺叅', origin: '灞辫タ', calorificValue: '5300澶у崱', quantity: 350.5, trainCode: 'C12345', createTime: '2023-05-07 09:30:15' },
+ { code: 'CK20230507001', type: '鍑哄簱', coalType: '鏃犵儫鐓�', origin: '鍐呰挋鍙�', calorificValue: '5800澶у崱', quantity: 280.2, trainCode: 'C12346', createTime: '2023-05-07 10:15:30' },
+ { code: 'LL20230507001', type: '棰嗘枡', coalType: '瑜愮叅', origin: '鏂扮枂', calorificValue: '4200澶у崱', quantity: 120.8, trainCode: '', createTime: '2023-05-07 11:05:45' },
+ { code: 'RK20230507002', type: '鍏ュ簱', coalType: '璐叅', origin: '闄曡タ', calorificValue: '5100澶у崱', quantity: 400.0, trainCode: 'C12347', createTime: '2023-05-07 13:20:00' },
+ { code: 'CK20230507002', type: '鍑哄簱', coalType: '鐦︾叅', origin: '璐靛窞', calorificValue: '5400澶у崱', quantity: 310.5, trainCode: 'C12348', createTime: '2023-05-07 14:45:15' },
+ { code: 'LL20230507002', type: '棰嗘枡', coalType: '鐑熺叅', origin: '灞辫タ', calorificValue: '5300澶у崱', quantity: 200.0, trainCode: '', createTime: '2023-05-07 15:30:30' }
+])
+
+// 鍔犺浇鐘舵��
+const loading = ref(false)
+
+// 鏌ヨ鏁版嵁
+const handleSearch = async () => {
+ try {
+ loading.value = true
+ console.log('鎼滅储鍙傛暟:', searchParams.value)
+
+ // 妯℃嫙API璇锋眰寤惰繜
+ await new Promise(resolve => setTimeout(resolve, 800))
+
+ // 妯℃嫙鏁版嵁鏇存柊
+ todayInStock.value = 1000 + Math.random() * 500
+ todayInStockPercentage.value = -10 + Math.random() * 20
+ todayOutStock.value = 800 + Math.random() * 400
+ todayOutStockPercentage.value = -10 + Math.random() * 20
+ todayMaterialPick.value = 200 + Math.random() * 200
+ todayMaterialPickPercentage.value = -10 + Math.random() * 20
+ currentTotalStock.value = 15000 + Math.random() * 3000
+
+ // 鏇存柊鍒嗙被鏁版嵁
+ coalTypeData.value.forEach(item => {
+ item.value = 2000 + Math.random() * 3000
+ })
+
+ originData.value.forEach(item => {
+ item.value = 1500 + Math.random() * 4000
+ })
+
+ calorificData.value.forEach(item => {
+ item.value = 500 + Math.random() * 5000
+ })
+
+ trainCodeData.value.forEach(item => {
+ item.count = 3 + Math.floor(Math.random() * 15)
+ item.totalQuantity = 1000 + Math.random() * 4000
+ })
+
+ // 閲嶆柊璁$畻鐧惧垎姣�
+ const calculatePercentages = (data) => {
+ const total = data.reduce((sum, item) => sum + item.value, 0)
+ data.forEach(item => {
+ item.percentage = total > 0 ? (item.value / total) * 100 : 0
+ })
+ }
+
+ calculatePercentages(coalTypeData.value)
+ calculatePercentages(originData.value)
+ calculatePercentages(calorificData.value)
+
+ ElMessage.success('鏌ヨ鎴愬姛')
+ } catch (error) {
+ console.error('鏌ヨ澶辫触:', error)
+ ElMessage.error('鏌ヨ澶辫触锛岃绋嶅悗閲嶈瘯')
+ } finally {
+ loading.value = false
+ }
+}
+
+// 閲嶇疆鎼滅储鍙傛暟
+const handleReset = () => {
+ searchParams.value = {
+ dateRange: [],
+ coalType: '',
+ trainCode: ''
+ }
+}
+
+// 鍒锋柊鏁版嵁
+const handleRefresh = () => {
+ ElMessage.info('姝e湪鍒锋柊鏁版嵁...')
+ handleSearch()
+}
+
+// 鑷姩鐢熸垚缂栫爜鍑芥暟
+const generateCode = (type) => {
+ const prefix = type === '鍏ュ簱' ? 'RK' : type === '鍑哄簱' ? 'CK' : 'LL'
+ const date = new Date().toISOString().slice(0, 10).replace(/-/g, '')
+ const random = Math.floor(Math.random() * 1000).toString().padStart(3, '0')
+ return `${prefix}${date}${random}`
+}
+
+// 鍒濆鍖栭〉闈�
+onMounted(() => {
+ // 榛樿鏌ヨ杩�7澶╂暟鎹�
+ const end = new Date()
+ const start = new Date()
+ start.setTime(start.getTime() - 3600 * 1000 * 24 * 7)
+ searchParams.value.dateRange = [start, end]
+
+ // 鍒濆鍔犺浇鏁版嵁
+ handleSearch()
+})
+</script>
+
+<style scoped>
+.stock-material-board {
+ padding: 20px;
+}
+
+.page-header {
+ margin-bottom: 20px;
+}
+
+.page-header h2 {
+ margin-bottom: 15px;
+ font-size: 18px;
+ font-weight: 600;
+ color: #303133;
+}
+
+.search-form-card {
+ margin-bottom: 20px;
+}
+
+.search-form {
+ display: flex;
+ align-items: center;
+ flex-wrap: wrap;
+ gap: 16px;
+}
+
+.stats-cards {
+ display: grid;
+ grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
+ gap: 16px;
+ margin-bottom: 24px;
+}
+
+.stat-card {
+ display: flex;
+ padding: 20px;
+ background: #fff;
+ border-radius: 8px;
+ box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+ transition: transform 0.3s, box-shadow 0.3s;
+}
+
+.stat-card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
+}
+
+.card-icon {
+ width: 48px;
+ height: 48px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ font-size: 24px;
+ margin-right: 16px;
+}
+
+.stat-card:nth-child(1) .card-icon {
+ background: #F6FFED;
+ color: #52C41A;
+}
+
+.stat-card:nth-child(2) .card-icon {
+ background: #FFF7E6;
+ color: #FA8C16;
+}
+
+.stat-card:nth-child(3) .card-icon {
+ background: #FFF2F0;
+ color: #FF4D4F;
+}
+
+.stat-card:nth-child(4) .card-icon {
+ background: #E6F7FF;
+ color: #1890FF;
+}
+
+.card-content {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-between;
+}
+
+.card-title {
+ font-size: 14px;
+ color: #909399;
+ margin-bottom: 8px;
+}
+
+.card-value {
+ font-size: 24px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 4px;
+}
+
+.card-percentage {
+ font-size: 12px;
+}
+
+.card-percentage.positive {
+ color: #52C41A;
+}
+
+.card-percentage.negative {
+ color: #FF4D4F;
+}
+
+.category-cards {
+ margin-bottom: 24px;
+}
+
+.category-section {
+ margin-bottom: 24px;
+ padding-bottom: 20px;
+ border-bottom: 1px solid #EBEEF5;
+}
+
+.category-section:last-child {
+ margin-bottom: 0;
+ padding-bottom: 0;
+ border-bottom: none;
+}
+
+.category-title {
+ font-size: 16px;
+ font-weight: 600;
+ color: #303133;
+ margin-bottom: 16px;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.category-items {
+ display: flex;
+ flex-direction: column;
+ gap: 12px;
+}
+
+.category-item {
+ display: flex;
+ align-items: center;
+ gap: 16px;
+}
+
+.item-name {
+ width: 100px;
+ font-size: 14px;
+ color: #606266;
+}
+
+.item-bar {
+ flex: 1;
+ height: 8px;
+ background-color: #F5F7FA;
+ border-radius: 4px;
+ overflow: hidden;
+}
+
+.item-progress {
+ height: 100%;
+ background-color: #409EFF;
+ border-radius: 4px;
+ transition: width 0.3s ease;
+}
+
+.item-value {
+ width: 140px;
+ text-align: right;
+ font-size: 14px;
+ color: #606266;
+}
+
+.transactions-card {
+ background: #fff;
+ border-radius: 8px;
+}
+
+.card-header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ padding: 16px 20px;
+ border-bottom: 1px solid #EBEEF5;
+}
+
+.card-header span {
+ font-weight: 600;
+ color: #303133;
+}
+
+.type-tag {
+ padding: 4px 8px;
+ border-radius: 4px;
+ font-size: 12px;
+}
+
+.type-in {
+ background: #F6FFED;
+ color: #52C41A;
+ border: 1px solid #B7EB8F;
+}
+
+.type-out {
+ background: #FFF7E6;
+ color: #FA8C16;
+ border: 1px solid #FFD591;
+}
+
+.type-pick {
+ background: #FFF2F0;
+ color: #FF4D4F;
+ border: 1px solid #FFCCC7;
+}
+
+/* 鍝嶅簲寮忚璁� */
+@media screen and (max-width: 1200px) {
+ .stats-cards {
+ grid-template-columns: repeat(2, 1fr);
+ }
+}
+
+@media screen and (max-width: 768px) {
+ .stats-cards {
+ grid-template-columns: 1fr;
+ }
+
+ .search-form {
+ flex-direction: column;
+ align-items: stretch;
+ }
+
+ .search-form .el-form-item {
+ width: 100%;
+ }
+}
+</style>
\ No newline at end of file
--
Gitblit v1.9.3