From 77f74b092b083cb5b46bfd7f174cb64ac5d54656 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期三, 25 三月 2026 10:46:39 +0800
Subject: [PATCH] Merge branch 'dev_银川_中盛建材' of http://114.132.189.42:9002/r/product-inventory-management into dev_银川_中盛建材

---
 src/views/productionManagement/productionReporting/detailDialog.vue |  527 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 527 insertions(+), 0 deletions(-)

diff --git a/src/views/productionManagement/productionReporting/detailDialog.vue b/src/views/productionManagement/productionReporting/detailDialog.vue
new file mode 100644
index 0000000..aec6b5c
--- /dev/null
+++ b/src/views/productionManagement/productionReporting/detailDialog.vue
@@ -0,0 +1,527 @@
+<template>
+  <el-dialog v-model="dialogVisible"
+             :title="dialogTitle"
+             width="1000px"
+             :close-on-click-modal="false"
+             custom-class="custom-dialog">
+    <div class="detail-container">
+      <!-- 鍩虹淇℃伅 -->
+      <div class="detail-section">
+        <h3 class="section-title">鍩虹淇℃伅</h3>
+        <el-descriptions :column="3"
+                         border>
+          <el-descriptions-item label="鐢熶骇璁㈠崟鍙�">{{ detailData.npsNo || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="鐝粍"><el-tag :type="detailData.schedule == '鐧界彮' ? 'primary' : 'warning'">{{ detailData.schedule || '-' }}</el-tag></el-descriptions-item>
+          <el-descriptions-item label="宀椾綅浜哄憳">{{ detailData.postName || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="浜у搧缂栫爜">{{ detailData.materialCode || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="浜у搧鍚嶇О">{{ detailData.productName || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="瑙勬牸">{{ detailData.model || '-' }}</el-descriptions-item>
+          <el-descriptions-item label="鍚堟牸鏁伴噺"><span class="num2">{{ detailData.qualifiedQuantity || 0 }}</span> <span class="unit">鏂�</span></el-descriptions-item>
+          <el-descriptions-item label="涓嶅悎鏍兼暟閲�"><span class="num3">{{ detailData.unqualifiedQuantity || 0 }}</span> <span class="unit">鏂�</span></el-descriptions-item>
+          <el-descriptions-item label="鎬绘暟閲�"><span class="num1">{{ detailData.quantity || 0 }}</span> <span class="unit">鏂�</span></el-descriptions-item>
+          <el-descriptions-item label="鎶ュ伐鏃堕棿">{{ formatTime(detailData.reportingTime) }}</el-descriptions-item>
+          <el-descriptions-item label="鍒涘缓鏃堕棿">{{ formatTime(detailData.createTime) }}</el-descriptions-item>
+          <el-descriptions-item label="鏇存柊鏃堕棿">{{ formatTime(detailData.updateTime) }}</el-descriptions-item>
+        </el-descriptions>
+      </div>
+      <!-- 宸ュ簭淇℃伅 -->
+      <div class="detail-section"
+           v-if="detailData.productionProductRouteItemDtoList && detailData.productionProductRouteItemDtoList.length > 0">
+        <h3 class="section-title">宸ュ簭淇℃伅</h3>
+        <div v-for="(process, index) in detailData.productionProductRouteItemDtoList"
+             :key="process.id"
+             class="process-item">
+          <div class="process-header">
+            <h4 class="process-title">{{ process.processName || '-' }}</h4>
+            <div class="process-info">
+              <span class="process-label">宀椾綅浜哄憳锛歿{ process.postName || '-' }}</span>
+              <span class="process-label">宸ュ簭ID锛歿{ process.processNo || '-' }}</span>
+            </div>
+          </div>
+          <!-- 宸ュ簭鍩烘湰淇℃伅 -->
+          <div class="process-details">
+            <el-descriptions :column="2"
+                             border>
+              <el-descriptions-item label="璁惧寮傚父鎯呭喌">{{ process.equipmentMalfunction || '-' }}</el-descriptions-item>
+              <el-descriptions-item label="褰撶彮璁惧澶勭疆">{{ process.equipmentDisposal || '-' }}</el-descriptions-item>
+              <el-descriptions-item label="宸ヨ壓浜哄憳浜ゅ緟"
+                                    :span="2">{{ process.processExplained || '-' }}</el-descriptions-item>
+            </el-descriptions>
+          </div>
+          <!-- 宸ュ簭鍙傛暟 -->
+          <div v-if="process.productionProductRouteItemParamDtoList && process.productionProductRouteItemParamDtoList.length > 0">
+            <!-- BOM淇℃伅 -->
+            <div class="param-section"
+                 v-if="getBomList(process.productionProductRouteItemParamDtoList).length > 0">
+              <h5 class="param-title">鎶曞叆鍝佷俊鎭�</h5>
+              <el-table :data="getBomList(process.productionProductRouteItemParamDtoList)"
+                        style="width: 100%"
+                        size="small">
+                <el-table-column prop="paramName"
+                                 label="浜у搧鍚嶇О"
+                                 min-width="120"></el-table-column>
+                <el-table-column prop="model"
+                                 label="瑙勬牸鍨嬪彿"
+                                 min-width="120"></el-table-column>
+                <el-table-column prop="productValue"
+                                 label="鎶曞叆閲�"
+                                 min-width="100"></el-table-column>
+                <el-table-column prop="unit"
+                                 label="鍗曚綅"
+                                 width="80"></el-table-column>
+              </el-table>
+            </div>
+            <!-- 鍙傛暟淇℃伅 -->
+            <div class="param-section"
+                 v-if="getParamList(process.productionProductRouteItemParamDtoList).length > 0">
+              <h5 class="param-title">鐢熶骇璁板綍</h5>
+              <div v-for="(group, sort) in getParamGroups(process.productionProductRouteItemParamDtoList)"
+                   :key="sort"
+                   class="param-group">
+                <div class="group-header">
+                  <span class="group-title">鐢熶骇璁板綍缁� {{ sort }}</span>
+                </div>
+                <div class="param-grid">
+                  <div v-for="param in group"
+                       :key="param.id"
+                       class="param-item">
+                    <span class="param-label">{{ param.paramName || '-' }}:</span>
+                    <span class="param-value">{{ param.paramValue || '-' }}</span>
+                    <span v-if="param.unit && param.unit !== '/'"
+                          class="param-unit">{{ param.unit }}</span>
+                  </div>
+                </div>
+              </div>
+            </div>
+          </div>
+          <!-- 涓婁紶鏂囦欢 -->
+          <div class="file-section"
+               v-if="process.fileList && process.fileList.length > 0">
+            <h5 class="file-title">涓婁紶鏂囦欢</h5>
+            <div class="file-grid">
+              <div v-for="file in process.fileList"
+                   :key="file.id"
+                   class="file-item">
+                <el-image style="width: 100px; height: 100px"
+                          v-if="file.fileUrl"
+                          :src="baseUrl + file.fileUrl"
+                          :zoom-rate="1.2"
+                          :max-scale="7"
+                          :alt="file.fileName"
+                          :min-scale="0.2"
+                          :preview-src-list="formatFileList(process.fileList)"
+                          show-progress
+                          :initial-index="4"
+                          fit="cover" />
+                <div class="file-info">
+                  <span class="file-name">{{ file.fileName || '-' }}</span>
+                </div>
+              </div>
+            </div>
+          </div>
+        </div>
+      </div>
+    </div>
+    <template #footer>
+      <div class="dialog-footer">
+        <el-button @click="dialogVisible = false">鍏抽棴</el-button>
+      </div>
+    </template>
+  </el-dialog>
+</template>
+
+<script setup>
+  import { ref, computed, watch } from "vue";
+  import dayjs from "dayjs";
+
+  const baseUrl = import.meta.env.VITE_APP_BASE_API;
+  const props = defineProps({
+    visible: {
+      type: Boolean,
+      default: false,
+    },
+    data: {
+      type: Object,
+      default: () => ({}),
+    },
+  });
+
+  const emit = defineEmits(["update:visible"]);
+
+  const dialogVisible = computed({
+    get: () => props.visible,
+    set: value => emit("update:visible", value),
+  });
+
+  const dialogTitle = computed(() => "鐢熶骇鎶ュ伐璇︽儏");
+  const detailData = ref(props.data);
+
+  // 鏍煎紡鍖栨椂闂�
+  const formatTime = time => {
+    return time ? dayjs(time).format("YYYY-MM-DD HH:mm:ss") : "-";
+  };
+
+  // 鏍煎紡鍖栨枃浠跺垪琛�
+  const formatFileList = fileList => {
+    return fileList.map(file => ({
+      name: file.fileName,
+      url: baseUrl + file.fileUrl,
+      size: file.fileSize,
+    }));
+  };
+
+  // 澶勭悊鏂囦欢棰勮
+  const handleFilePreview = file => {
+    if (file.fileUrl) {
+      window.open(baseUrl + file.fileUrl, "_blank");
+    } else {
+      console.log("鏂囦欢娌℃湁URL锛屾棤娉曢瑙�");
+    }
+  };
+
+  // 鑾峰彇BOM鍒楄〃
+  const getBomList = paramList => {
+    return paramList.filter(item => item.bomId);
+  };
+
+  // 鑾峰彇鍙傛暟鍒楄〃
+  const getParamList = paramList => {
+    return paramList.filter(item => !item.bomId);
+  };
+
+  // 鎸塻ourceSort鍒嗙粍鍙傛暟
+  const getParamGroups = paramList => {
+    const params = getParamList(paramList);
+    const groups = {};
+
+    params.forEach(param => {
+      const sort = param.sourceSort || 1;
+      if (!groups[sort]) {
+        groups[sort] = [];
+      }
+      groups[sort].push(param);
+    });
+
+    return groups;
+  };
+
+  // 鐩戝惉鏁版嵁鍙樺寲
+  watch(
+    () => props.data,
+    newData => {
+      detailData.value = newData;
+    },
+    { deep: true }
+  );
+</script>
+
+<style scoped>
+  .detail-container {
+    max-height: 600px;
+    overflow-y: auto;
+    padding: 0 16px;
+  }
+
+  .detail-section {
+    margin-bottom: 28px;
+    background-color: #ffffff;
+    border-radius: 8px;
+    padding: 20px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+  }
+
+  .section-title {
+    font-size: 16px;
+    font-weight: 600;
+    margin-bottom: 16px;
+    color: #1a1a1a;
+    border-bottom: 2px solid #409eff;
+    padding-bottom: 10px;
+  }
+
+  .process-item {
+    margin-bottom: 24px;
+    padding: 20px;
+    background-color: #ffffff;
+    border-radius: 8px;
+    border: 1px solid #ebeef5;
+    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
+  }
+
+  .process-header {
+    margin-bottom: 20px;
+    padding-bottom: 12px;
+    border-bottom: 1px solid #f0f2f5;
+  }
+
+  .process-title {
+    font-size: 15px;
+    font-weight: 600;
+    margin-bottom: 12px;
+    color: #1a1a1a;
+    display: flex;
+    align-items: center;
+  }
+
+  .process-title::before {
+    content: "";
+    display: inline-block;
+    width: 4px;
+    height: 16px;
+    background-color: #409eff;
+    margin-right: 8px;
+    border-radius: 2px;
+  }
+
+  .process-info {
+    display: flex;
+    gap: 20px;
+    font-size: 13px;
+    color: #606266;
+  }
+
+  .process-label {
+    padding: 4px 12px;
+    background-color: #ecf5ff;
+    border-radius: 4px;
+    color: #409eff;
+    font-weight: 500;
+  }
+
+  .process-details {
+    margin-bottom: 20px;
+  }
+
+  .param-section {
+    margin-bottom: 20px;
+    background-color: #f9f9f9;
+    border-radius: 6px;
+    padding: 16px;
+    border: 1px solid #f0f2f5;
+  }
+
+  .param-title {
+    font-size: 14px;
+    font-weight: 600;
+    margin-bottom: 14px;
+    color: #1a1a1a;
+    padding-bottom: 8px;
+    border-bottom: 1px solid #e8e8e8;
+  }
+
+  .file-section {
+    margin-top: 20px;
+    background-color: #f9f9f9;
+    border-radius: 6px;
+    padding: 16px;
+    border: 1px solid #f0f2f5;
+  }
+
+  .file-title {
+    font-size: 14px;
+    font-weight: 600;
+    margin-bottom: 14px;
+    color: #1a1a1a;
+    padding-bottom: 8px;
+    border-bottom: 1px solid #e8e8e8;
+  }
+
+  .file-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(120px, 1fr));
+    gap: 16px;
+  }
+
+  .file-item {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    background-color: #ffffff;
+    border: 1px solid #e8e8e8;
+    border-radius: 6px;
+    padding: 10px;
+    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
+    transition: all 0.3s ease;
+  }
+
+  .file-item:hover {
+    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
+    border-color: #409eff;
+    transform: translateY(-2px);
+  }
+
+  .file-image {
+    width: 100px;
+    height: 100px;
+    object-fit: cover;
+    border-radius: 4px;
+    cursor: pointer;
+    margin-bottom: 8px;
+  }
+
+  :deep(.el-image) {
+    border-radius: 4px;
+    overflow: hidden;
+  }
+
+  :deep(.el-image__inner) {
+    transition: transform 0.3s ease;
+  }
+
+  .file-item:hover :deep(.el-image__inner) {
+    transform: scale(1.05);
+  }
+
+  .file-info {
+    width: 100%;
+    text-align: center;
+  }
+
+  .file-name {
+    font-size: 12px;
+    color: #606266;
+    word-break: break-all;
+    line-height: 1.4;
+  }
+
+  .param-group {
+    margin-bottom: 16px;
+    padding: 14px;
+    background-color: #ffffff;
+    border-radius: 6px;
+    border: 1px solid #e8e8e8;
+  }
+
+  .group-header {
+    margin-bottom: 12px;
+    padding-bottom: 8px;
+    border-bottom: 1px solid #f0f2f5;
+  }
+  .num1 {
+    color: #1107cc;
+    font-weight: 600;
+  }
+  .num2 {
+    color: #0fcf25;
+    font-weight: 600;
+  }
+  .num3 {
+    color: #d31818;
+    font-weight: 600;
+  }
+  .unit {
+    font-size: 12px;
+    color: #5d5a66;
+  }
+
+  .group-title {
+    font-size: 14px;
+    font-weight: 600;
+    color: #303133;
+  }
+
+  .param-grid {
+    display: grid;
+    grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
+    gap: 16px;
+  }
+
+  .param-item {
+    display: flex;
+    align-items: center;
+    gap: 12px;
+    padding: 8px 0;
+    border-bottom: 1px solid #f5f7fa;
+  }
+
+  .param-item:last-child {
+    border-bottom: none;
+  }
+
+  .param-label {
+    font-size: 13px;
+    color: #606266;
+    min-width: 100px;
+    font-weight: 500;
+  }
+
+  .param-value {
+    font-size: 13px;
+    color: #1a1a1a;
+    font-weight: 600;
+    flex: 1;
+  }
+
+  .param-unit {
+    font-size: 12px;
+    color: #909399;
+    background-color: #f0f2f5;
+    padding: 2px 6px;
+    border-radius: 3px;
+  }
+
+  .dialog-footer {
+    text-align: center;
+    padding: 20px;
+    border-top: 1px solid #ebeef5;
+  }
+
+  .dialog-footer .el-button {
+    min-width: 100px;
+    padding: 8px 20px;
+  }
+
+  /* 鑷畾涔夊璇濇鏍峰紡 */
+  :deep(.custom-dialog) {
+    border-radius: 12px;
+    overflow: hidden;
+  }
+
+  :deep(.custom-dialog .el-dialog__header) {
+    background-color: #f5f7fa;
+    padding: 20px;
+    border-bottom: 1px solid #ebeef5;
+  }
+
+  :deep(.custom-dialog .el-dialog__title) {
+    font-size: 18px;
+    font-weight: 600;
+    color: #1a1a1a;
+  }
+
+  :deep(.custom-dialog .el-dialog__body) {
+    padding: 20px;
+  }
+
+  /* 琛ㄦ牸鏍峰紡浼樺寲 */
+  :deep(.el-table) {
+    border-radius: 6px;
+    overflow: hidden;
+  }
+
+  :deep(.el-table th) {
+    background-color: #f5f7fa;
+    font-weight: 600;
+    color: #303133;
+  }
+
+  :deep(.el-table tr:hover > td) {
+    background-color: #ecf5ff !important;
+  }
+
+  /* 鎻忚堪鍒楄〃鏍峰紡浼樺寲 */
+  :deep(.el-descriptions) {
+    border-radius: 6px;
+    overflow: hidden;
+  }
+
+  :deep(.el-descriptions__label) {
+    font-weight: 500;
+    color: #606266;
+  }
+
+  :deep(.el-descriptions__content) {
+    color: #1a1a1a;
+    font-weight: 500;
+  }
+</style>
\ No newline at end of file

--
Gitblit v1.9.3