zhangwencui
2026-05-06 a5a3f4b3a283d9d8e2b41b6291ed0fb11ad31c1c
生产订单模块做工序生产进度功能
已修改1个文件
144 ■■■■■ 文件已修改
src/pages/productionManagement/productionOrder/index.vue 144 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/productionManagement/productionOrder/index.vue
@@ -67,6 +67,31 @@
                <text class="progress-text">{{ item.completeQuantity || 0 }} / {{ item.quantity || 0 }}</text>
              </view>
            </view>
            <!-- 工序生产进度展示 -->
            <view class="detail-row process-row">
              <text class="detail-label">工序进度</text>
              <scroll-view scroll-x
                           class="process-scroll">
                <view class="process-container">
                  <view v-for="(process, pIdx) in item.processRouteStatus"
                        :key="pIdx"
                        class="process-item">
                    <view class="process-node">
                      <view class="node-circle"
                            :class="{ 'is-complete': process.percentage >= 100 }">
                        <text class="node-percentage"
                              :style="{ color: process.percentage >= 100 ? '#52c41a' : (process.percentage >= 70 ? '#f56c6c' : '#3c9cff') }">{{ process.percentage }}%</text>
                      </view>
                      <text class="node-name">{{ process.name }}</text>
                    </view>
                    <view v-if="pIdx < item.processRouteStatus.length - 1"
                          class="node-line"></view>
                  </view>
                  <view v-if="!item.processRouteStatus || !item.processRouteStatus.length"
                        class="no-process">-</view>
                </view>
              </scroll-view>
            </view>
            <view class="detail-row">
              <text class="detail-label">计划完成</text>
              <text class="detail-value">{{ formatDate(item.planCompleteTime) }}</text>
@@ -112,6 +137,7 @@
    productOrderListPage,
    getOrderProcessRouteMain,
  } from "@/api/productionManagement/productionOrder.js";
  import { productWorkOrderPage } from "@/api/productionManagement/workOrder.js";
  import PageHeader from "@/components/PageHeader.vue";
  const { proxy } = getCurrentInstance();
@@ -166,7 +192,7 @@
      2: "warning",
      3: "success",
      4: "info",
      5: "danger",
      5: "error",
    };
    return typeMap[status] || "info";
  };
@@ -216,16 +242,44 @@
    };
    productOrderListPage(params)
      .then(res => {
        loading.value = false;
      .then(async res => {
        const records = res.data.records || [];
        // 为每个订单并行查询工序进度
        const processPromises = records.map(async item => {
          if (item.npsNo) {
            try {
              const workOrderRes = await productWorkOrderPage({
                npsNo: item.npsNo,
                size: 100,
              });
              const workOrders = workOrderRes.data.records || [];
              const processRouteStatus = workOrders.map(wo => ({
                name: wo.operationName || "未知工序",
                percentage:
                  Number(wo.completionStatus) > 100
                    ? 100
                    : Number(wo.completionStatus || 0),
              }));
              return { ...item, processRouteStatus };
            } catch (error) {
              console.error(`获取工单 ${item.npsNo} 进度失败:`, error);
              return { ...item, processRouteStatus: [] };
            }
          }
          return { ...item, processRouteStatus: [] };
        });
        const updatedRecords = await Promise.all(processPromises);
        loading.value = false;
        if (page.current === 1) {
          tableData.value = records;
          tableData.value = updatedRecords;
        } else {
          tableData.value = [...tableData.value, ...records];
          tableData.value = [...tableData.value, ...updatedRecords];
        }
        if (records.length < page.size) {
        if (updatedRecords.length < page.size) {
          loadStatus.value = "nomore";
        } else {
          loadStatus.value = "loadmore";
@@ -380,6 +434,84 @@
            text-align: right;
          }
        }
        &.process-row {
          flex-direction: column;
          margin: 20rpx 0;
          .process-scroll {
            width: 100%;
            margin-top: 16rpx;
            .process-container {
              display: flex;
              align-items: flex-start;
              padding: 10rpx 0;
              min-height: 120rpx;
              .process-item {
                display: flex;
                align-items: center;
                .process-node {
                  display: flex;
                  flex-direction: column;
                  align-items: center;
                  width: 100rpx;
                  .node-circle {
                    width: 60rpx;
                    height: 60rpx;
                    border-radius: 50%;
                    border: 2rpx solid #3c9cff;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                    background: #fff;
                    margin-bottom: 8rpx;
                    .node-percentage {
                      font-size: 18rpx;
                      color: #3c9cff;
                      font-weight: bold;
                    }
                    &.is-complete {
                      border-color: #52c41a;
                      background: #f6ffed;
                      .node-percentage {
                        color: #52c41a;
                      }
                    }
                  }
                  .node-name {
                    font-size: 20rpx;
                    color: #666;
                    text-align: center;
                    width: 120rpx;
                    white-space: nowrap;
                    overflow: hidden;
                    text-overflow: ellipsis;
                  }
                }
                .node-line {
                  width: 40rpx;
                  height: 2rpx;
                  background: #e8e8e8;
                  margin: -30rpx 0 0 0;
                }
              }
              .no-process {
                font-size: 24rpx;
                color: #ccc;
              }
            }
          }
        }
      }
    }