From a9d97b150701e634bdb751eab277696abd136cca Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期二, 16 六月 2026 14:39:47 +0800
Subject: [PATCH] 君歌app 1.依照web端功能修改

---
 src/pages/productionManagement/processRoute/items.vue |  554 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 554 insertions(+), 0 deletions(-)

diff --git a/src/pages/productionManagement/processRoute/items.vue b/src/pages/productionManagement/processRoute/items.vue
new file mode 100644
index 0000000..9c2b266
--- /dev/null
+++ b/src/pages/productionManagement/processRoute/items.vue
@@ -0,0 +1,554 @@
+<template>
+  <view class="process-route-items">
+    <PageHeader title="璺嚎椤圭洰"
+                @back="goBack" />
+    <!-- 璺嚎鍩虹淇℃伅鍗$墖 -->
+    <view class="route-info-card">
+      <view class="info-row">
+        <text class="label">宸ヨ壓璺嚎缂栧彿</text>
+        <text class="value">{{ routeInfo.processRouteCode || '-' }}</text>
+      </view>
+      <view class="info-row">
+        <text class="label">浜у搧鍚嶇О</text>
+        <text class="value">{{ routeInfo.productName || '-' }}</text>
+      </view>
+      <view class="info-row">
+        <text class="label">瑙勬牸鍚嶇О</text>
+        <text class="value">{{ routeInfo.model || '-' }}</text>
+      </view>
+      <view class="info-row">
+        <text class="label">BOM缂栧彿</text>
+        <text class="value">{{ routeInfo.bomNo || '-' }}</text>
+      </view>
+    </view>
+    <!-- 閫夐」鍗″垏鎹� -->
+    <view class="tabs-box">
+      <up-tabs :list="tabsList"
+               @click="handleTabClick"
+               :current="currentTab"></up-tabs>
+    </view>
+    <!-- 宸ュ簭椤圭洰鍒楄〃 -->
+    <scroll-view scroll-y
+                 class="content-scroll"
+                 v-if="currentTab === 0">
+      <view v-if="itemsList.length > 0">
+        <view v-for="(item, index) in itemsList"
+              :key="index"
+              class="process-card">
+          <view class="card-header">
+            <view class="index-badge">{{ index + 1 }}</view>
+            <text class="process-name">{{ item.technologyOperationName || item.operationName || '-' }}</text>
+          </view>
+          <view class="card-content">
+            <view class="detail-row">
+              <text class="detail-label">鍏宠仈浜у搧</text>
+              <text class="detail-value">{{ item.productName || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">瑙勬牸鍨嬪彿</text>
+              <text class="detail-value">{{ item.model || '-' }}</text>
+            </view>
+            <view class="detail-row">
+              <text class="detail-label">鍗曚綅</text>
+              <text class="detail-value">{{ item.unit || '-' }}</text>
+            </view>
+            <view class="tag-row">
+              <up-tag v-if="item.isQuality"
+                      text="璐ㄦ"
+                      type="primary"
+                      size="mini"
+                      plain />
+              <up-tag v-if="item.isProduction"
+                      text="鐢熶骇"
+                      type="success"
+                      size="mini"
+                      plain />
+              <up-tag v-if="item.type==0"
+                      text="璁℃椂"
+                      type="info"
+                      size="mini"
+                      plain />
+              <up-tag v-else
+                      text="璁′欢"
+                      type="warning"
+                      size="mini"
+                      plain />
+            </view>
+          </view>
+          <view class="card-footer"
+                @click="showParams(item)">
+            <text class="action-text">鏌ョ湅鍙傛暟鍒楄〃</text>
+            <up-icon name="arrow-right"
+                     size="14"
+                     color="#3c9cff"></up-icon>
+          </view>
+        </view>
+      </view>
+      <view v-else
+            class="no-data">
+        <up-empty mode="data"
+                  text="鏆傛棤璺嚎椤圭洰"></up-empty>
+      </view>
+    </scroll-view>
+    <!-- BOM 缁撴瀯灞曠ず -->
+    <scroll-view scroll-y
+                 class="content-scroll"
+                 v-if="currentTab === 1">
+      <view v-if="bomList.length > 0"
+            class="bom-tree">
+        <view v-for="(node, nIndex) in flatBomList"
+              :key="nIndex"
+              class="bom-node"
+              :style="{ paddingLeft: (node.level * 40) + 'rpx' }">
+          <view class="bom-node-inner">
+            <view class="bom-line"
+                  v-if="node.level > 0"></view>
+            <view class="bom-content">
+              <view class="bom-header">
+                <text class="bom-product">{{ node.productName }}</text>
+                <text class="bom-model"
+                      v-if="node.model">({{ node.model }})</text>
+              </view>
+              <view class="bom-details">
+                <text class="bom-info">宸ュ簭: {{ node.operationName || '-' }}</text>
+                <text class="bom-info">鎵�闇�: {{ node.unitQuantity || 0 }} {{ node.unit || '' }}</text>
+              </view>
+            </view>
+          </view>
+        </view>
+      </view>
+      <view v-else
+            class="no-data">
+        <up-empty mode="data"
+                  text="鏆傛棤 BOM 缁撴瀯"></up-empty>
+      </view>
+    </scroll-view>
+    <!-- 鍙傛暟鍒楄〃寮圭獥 -->
+    <up-popup :show="showPopup"
+              mode="bottom"
+              @close="showPopup = false"
+              round="10">
+      <view class="popup-content">
+        <view class="popup-header">
+          <text class="title">鍙傛暟鍒楄〃 - {{ currentItem.technologyOperationName || currentItem.operationName }}</text>
+          <up-icon name="close"
+                   size="20"
+                   @click="showPopup = false"></up-icon>
+        </view>
+        <scroll-view scroll-y
+                     class="param-list">
+          <view v-if="paramList.length > 0">
+            <view v-for="(param, pIndex) in paramList"
+                  :key="pIndex"
+                  class="param-item">
+              <view class="param-row">
+                <text class="param-label">鍙傛暟鍚嶇О锛�</text>
+                <text class="param-value">{{ param.paramName || '-' }}</text>
+              </view>
+              <view class="param-row">
+                <text class="param-label">鏍囧噯鍊硷細</text>
+                <text class="param-value">{{ param.standardValue || '-' }}</text>
+              </view>
+              <view class="param-row">
+                <text class="param-label">鍗曚綅锛�</text>
+                <text class="param-value">{{ param.unit || '-' }}</text>
+              </view>
+            </view>
+          </view>
+          <view v-else
+                class="no-record">
+            <text>鏆傛棤鍙傛暟璁板綍</text>
+          </view>
+        </scroll-view>
+      </view>
+    </up-popup>
+  </view>
+</template>
+
+<script setup>
+  import { ref, reactive, computed } from "vue";
+  import { onLoad } from "@dcloudio/uni-app";
+  import {
+    findProcessRouteItemList,
+    getProcessParamList,
+    queryBomList,
+  } from "@/api/productionManagement/processRoute.js";
+  import {
+    queryOrderBomList,
+    findProcessParamListOrder,
+  } from "@/api/productionManagement/productionOrder.js";
+  import PageHeader from "@/components/PageHeader.vue";
+
+  const routeInfo = ref({});
+  const itemsList = ref([]);
+  const bomList = ref([]);
+  const loading = ref(false);
+  const pageType = ref("route"); // route | order
+
+  // 閫夐」鍗�
+  const tabsList = reactive([{ name: "璺嚎椤圭洰" }, { name: "BOM缁撴瀯" }]);
+  const currentTab = ref(0);
+
+  // 寮圭獥鐩稿叧
+  const showPopup = ref(false);
+  const currentItem = ref({});
+  const paramList = ref([]);
+  const paramLoading = ref(false);
+
+  const goBack = () => {
+    uni.navigateBack();
+  };
+
+  const handleTabClick = item => {
+    currentTab.value = item.index;
+    if (item.index === 1 && bomList.value.length === 0) {
+      fetchBom();
+    }
+  };
+
+  // 鎵佸钩鍖� BOM 鏍戠敤浜庡睍绀�
+  const flatBomList = computed(() => {
+    const result = [];
+    const flatten = (nodes, level = 0) => {
+      nodes.forEach(node => {
+        result.push({ ...node, level });
+        if (node.children && node.children.length > 0) {
+          flatten(node.children, level + 1);
+        }
+      });
+    };
+    flatten(bomList.value);
+    return result;
+  });
+
+  onLoad(options => {
+    if (options.id) {
+      pageType.value = options.type || "route";
+      routeInfo.value = {
+        id: options.id,
+        processRouteCode: options.processRouteCode || "",
+        productName: decodeURIComponent(options.productName || ""),
+        model: decodeURIComponent(options.model || ""),
+        bomNo: options.bomNo || "",
+        bomId: options.bomId || "",
+        description: decodeURIComponent(options.description || ""),
+        orderId: options.orderId || "",
+      };
+      fetchItems(options.id);
+    }
+  });
+
+  const fetchItems = id => {
+    loading.value = true;
+    findProcessRouteItemList({ routeId: id, orderId: routeInfo.value.orderId })
+      .then(res => {
+        itemsList.value = res.data || [];
+        loading.value = false;
+      })
+      .catch(() => {
+        loading.value = false;
+        uni.showToast({
+          title: "鑾峰彇椤圭洰澶辫触",
+          icon: "error",
+        });
+      });
+  };
+
+  const fetchBom = () => {
+    console.log(routeInfo.value.bomId, "routeInfo.value.bomId");
+
+    if (!routeInfo.value.bomId) return;
+    loading.value = true;
+    const api = pageType.value === "order" ? queryOrderBomList : queryBomList;
+    api(routeInfo.value.bomId)
+      .then(res => {
+        bomList.value = res.data || [];
+        loading.value = false;
+      })
+      .catch(() => {
+        loading.value = false;
+        uni.showToast({
+          title: "鑾峰彇 BOM 澶辫触",
+          icon: "error",
+        });
+      });
+  };
+
+  const showParams = item => {
+    currentItem.value = item;
+    showPopup.value = true;
+    paramLoading.value = true;
+    paramList.value = [];
+
+    const api =
+      pageType.value === "order"
+        ? findProcessParamListOrder
+        : getProcessParamList;
+    const params =
+      pageType.value === "order"
+        ? {
+            productionOrderRoutingOperationId: item.id,
+            productionOrderId: routeInfo.value.orderId,
+          }
+        : { technologyRoutingOperationId: item.id };
+
+    api(params)
+      .then(res => {
+        paramList.value = res.data || [];
+        paramLoading.value = false;
+      })
+      .catch(() => {
+        paramLoading.value = false;
+        uni.showToast({
+          title: "鑾峰彇鍙傛暟澶辫触",
+          icon: "error",
+        });
+      });
+  };
+</script>
+
+<style scoped lang="scss">
+  .process-route-items {
+    min-height: 100vh;
+    background: #f8f9fa;
+    display: flex;
+    flex-direction: column;
+  }
+
+  .route-info-card {
+    background: #fff;
+    margin: 20rpx;
+    padding: 24rpx;
+    border-radius: 16rpx;
+    box-shadow: 0 2rpx 12rpx rgba(0, 0, 0, 0.05);
+
+    .info-row {
+      display: flex;
+      justify-content: space-between;
+      margin-bottom: 12rpx;
+      &:last-child {
+        margin-bottom: 0;
+      }
+
+      .label {
+        font-size: 26rpx;
+        color: #999;
+      }
+      .value {
+        font-size: 26rpx;
+        color: #333;
+        font-weight: bold;
+      }
+    }
+  }
+
+  .tabs-box {
+    background: #fff;
+    margin-bottom: 10rpx;
+  }
+
+  .content-scroll {
+    flex: 1;
+    height: 0;
+    padding: 0 20rpx;
+  }
+
+  .process-card {
+    background: #fff;
+    margin-bottom: 24rpx;
+    border-radius: 16rpx;
+    overflow: hidden;
+    box-shadow: 0 4rpx 16rpx rgba(0, 0, 0, 0.05);
+
+    .card-header {
+      display: flex;
+      align-items: center;
+      padding: 20rpx 24rpx;
+      background: #fcfcfc;
+      border-bottom: 1rpx solid #f5f5f5;
+
+      .index-badge {
+        width: 40rpx;
+        height: 40rpx;
+        background: #3c9cff;
+        color: #fff;
+        border-radius: 20rpx;
+        display: flex;
+        justify-content: center;
+        align-items: center;
+        font-size: 24rpx;
+        margin-right: 20rpx;
+      }
+
+      .process-name {
+        font-size: 28rpx;
+        font-weight: bold;
+        color: #333;
+      }
+    }
+
+    .card-content {
+      padding: 24rpx;
+
+      .detail-row {
+        display: flex;
+        justify-content: space-between;
+        margin-bottom: 12rpx;
+
+        .detail-label {
+          font-size: 24rpx;
+          color: #999;
+        }
+        .detail-value {
+          font-size: 24rpx;
+          color: #666;
+        }
+      }
+
+      .tag-row {
+        display: flex;
+        gap: 16rpx;
+        margin-top: 10rpx;
+      }
+    }
+
+    .card-footer {
+      padding: 16rpx 24rpx;
+      border-top: 1rpx dashed #eee;
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+
+      .action-text {
+        font-size: 24rpx;
+        color: #3c9cff;
+      }
+    }
+  }
+
+  /* BOM 鏍戞牱寮� */
+  .bom-tree {
+    padding: 20rpx 0;
+  }
+
+  .bom-node {
+    position: relative;
+    margin-bottom: 20rpx;
+  }
+
+  .bom-node-inner {
+    background: #fff;
+    padding: 20rpx;
+    border-radius: 12rpx;
+    box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.03);
+    display: flex;
+    align-items: center;
+  }
+
+  .bom-line {
+    position: absolute;
+    left: -20rpx;
+    top: 50%;
+    width: 20rpx;
+    height: 2rpx;
+    background: #ddd;
+  }
+
+  .bom-content {
+    flex: 1;
+  }
+
+  .bom-header {
+    display: flex;
+    align-items: center;
+    margin-bottom: 8rpx;
+
+    .bom-product {
+      font-size: 28rpx;
+      font-weight: bold;
+      color: #333;
+    }
+
+    .bom-model {
+      font-size: 24rpx;
+      color: #999;
+      margin-left: 10rpx;
+    }
+  }
+
+  .bom-details {
+    display: flex;
+    justify-content: space-between;
+
+    .bom-info {
+      font-size: 24rpx;
+      color: #666;
+    }
+  }
+
+  .no-data {
+    padding-top: 100rpx;
+  }
+
+  /* 寮圭獥鏍峰紡 */
+  .popup-content {
+    background: #fff;
+    padding: 30rpx;
+    max-height: 70vh;
+    display: flex;
+    flex-direction: column;
+  }
+
+  .popup-header {
+    display: flex;
+    justify-content: space-between;
+    align-items: center;
+    padding-bottom: 30rpx;
+    border-bottom: 1rpx solid #eee;
+
+    .title {
+      font-size: 30rpx;
+      font-weight: bold;
+      color: #333;
+    }
+  }
+
+  .param-list {
+    flex: 1;
+    height: 0;
+    padding-top: 20rpx;
+  }
+
+  .param-item {
+    padding: 20rpx;
+    background: #f9f9f9;
+    border-radius: 12rpx;
+    margin-bottom: 16rpx;
+
+    .param-row {
+      display: flex;
+      margin-bottom: 8rpx;
+      &:last-child {
+        margin-bottom: 0;
+      }
+
+      .param-label {
+        font-size: 24rpx;
+        color: #999;
+        width: 140rpx;
+      }
+      .param-value {
+        font-size: 24rpx;
+        color: #333;
+        flex: 1;
+      }
+    }
+  }
+
+  .no-record {
+    padding: 100rpx 0;
+    text-align: center;
+    color: #999;
+    font-size: 26rpx;
+  }
+</style>

--
Gitblit v1.9.3