From 8757616a02b834cb5a8353e595d8e4e71acfa764 Mon Sep 17 00:00:00 2001
From: huminmin <mac@MacBook-Pro.local>
Date: 星期一, 16 三月 2026 17:37:36 +0800
Subject: [PATCH] 优化原料检;修改不合格管理类别

---
 src/views/consumablesLogistics/stockReport/index.vue |  675 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 675 insertions(+), 0 deletions(-)

diff --git a/src/views/consumablesLogistics/stockReport/index.vue b/src/views/consumablesLogistics/stockReport/index.vue
new file mode 100644
index 0000000..0305289
--- /dev/null
+++ b/src/views/consumablesLogistics/stockReport/index.vue
@@ -0,0 +1,675 @@
+<template>
+  <div class="app-container">
+    <!-- 鎼滅储琛ㄥ崟 -->
+    <div class="search_form">
+      <div class="search_left">
+        <span class="search_title">鎶ヨ〃绫诲瀷锛�</span>
+        <el-select
+          v-model="searchForm.reportType"
+          style="width: 150px;"
+          placeholder="璇烽�夋嫨"
+          @change="handleReportTypeChange"
+        >
+          <el-option label="鏃ユ姤" value="daily" />
+          <el-option label="鏈堟姤" value="monthly" />
+          <el-option label="杩涘嚭瀛樻姤琛�" value="inout" />
+        </el-select>
+        
+        <span class="search_title ml10">鏃堕棿鑼冨洿锛�</span>
+         <el-date-picker
+           v-if="searchForm.reportType === 'daily'"
+           v-model="searchForm.singleDate"
+           type="date"
+           placeholder="璇烽�夋嫨鏃ユ湡"
+           format="YYYY-MM-DD"
+           value-format="YYYY-MM-DD"
+           style="width: 200px;"
+         />
+        <el-date-picker
+          v-else-if="searchForm.reportType === 'monthly'"
+          v-model="searchForm.monthRange"
+          type="monthrange"
+          range-separator="鑷�"
+          start-placeholder="寮�濮嬫湀浠�"
+          end-placeholder="缁撴潫鏈堜唤"
+          format="YYYY-MM-DD"
+          value-format="YYYY-MM-DD"
+          style="width: 240px;"
+        />
+        <el-date-picker
+          v-else
+          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-button type="primary" @click="handleQuery" style="margin-left: 10px">
+          鏌ヨ
+        </el-button>
+        <el-button @click="handleReset">閲嶇疆</el-button>
+      </div>
+
+      <div class="search_right">
+<!--        <el-button type="success" @click="handleExport" icon="Download">-->
+<!--          瀵煎嚭鎶ヨ〃-->
+<!--        </el-button>-->
+      </div>
+    </div>
+
+<!--    &lt;!&ndash; 缁熻鍗$墖 &ndash;&gt;-->
+<!--    <div class="stats_cards" v-if="reportData.summary">-->
+<!--      <el-row :gutter="20">-->
+<!--        <el-col :span="6">-->
+<!--          <el-card class="stats_card">-->
+<!--            <div class="stats_content">-->
+<!--              <div class="stats_icon in">-->
+<!--                <el-icon><TrendCharts /></el-icon>-->
+<!--              </div>-->
+<!--              <div class="stats_info">-->
+<!--                <div class="stats_value">{{ reportData.summary.totalIn || 0 }}</div>-->
+<!--                <div class="stats_label">鎬诲叆搴撻噺</div>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--        <el-col :span="6">-->
+<!--          <el-card class="stats_card">-->
+<!--            <div class="stats_content">-->
+<!--              <div class="stats_icon out">-->
+<!--                <el-icon><TrendCharts /></el-icon>-->
+<!--              </div>-->
+<!--              <div class="stats_info">-->
+<!--                <div class="stats_value">{{ reportData.summary.totalOut || 0 }}</div>-->
+<!--                <div class="stats_label">鎬诲嚭搴撻噺</div>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--        <el-col :span="6">-->
+<!--          <el-card class="stats_card">-->
+<!--            <div class="stats_content">-->
+<!--              <div class="stats_icon stock">-->
+<!--                <el-icon><Box /></el-icon>-->
+<!--              </div>-->
+<!--              <div class="stats_info">-->
+<!--                <div class="stats_value">{{ reportData.summary.currentStock || 0 }}</div>-->
+<!--                <div class="stats_label">褰撳墠搴撳瓨</div>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--        <el-col :span="6">-->
+<!--          <el-card class="stats_card">-->
+<!--            <div class="stats_content">-->
+<!--              <div class="stats_icon turnover">-->
+<!--                <el-icon><Refresh /></el-icon>-->
+<!--              </div>-->
+<!--              <div class="stats_info">-->
+<!--                <div class="stats_value">{{ reportData.summary.turnoverRate || 0 }}%</div>-->
+<!--                <div class="stats_label">鍛ㄨ浆鐜�</div>-->
+<!--              </div>-->
+<!--            </div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--      </el-row>-->
+<!--    </div>-->
+
+<!--    &lt;!&ndash; 鍥捐〃鍖哄煙 &ndash;&gt;-->
+<!--    <div class="chart_section" v-if="reportData.chartData">-->
+<!--      <el-row :gutter="20">-->
+<!--        <el-col :span="12">-->
+<!--          <el-card>-->
+<!--            <template #header>-->
+<!--              <span>搴撳瓨瓒嬪娍鍥�</span>-->
+<!--            </template>-->
+<!--            <div ref="trendChart" style="height: 300px;"></div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--        <el-col :span="12">-->
+<!--          <el-card>-->
+<!--            <template #header>-->
+<!--              <span>杩涘嚭搴撳姣�</span>-->
+<!--            </template>-->
+<!--            <div ref="comparisonChart" style="height: 300px;"></div>-->
+<!--          </el-card>-->
+<!--        </el-col>-->
+<!--      </el-row>-->
+<!--    </div>-->
+
+    <!-- 璇︾粏鏁版嵁琛ㄦ牸 -->
+    <div class="table_section">
+      <el-card>
+        <template #header>
+          <span>{{ getTableTitle() }}</span>
+        </template>
+         <el-table
+           v-loading="tableLoading"
+           :data="reportData.tableData"
+           border
+           height="400"
+           style="width: 100%"
+           :header-cell-style="{ background: '#F0F1F5', color: '#333333' }"
+         >
+          <el-table-column
+            align="center"
+            label="搴忓彿"
+            type="index"
+            width="60"
+          />
+           <el-table-column
+             label="鍏ュ簱鏃堕棿"
+             prop="createTime"
+             width="200"
+             show-overflow-tooltip
+             v-if="searchForm.reportType !== 'inout'"
+           />
+           <el-table-column
+             label="鍏ュ簱鎵规"
+             prop="inboundBatches"
+             width="240"
+             show-overflow-tooltip
+             v-if="searchForm.reportType !== 'inout'"
+           />
+           <el-table-column
+             label="浜у搧澶х被"
+             prop="productName"
+             show-overflow-tooltip
+           />
+           <el-table-column
+             label="瑙勬牸鍨嬪彿"
+             prop="model"
+             show-overflow-tooltip
+           />
+           <el-table-column
+             label="鍗曚綅"
+             prop="unit"
+             show-overflow-tooltip
+           />
+           <el-table-column
+             label="鍏ュ簱鏁伴噺"
+             prop="totalStockIn"
+             align="center"
+             v-if="searchForm.reportType === 'inout'"
+           />
+           <el-table-column
+               label="鍏ュ簱鏁伴噺"
+               prop="stockInNum"
+               align="center"
+               v-else
+           />
+           <el-table-column
+             label="鍑哄簱鏁伴噺"
+             prop="totalStockOut"
+             width="100"
+             align="center"
+             v-if="searchForm.reportType === 'inout'"
+           />
+           <el-table-column
+             label="鐜板湪搴撳瓨"
+             prop="currentStock"
+             align="center"
+           />
+            <el-table-column
+             label="鐜板噣閲�(鍚�)"
+             prop="currentWeight"
+             align="center"
+           />
+           <el-table-column label="鏉ユ簮"
+                            prop="recordType"
+                            v-if="searchForm.reportType !== 'inout'"
+                            show-overflow-tooltip>
+             <template #default="scope">
+               {{ getRecordType(scope.row.recordType) }}
+             </template>
+           </el-table-column>
+           <el-table-column
+             label="鍏ュ簱浜�"
+             prop="createBy"
+             width="80"
+             v-if="searchForm.reportType !== 'inout'"
+             show-overflow-tooltip
+           />
+        </el-table>
+      </el-card>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { ref, reactive, onMounted, nextTick, getCurrentInstance } from 'vue'
+import { ElMessage } from 'element-plus'
+import * as echarts from 'echarts'
+import {
+  getConsumablesInInAndOutReportList,
+  getConsumablesInReportList
+} from "@/api/consumablesLogistics/consumablesIn.js";
+import {
+  findAllQualifiedStockInRecordTypeOptions,
+} from "@/api/basicData/enum.js";
+
+
+const { proxy } = getCurrentInstance()
+// 鍝嶅簲寮忔暟鎹�
+const tableLoading = ref(false)
+const trendChart = ref(null)
+const comparisonChart = ref(null)
+
+const searchForm = reactive({
+  reportType: 'daily',
+  singleDate: '',
+  dateRange: [],
+  monthRange: []
+})
+
+const reportData = ref({
+  summary: null,
+  chartData: null,
+  tableData: []
+})
+
+const stockRecordTypeOptions = ref([])
+
+const getRecordType = (recordType) => {
+  return stockRecordTypeOptions.value.find(item => item.value === recordType)?.label || ''
+}
+
+// 鑾峰彇鏉ユ簮绫诲瀷閫夐」
+const fetchStockRecordTypeOptions = () => {
+  findAllQualifiedStockInRecordTypeOptions()
+      .then(res => {
+        stockRecordTypeOptions.value = res.data;
+      })
+}
+
+// 鑾峰彇琛ㄦ牸鏍囬
+const getTableTitle = () => {
+  const typeMap = {
+    daily: '鏃ユ姤璇︾粏鏁版嵁',
+    monthly: '鏈堟姤璇︾粏鏁版嵁',
+    inout: '杩涘嚭瀛樻姤琛ㄨ缁嗘暟鎹�'
+  }
+  return typeMap[searchForm.reportType] || '鎶ヨ〃璇︾粏鏁版嵁'
+}
+
+// 鎶ヨ〃绫诲瀷鏀瑰彉
+const handleReportTypeChange = () => {
+  reportData.value = {
+    summary: null,
+    chartData: null,
+    tableData: []
+  }
+}
+
+// 鏌ヨ鏁版嵁
+const handleQuery = async () => {
+  if (!validateSearchForm()) {
+    return
+  }
+  
+  tableLoading.value = true
+  try {
+    const params = getQueryParams()
+    let response
+
+    if (searchForm.reportType === 'inout') {
+      response = await getConsumablesInInAndOutReportList(params)
+    } else {
+      response = await getConsumablesInReportList(params)
+    }
+    if (response.code === 200) {
+      reportData.value.tableData = response.data.records
+      // reportData.value.summary = response.data.summary
+      // reportData.value.chartData = response.data.chartData
+      // nextTick(() => {
+      //   initCharts()
+      // })
+      
+    }
+  } catch (error) {
+    ElMessage.error('鏌ヨ澶辫触锛�' + error.message)
+  } finally {
+    tableLoading.value = false
+  }
+}
+// // 鐢熸垚鍋囨暟鎹�
+// const generateMockData = () => {
+//   // 鐢熸垚缁熻鍗$墖鍋囨暟鎹�
+//   const summary = {
+//     totalIn: 1000,
+//     totalOut: 600,
+//     currentStock: 400,
+//     turnoverRate: 30
+//   }
+
+//   // 鐢熸垚鍥捐〃鍋囨暟鎹�
+//   const trendDates = ['2025-09-15', '2025-09-16', '2025-09-17', '2025-09-18', '2025-09-19']
+//   const trendValues = [300, 350, 400, 380, 420]
+//   const comparisonDates = ['2025-09-15', '2025-09-16', '2025-09-17']
+//   const inValues = [100, 150, 200]
+//   const outValues = [80, 120, 100]
+
+//   const chartData = {
+//     trendDates,
+//     trendValues,
+//     comparisonDates,
+//     inValues,
+//     outValues
+//   }
+
+//   reportData.value = {
+//     summary,
+//     chartData,
+//     tableData: []
+//   }
+// }
+// 楠岃瘉鎼滅储琛ㄥ崟
+const validateSearchForm = () => {
+  if (searchForm.reportType === 'daily') {
+    if (!searchForm.singleDate) {
+      ElMessage.warning('璇烽�夋嫨鏃ユ湡')
+      return false
+    }
+  } else if (searchForm.reportType === 'inout') {
+    if (!searchForm.dateRange || searchForm.dateRange.length !== 2) {
+      ElMessage.warning('璇烽�夋嫨鏃ユ湡鑼冨洿')
+      return false
+    }
+  } else if (searchForm.reportType === 'monthly') {
+    if (!searchForm.monthRange || searchForm.monthRange.length !== 2) {
+      ElMessage.warning('璇烽�夋嫨鏈堜唤鑼冨洿')
+      return false
+    }
+  }
+  return true
+}
+
+// 鑾峰彇鏌ヨ鍙傛暟
+const getQueryParams = () => {
+  const params = {
+    reportType: searchForm.reportType,
+    reportDate: "",
+    startMonth: "",
+    endMonth: "",
+    startDate: "",
+    endDate: ""
+  }
+  
+  if (searchForm.reportType === 'daily') {
+    params.reportDate = searchForm.singleDate
+  } else if (searchForm.reportType === 'monthly') {
+    params.startMonth = searchForm.monthRange[0]
+    params.endMonth = searchForm.monthRange[1]
+  } else {
+    params.startDate = searchForm.dateRange[0]
+    params.endDate = searchForm.dateRange[1]
+  }
+  
+  return params
+}
+
+// 閲嶇疆鎼滅储
+const handleReset = () => {
+  searchForm.reportType = 'daily'
+  searchForm.singleDate = ''
+  searchForm.dateRange = []
+  searchForm.monthRange = []
+  reportData.value = {
+    summary: null,
+    chartData: null,
+    tableData: []
+  }
+}
+
+// 瀵煎嚭鎶ヨ〃
+const handleExport = async () => {
+  if (!validateSearchForm()) {
+    return
+  }
+  
+  try {
+    const params = getQueryParams()
+    // const response = await exportStockReport(params)
+    proxy.download("/consumablesInventory/exportConsumablesInventory", params, '鑰楁潗搴撳瓨鎶ヨ〃.xlsx')
+    // 鍒涘缓涓嬭浇閾炬帴
+    // const blob = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' })
+    // const url = window.URL.createObjectURL(blob)
+    // const link = document.createElement('a')
+    // link.href = url
+    // link.download = `${getTableTitle()}_${new Date().getTime()}.xlsx`
+    // document.body.appendChild(link)
+    // link.click()
+    // document.body.removeChild(link)
+    // window.URL.revokeObjectURL(url)
+    
+    // ElMessage.success('瀵煎嚭鎴愬姛')
+  } catch (error) {
+    ElMessage.error('瀵煎嚭澶辫触锛�' + error.message)
+  }
+}
+
+// 鍒濆鍖栧浘琛�
+const initCharts = () => {
+  if (!reportData.value.chartData) return
+  
+  initTrendChart()
+  initComparisonChart()
+}
+
+// 鍒濆鍖栬秼鍔垮浘
+const initTrendChart = () => {
+  if (!trendChart.value) return
+  
+  const chart = echarts.init(trendChart.value)
+  const option = {
+    title: {
+      text: '搴撳瓨鍙樺寲瓒嬪娍',
+      left: 'center'
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['搴撳瓨閲�'],
+      top: 30
+    },
+    xAxis: {
+      type: 'category',
+      data: reportData.value.chartData.trendDates || []
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [{
+      name: '搴撳瓨閲�',
+      type: 'line',
+      data: reportData.value.chartData.trendValues || [],
+      smooth: true,
+      itemStyle: {
+        color: '#409EFF'
+      }
+    }]
+  }
+  chart.setOption(option)
+}
+
+// 鍒濆鍖栧姣斿浘
+const initComparisonChart = () => {
+  if (!comparisonChart.value) return
+  
+  const chart = echarts.init(comparisonChart.value)
+  const option = {
+    title: {
+      text: '杩涘嚭搴撳姣�',
+      left: 'center'
+    },
+    tooltip: {
+      trigger: 'axis'
+    },
+    legend: {
+      data: ['鍏ュ簱', '鍑哄簱'],
+      top: 30
+    },
+    xAxis: {
+      type: 'category',
+      data: reportData.value.chartData.comparisonDates || []
+    },
+    yAxis: {
+      type: 'value'
+    },
+    series: [
+      {
+        name: '鍏ュ簱',
+        type: 'bar',
+        data: reportData.value.chartData.inValues || [],
+        itemStyle: {
+          color: '#67C23A'
+        }
+      },
+      {
+        name: '鍑哄簱',
+        type: 'bar',
+        data: reportData.value.chartData.outValues || [],
+        itemStyle: {
+          color: '#F56C6C'
+        }
+      }
+    ]
+  }
+  chart.setOption(option)
+}
+
+// 缁勪欢鎸傝浇鏃惰缃粯璁ゆ椂闂�
+onMounted(() => {
+  const today = new Date()
+  searchForm.singleDate = today.toISOString().split('T')[0]
+  
+  const yesterday = new Date(today.getTime() - 24 * 60 * 60 * 1000)
+  searchForm.dateRange = [
+    yesterday.toISOString().split('T')[0],
+    today.toISOString().split('T')[0]
+  ]
+
+  fetchStockRecordTypeOptions()
+})
+</script>
+
+<style scoped>
+.app-container {
+  padding: 20px;
+}
+
+.search_form {
+  display: flex;
+  justify-content: space-between;
+  align-items: center;
+  margin-bottom: 20px;
+  padding: 20px;
+  background: #fff;
+  border-radius: 4px;
+  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
+}
+
+.search_left {
+  display: flex;
+  align-items: center;
+}
+
+.search_title {
+  font-weight: 500;
+  color: #333;
+  margin-right: 8px;
+}
+
+.ml10 {
+  margin-left: 10px;
+}
+
+.stats_cards {
+  margin-bottom: 20px;
+}
+
+.stats_card {
+  border-radius: 8px;
+  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
+}
+
+.stats_content {
+  display: flex;
+  align-items: center;
+  padding: 10px 0;
+}
+
+.stats_icon {
+  width: 50px;
+  height: 50px;
+  border-radius: 50%;
+  display: flex;
+  align-items: center;
+  justify-content: center;
+  margin-right: 15px;
+  font-size: 24px;
+  color: #fff;
+}
+
+.stats_icon.in {
+  background: linear-gradient(135deg, #67C23A, #85CE61);
+}
+
+.stats_icon.out {
+  background: linear-gradient(135deg, #F56C6C, #F78989);
+}
+
+.stats_icon.stock {
+  background: linear-gradient(135deg, #409EFF, #66B1FF);
+}
+
+.stats_icon.turnover {
+  background: linear-gradient(135deg, #E6A23C, #EEBE77);
+}
+
+.stats_info {
+  flex: 1;
+}
+
+.stats_value {
+  font-size: 24px;
+  font-weight: bold;
+  color: #333;
+  line-height: 1;
+  margin-bottom: 5px;
+}
+
+.stats_label {
+  font-size: 14px;
+  color: #666;
+}
+
+.chart_section {
+  margin-bottom: 20px;
+}
+
+.table_section {
+  margin-bottom: 20px;
+}
+
+:deep(.el-card__header) {
+  background: #f8f9fa;
+  border-bottom: 1px solid #e9ecef;
+  font-weight: 500;
+}
+
+:deep(.el-table .el-table__header-wrapper th) {
+  background-color: #F0F1F5 !important;
+  color: #333333;
+  font-weight: 600;
+}
+
+:deep(.el-table .el-table__body-wrapper td) {
+  padding: 8px 0;
+}
+</style>

--
Gitblit v1.9.3