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/productionDesign/bom/BomStructureItem.vue |  256 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 256 insertions(+), 0 deletions(-)

diff --git a/src/pages/productionDesign/bom/BomStructureItem.vue b/src/pages/productionDesign/bom/BomStructureItem.vue
new file mode 100644
index 0000000..689010c
--- /dev/null
+++ b/src/pages/productionDesign/bom/BomStructureItem.vue
@@ -0,0 +1,256 @@
+<template>
+  <view class="structure-item-wrapper"
+        :class="{ 'is-root': level === 0, 'is-last': isLast }">
+    <!-- 鏍戝舰杩炴帴绾� (闈炴牴鑺傜偣鏄剧ず) -->
+    <template v-if="level > 0">
+      <view class="line-v"></view>
+      <view class="line-h"></view>
+    </template>
+    <view class="structure-item-card"
+          :class="{ 'has-children': hasChildren }">
+      <view class="card-main">
+        <view class="item-header"
+              @click="toggleExpand">
+          <view class="header-left">
+            <view v-if="hasChildren"
+                  class="expand-icon"
+                  :class="{ 'is-expanded': isExpanded }">
+              <up-icon name="arrow-right"
+                       size="14"
+                       color="#999"></up-icon>
+            </view>
+            <view v-else
+                  class="dot-icon"></view>
+            <text class="item-title">{{ item.productName || '鏈�夋嫨浜у搧' }}</text>
+          </view>
+          <up-tag v-if="hasChildren"
+                  text="缁勫悎"
+                  type="primary"
+                  size="mini"
+                  plain
+                  shape="circle" />
+        </view>
+        <view class="item-body">
+          <view class="info-grid">
+            <view class="info-item">
+              <text class="label">瑙勬牸鍨嬪彿锛�</text>
+              <text class="value">{{ item.model || '-' }}</text>
+            </view>
+            <view class="info-item">
+              <text class="label">娑堣�楀伐搴忥細</text>
+              <text class="value">{{ getProcessName(item.processId) }}</text>
+            </view>
+            <view class="info-item">
+              <text class="label">鍗曚綅鏁伴噺锛�</text>
+              <text class="value highlight">{{ item.unitQuantity || 0 }}</text>
+            </view>
+            <view class="info-item">
+              <text class="label">闇�姹傛�婚噺锛�</text>
+              <text class="value highlight">{{ item.demandedQuantity || 0 }}</text>
+            </view>
+            <view class="info-item">
+              <text class="label">鍗曚綅锛�</text>
+              <text class="value">{{ item.unit || '-' }}</text>
+            </view>
+            <view class="info-item">
+              <text class="label">鐩樻暟锛�</text>
+              <text class="value">{{ item.diskQuantity || 0 }}</text>
+            </view>
+          </view>
+        </view>
+      </view>
+    </view>
+    <!-- 閫掑綊灞曠ず瀛愯妭鐐� -->
+    <view v-if="hasChildren && isExpanded"
+          class="children-container">
+      <BomStructureItem v-for="(child, index) in item.children"
+                        :key="index"
+                        :item="child"
+                        :level="level + 1"
+                        :isLast="index === item.children.length - 1"
+                        :processOptions="processOptions" />
+    </view>
+  </view>
+</template>
+
+<script setup>
+  import { ref, computed, defineProps } from "vue";
+
+  const props = defineProps({
+    item: {
+      type: Object,
+      required: true,
+    },
+    level: {
+      type: Number,
+      default: 0,
+    },
+    isLast: {
+      type: Boolean,
+      default: false,
+    },
+    processOptions: {
+      type: Array,
+      default: () => [],
+    },
+  });
+
+  const isExpanded = ref(true);
+  const hasChildren = computed(
+    () => props.item.children && props.item.children.length > 0
+  );
+
+  const toggleExpand = () => {
+    if (hasChildren.value) {
+      isExpanded.value = !isExpanded.value;
+    }
+  };
+
+  const getProcessName = id => {
+    const process = props.processOptions.find(p => p.id === id);
+    return process ? process.name : "-";
+  };
+</script>
+
+<script>
+  export default {
+    name: "BomStructureItem",
+  };
+</script>
+
+<style scoped lang="scss">
+  .structure-item-wrapper {
+    position: relative;
+    padding-left: 44rpx;
+
+    &.is-root {
+      padding-left: 0;
+    }
+  }
+
+  // 鍨傜洿杩炴帴绾挎
+  .line-v {
+    position: absolute;
+    left: 18rpx; // 灞呬腑浜� 44rpx 鐨勭缉杩涘唴
+    top: -20rpx; // 鍚戜笂寤朵几瑕嗙洊涓婁竴涓妭鐐圭殑 margin-bottom
+    bottom: 0;
+    width: 2rpx;
+    background-color: #ddd;
+    z-index: 1;
+  }
+
+  // 鏈�鍚庝竴涓妭鐐圭殑鍨傜洿绾垮彧寤朵几鍒版按骞崇嚎浣嶇疆
+  .is-last > .line-v {
+    bottom: auto;
+    height: 60rpx; // 20rpx (top offset) + 40rpx (to horizontal line)
+  }
+
+  // 姘村钩杩炴帴绾�
+  .line-h {
+    position: absolute;
+    left: 18rpx;
+    top: 40rpx; // 瀵归綈鍒板崱鐗囧唴閮ㄥ浘鏍囦腑蹇� (padding 24 + icon 32/2)
+    width: 26rpx;
+    height: 2rpx;
+    background-color: #ddd;
+    z-index: 1;
+  }
+
+  .structure-item-card {
+    position: relative;
+    background: #fff;
+    border-radius: 16rpx;
+    margin-bottom: 20rpx;
+    padding: 24rpx;
+    box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
+    border: 1rpx solid #f0f0f0;
+    transition: all 0.3s;
+    z-index: 2;
+
+    &:active {
+      background-color: #f9f9f9;
+    }
+
+    &.has-children {
+      border-left: 6rpx solid #3c9cff;
+    }
+  }
+
+  .card-main {
+    .item-header {
+      display: flex;
+      justify-content: space-between;
+      align-items: center;
+      margin-bottom: 20rpx;
+
+      .header-left {
+        display: flex;
+        align-items: center;
+        flex: 1;
+
+        .expand-icon {
+          margin-right: 12rpx;
+          transition: transform 0.3s;
+          display: flex;
+          align-items: center;
+          justify-content: center;
+          width: 32rpx;
+          height: 32rpx;
+
+          &.is-expanded {
+            transform: rotate(90deg);
+          }
+        }
+
+        .dot-icon {
+          width: 12rpx;
+          height: 12rpx;
+          border-radius: 50%;
+          background-color: #ccc;
+          margin-right: 20rpx;
+          margin-left: 10rpx;
+        }
+
+        .item-title {
+          font-size: 30rpx;
+          font-weight: bold;
+          color: #333;
+          line-height: 1.4;
+        }
+      }
+    }
+
+    .item-body {
+      .info-grid {
+        display: grid;
+        grid-template-columns: 1fr 1fr;
+        gap: 12rpx 20rpx;
+
+        .info-item {
+          display: flex;
+          font-size: 24rpx;
+          line-height: 1.5;
+
+          .label {
+            color: #999;
+            white-space: nowrap;
+          }
+
+          .value {
+            color: #666;
+            word-break: break-all;
+
+            &.highlight {
+              color: #3c9cff;
+              font-weight: 500;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  .children-container {
+    position: relative;
+  }
+</style>

--
Gitblit v1.9.3