zhangwencui
23 小时以前 79871604f3c79e0ee7a15d198ef321b42fe65c24
追踪进度页面修改
已添加1个文件
已修改3个文件
618 ■■■■ 文件已修改
src/views/productionPlan/productionPlan/index.vue 173 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionPlan/trackProgress/index.vue 441 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/productionPlan/productionPlan/index.vue
@@ -187,73 +187,6 @@
        </span>
      </template>
    </el-dialog>
    <!-- è¿½è¸ªè¿›åº¦å¼¹çª— -->
    <el-dialog v-model="showTrackProgressDialog"
               destroy-on-close
               :title="`追踪进度 - ${trackProgressForm.materialCode || ''}`"
               width="600px">
      <el-form :model="trackProgressForm"
               label-width="120px">
        <el-form-item label="物料编码">
          <el-input v-model="trackProgressForm.materialCode"
                    disabled />
        </el-form-item>
        <el-form-item label="当前状态">
          <el-select v-model="trackProgressForm.currentStatus"
                     placeholder="请选择状态">
            <el-option label="待处理"
                       value="pending" />
            <el-option label="进行中"
                       value="processing" />
            <el-option label="已完成"
                       value="completed" />
          </el-select>
        </el-form-item>
        <el-form-item label="完成进度">
          <el-progress :percentage="trackProgressForm.completionRate"
                       :status="trackProgressForm.completionRate === 100 ? 'success' : ''" />
        </el-form-item>
        <el-form-item label="进度详情">
          <el-table :data="trackProgressForm.progressDetails"
                    border
                    style="width: 100%">
            <el-table-column prop="step"
                             label="步骤"
                             align="center"
                             width="100" />
            <el-table-column prop="status"
                             label="状态"
                             align="center"
                             width="100">
              <template #default="scope">
                <el-tag :type="scope.row.status === 'completed' ? 'success' : scope.row.status === 'processing' ? 'warning' : 'info'">
                  {{ scope.row.status === 'completed' ? '已完成' : scope.row.status === 'processing' ? '进行中' : '待开始' }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column prop="startTime"
                             label="开始时间"
                             align="center"
                             width="180" />
            <el-table-column prop="endTime"
                             label="结束时间"
                             align="center"
                             width="180" />
          </el-table>
        </el-form-item>
        <el-form-item label="备注">
          <el-input v-model="trackProgressForm.remark"
                    type="textarea" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="showTrackProgressDialog = false">关闭</el-button>
          <el-button type="primary"
                     @click="handleUpdateProgress">更新进度</el-button>
        </span>
      </template>
    </el-dialog>
    <!-- å¯¼å…¥å¼¹çª— -->
    <ImportDialog ref="importDialogRef"
                  v-model="importDialogVisible"
@@ -394,6 +327,7 @@
  import ImportDialog from "@/components/Dialog/ImportDialog.vue";
  import { getToken } from "@/utils/auth";
  import { useDict } from "@/utils/dict";
  import { useRouter } from "vue-router";
  import {
    productionPlanListPage,
    loadProdData,
@@ -411,6 +345,7 @@
  } from "@/api/basicData/newProduct.js";
  const { proxy } = getCurrentInstance();
  const router = useRouter();
  const tableColumn = ref([
    {
@@ -666,17 +601,6 @@
    strength: "",
  });
  // è¿½è¸ªè¿›åº¦å¼¹çª—控制
  const showTrackProgressDialog = ref(false);
  // è¿½è¸ªè¿›åº¦è¡¨å•数据
  const trackProgressForm = reactive({
    materialCode: "",
    currentStatus: "",
    completionRate: 0,
    progressDetails: [],
    remark: "",
  });
  // å¯¼å…¥ç›¸å…³
  const importDialogRef = ref(null);
  const importDialogVisible = ref(false);
@@ -744,21 +668,13 @@
  // å¤„理追踪进度按钮点击
  const handleTrackProgress = row => {
    // è®¾ç½®è¡¨å•数据
    trackProgressForm.materialCode = row.materialCode;
    trackProgressForm.currentStatus = row.status;
    // ç”Ÿæˆæ¨¡æ‹Ÿè¿›åº¦æ•°æ®
    trackProgressForm.progressDetails = generateProgressDetails(row.status);
    // è®¡ç®—完成率
    trackProgressForm.completionRate = calculateCompletionRate(
      trackProgressForm.progressDetails
    );
    trackProgressForm.remark = "";
    // æ‰“开弹窗
    showTrackProgressDialog.value = true;
    // è·³è½¬åˆ°è¿½è¸ªè¿›åº¦é¡µé¢
    router.push({
      path: "/productionPlan/trackProgress",
      query: {
        row: encodeURIComponent(JSON.stringify(row)),
      },
    });
  };
  const onBlur = value => {
    // é™åˆ¶å››ä½å°æ•°
@@ -842,77 +758,6 @@
        }
      }
    }
  };
  // ç”Ÿæˆæ¨¡æ‹Ÿè¿›åº¦è¯¦æƒ…数据
  const generateProgressDetails = status => {
    const details = [
      {
        step: "计划确认",
        status: "completed",
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
      {
        step: "物料准备",
        status:
          status === "completed"
            ? "completed"
            : status === "processing"
            ? "completed"
            : "pending",
        startTime:
          status === "completed" || status === "processing"
            ? "2026-03-01 10:30:00"
            : "",
        endTime:
          status === "completed" || status === "processing"
            ? "2026-03-02 16:00:00"
            : "",
      },
      {
        step: "生产加工",
        status:
          status === "completed"
            ? "completed"
            : status === "processing"
            ? "processing"
            : "pending",
        startTime:
          status === "completed" || status === "processing"
            ? "2026-03-03 08:00:00"
            : "",
        endTime: status === "completed" ? "2026-03-08 17:00:00" : "",
      },
      {
        step: "质量检验",
        status: status === "completed" ? "completed" : "pending",
        startTime: status === "completed" ? "2026-03-09 09:00:00" : "",
        endTime: status === "completed" ? "2026-03-09 15:00:00" : "",
      },
      {
        step: "入库",
        status: status === "completed" ? "completed" : "pending",
        startTime: status === "completed" ? "2026-03-10 10:00:00" : "",
        endTime: status === "completed" ? "2026-03-10 11:00:00" : "",
      },
    ];
    return details;
  };
  // è®¡ç®—完成率
  const calculateCompletionRate = details => {
    const completedSteps = details.filter(
      step => step.status === "completed"
    ).length;
    return Math.round((completedSteps / details.length) * 100);
  };
  // å¤„理进度更新
  const handleUpdateProgress = () => {
    // è¿™é‡Œå¯ä»¥æ·»åŠ æ›´æ–°è¿›åº¦çš„é€»è¾‘
    ElMessage.success("进度更新成功");
    showTrackProgressDialog.value = false;
  };
  const data = reactive({
src/views/productionPlan/trackProgress/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,441 @@
<template>
  <div class="app-container">
    <PageHeader content="生产计划追踪进度">
    </PageHeader>
    <el-card style="height:82vh;overflow:auto;">
      <template #header>
        <div class="card-header">
          <span>申请单编号 - {{ rowData.applyNo || '' }}</span>
        </div>
      </template>
      <!-- åŸºç¡€ä¿¡æ¯ -->
      <div class="detail-section">
        <h3 class="section-title">基础信息</h3>
        <el-descriptions :column="3"
                         border>
          <el-descriptions-item label="申请单编号">{{ rowData.applyNo || '-' }}</el-descriptions-item>
          <el-descriptions-item label="产品名称">{{ rowData.productName || '-' }}</el-descriptions-item>
          <el-descriptions-item label="产品规格">{{ rowData.model || '-' }}</el-descriptions-item>
          <el-descriptions-item label="物料编码">{{ rowData.materialCode || '-' }}</el-descriptions-item>
          <el-descriptions-item label="下发数量">{{ rowData.assignedQuantity || 0 }} <span class="unit">方</span></el-descriptions-item>
          <el-descriptions-item label="当前状态">
            <el-tag :type="getStatusType(rowData.status)">
              {{ getStatusText(rowData.status) }}
            </el-tag>
          </el-descriptions-item>
        </el-descriptions>
      </div>
      <div class="progress-container">
        <div class="progress-section">
          <h3 class="section-title">进度信息</h3>
          <div class="progress-item">
            <div class="progress-label">完成进度:</div>
            <div class="progress-content">
              <el-progress :percentage="trackProgressForm.completionRate"
                           :color="customColors"
                           :status="trackProgressForm.completionRate === 100 ? 'success' : ''" />
            </div>
          </div>
          <div class="progress-item">
            <div class="progress-label">进度详情:</div>
            <div class="progress-content">
              <el-table :data="trackProgressForm.progressDetails"
                        border
                        style="width: auto; height: 300px">
                <el-table-column prop="step"
                                 label="步骤(点击查看详情)"
                                 align="center">
                  <template #default="{ row, $index }">
                    <el-link v-if="$index!=0"
                             @click="handleClickStep(row)"
                             type="primary">{{ row.step }}</el-link>
                    <span v-else
                          @click="handleClickStep(row)">{{ row.step }}</span>
                  </template>
                </el-table-column>
                <el-table-column prop="status"
                                 label="状态"
                                 align="center">
                  <template #default="scope">
                    <el-tag :type="scope.row.status === 'completed' ? 'success' : scope.row.status === 'processing' ? 'warning' : 'info'">
                      {{ scope.row.status === 'completed' ? '已完成' : scope.row.status === 'processing' ? '进行中' : '待开始' }}
                    </el-tag>
                  </template>
                </el-table-column>
                <el-table-column prop="quantity"
                                 label="数量"
                                 align="center" />
                <el-table-column prop="startTime"
                                 label="时间"
                                 align="center" />
              </el-table>
            </div>
          </div>
        </div>
        <div class="progress-section">
          <h3 class="section-title">订单信息</h3>
          <div v-for="item in rowData.orderList"
               :key="item.orderNo"
               class="order-item">
            <el-descriptions :column="3"
                             border>
              <el-descriptions-item label="订单编号">{{ item.orderNo || '-' }}</el-descriptions-item>
              <el-descriptions-item label="订单状态">
                <el-tag :type="getStatusType(item.status)">{{ getStatusText(item.status) }}</el-tag>
              </el-descriptions-item>
              <el-descriptions-item label="开始日期">{{ item.startTime || '-' }}</el-descriptions-item>
              <el-descriptions-item label="需求数量">{{ item.quantity || 0 }} <span class="unit">方</span></el-descriptions-item>
              <el-descriptions-item label="完成数量">{{ item.completeQuantity || 0 }} <span class="unit">方</span></el-descriptions-item>
              <el-descriptions-item label="完成进度">
                <el-progress :percentage="item.completionRate"
                             :color="customColors(item.completionRate)"
                             :status="item.completionRate === 100 ? 'success' : ''"
                             style="width: 120px;" />
              </el-descriptions-item>
            </el-descriptions>
          </div>
        </div>
      </div>
    </el-card>
  </div>
</template>
<script setup>
  import { ref, reactive, onMounted } from "vue";
  import { ElMessage } from "element-plus";
  import { useRouter, useRoute } from "vue-router";
  const router = useRouter();
  const route = useRoute();
  // è·¯ç”±å‚数数据
  const rowData = reactive({});
  // è¿½è¸ªè¿›åº¦è¡¨å•数据
  const trackProgressForm = reactive({
    materialCode: "",
    currentStatus: "",
    completionRate: 0,
    progressDetails: [],
    remark: "",
  });
  // èŽ·å–çŠ¶æ€ç±»åž‹
  const getStatusType = status => {
    const typeMap = {
      0: "warning",
      1: "primary",
      2: "info",
    };
    return typeMap[status] || "info";
  };
  // èŽ·å–çŠ¶æ€æ–‡æœ¬
  const getStatusText = status => {
    const statusMap = {
      0: "待下发",
      1: "部分下发",
      2: "已下发",
    };
    return statusMap[status] || "";
  };
  const customColors = percentage => {
    if (Number(percentage) < 10) {
      return "#909399";
    }
    if (Number(percentage) < 70) {
      return "#e6a23c";
    }
    return "#67c23a";
  };
  // ç”Ÿæˆæ¨¡æ‹Ÿè¿›åº¦è¯¦æƒ…数据
  const generateProgressDetails = status => {
    const details = [
      {
        step: "计划确认",
        status: "completed",
        quantity: 233,
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
      {
        step: "第一次报工",
        status: "completed",
        quantity: 233,
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
      {
        step: "第二次报工",
        status: "completed",
        quantity: 233,
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
      {
        step: "第三次报工",
        status: "completed",
        quantity: 233,
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
      {
        step: "第四次报工",
        status: "completed",
        quantity: 233,
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
      {
        step: "第五次报工",
        status: "completed",
        quantity: 233,
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
      {
        step: "第六次报工",
        status: "completed",
        quantity: 233,
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
      {
        step: "第七次报工",
        status: "completed",
        quantity: 233,
        startTime: "2026-03-01 09:00:00",
        endTime: "2026-03-01 10:00:00",
      },
    ];
    return details;
  };
  // è®¡ç®—完成率
  const calculateCompletionRate = details => {
    const completedSteps = details.filter(
      step => step.status === "completed"
    ).length;
    return Math.round((completedSteps / details.length) * 100);
  };
  // å¤„理进度更新
  const handleUpdateProgress = () => {
    // è¿™é‡Œå¯ä»¥æ·»åŠ æ›´æ–°è¿›åº¦çš„é€»è¾‘
    ElMessage.success("进度更新成功");
  };
  // å¤„理返回
  const handleBack = () => {
    router.push("/productionPlan/productionPlan");
  };
  // ç”Ÿæˆæ¨¡æ‹Ÿè®¢å•数据
  const generateOrderList = () => {
    return [
      {
        orderNo: "ORD-2026-001",
        status: 1,
        quantity: 233.28,
        completeQuantity: 14,
        completionRate: 6,
        startTime: "2026-03-25",
      },
      {
        orderNo: "ORD-2026-002",
        status: 2,
        quantity: 150.5,
        completeQuantity: 100,
        completionRate: 67,
        startTime: "2026-03-20",
      },
      {
        orderNo: "ORD-2026-003",
        status: 0,
        quantity: 80.0,
        completeQuantity: 0,
        completionRate: 0,
        startTime: "2026-03-30",
      },
    ];
  };
  // é¡µé¢åŠ è½½æ—¶èŽ·å–æ•°æ®
  onMounted(() => {
    // ä»Žè·¯ç”±å‚数中获取数据
    const data = route.query.row
      ? JSON.parse(decodeURIComponent(route.query.row))
      : null;
    if (data) {
      // èµ‹å€¼ç»™rowData
      Object.assign(rowData, data);
      // èµ‹å€¼ç»™è¡¨å•数据
      trackProgressForm.materialCode = data.materialCode;
      trackProgressForm.currentStatus = data.status;
      trackProgressForm.progressDetails = generateProgressDetails(data.status);
      trackProgressForm.completionRate = calculateCompletionRate(
        trackProgressForm.progressDetails
      );
      trackProgressForm.remark = "";
    }
    // ç”Ÿæˆæ¨¡æ‹Ÿè®¢å•数据
    rowData.orderList = generateOrderList();
  });
</script>
<style scoped>
  .app-container {
    padding: 20px;
    background-color: #f5f7fa;
    min-height: 100vh;
  }
  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0 10px;
  }
  .action-buttons {
    display: flex;
    justify-content: flex-end;
    margin-top: 20px;
    gap: 10px;
  }
  .detail-section {
    margin-bottom: 24px;
    background-color: #ffffff;
    border-radius: 10px;
    padding: 24px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
    transition: all 0.3s ease;
  }
  .detail-section:hover {
    box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.12);
  }
  .section-title {
    font-size: 16px;
    font-weight: 600;
    margin-bottom: 20px;
    color: #1a1a1a;
    border-bottom: 2px solid #409eff;
    padding-bottom: 10px;
    display: flex;
    align-items: center;
  }
  .section-title::before {
    content: "";
    display: inline-block;
    width: 4px;
    height: 16px;
    background-color: #409eff;
    margin-right: 8px;
    border-radius: 2px;
  }
  .unit {
    font-size: 12px;
    color: #909399;
    margin-left: 4px;
  }
  :deep(.el-descriptions) {
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  }
  :deep(.el-descriptions__row:nth-child(odd)) {
    background-color: #f9f9f9;
  }
  :deep(.el-descriptions__label) {
    font-weight: 500;
    color: #606266;
    background-color: #f5f7fa;
  }
  :deep(.el-descriptions__content) {
    color: #303133;
    font-weight: 500;
  }
  .progress-container {
    display: flex;
    gap: 24px;
  }
  .progress-section {
    margin-bottom: 24px;
    background-color: #ffffff;
    border-radius: 10px;
    padding: 24px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.08);
    flex: 1;
    transition: all 0.3s ease;
  }
  .progress-section:hover {
    box-shadow: 0 4px 16px 0 rgba(0, 0, 0, 0.12);
  }
  .progress-item {
    margin-bottom: 24px;
  }
  .progress-label {
    font-size: 14px;
    font-weight: 500;
    color: #606266;
    margin-bottom: 12px;
    display: flex;
    align-items: center;
  }
  .progress-content {
    margin-left: 0;
  }
  .progress-content .el-table {
    max-height: 400px;
    overflow-y: auto;
    border-radius: 8px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  }
  :deep(.el-table th) {
    background-color: #f5f7fa !important;
    font-weight: 600;
    color: #606266;
  }
  :deep(.el-table tr:hover) {
    background-color: #f5f7fa !important;
  }
  .order-item {
    margin-bottom: 20px;
    border-radius: 8px;
    overflow: hidden;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
  }
  .order-item:last-child {
    margin-bottom: 0;
  }
  :deep(.el-progress-bar__inner) {
    border-radius: 10px;
  }
  :deep(.el-tag) {
    border-radius: 12px;
    padding: 2px 10px;
  }
</style>
src/views/qualityManagement/rawMaterialInspection/components/formDia.vue
@@ -347,7 +347,7 @@
    testStandardOptions.value = [];
    tableData.value = [];
    // å…ˆç¡®ä¿äº§å“æ ‘已加载,否则编辑时产品/规格型号无法反显
    await getProductOptions();
    // await getProductOptions();
    if (operationType.value === "edit") {
      // å…ˆä¿å­˜ testStandardId,避免被清空
      const savedTestStandardId = row.testStandardId;
vite.config.js
@@ -8,7 +8,7 @@
  const { VITE_APP_ENV } = env;
  const baseUrl =
      env.VITE_APP_ENV === "development"
          ? "http://192.168.1.234:9019"
          ? "http://192.168.1.107:7003"
          : env.VITE_BASE_API;
  const javaUrl =
      env.VITE_APP_ENV === "development"