From 2fb38b2d2d005c0ff524b619a529fee1ca151095 Mon Sep 17 00:00:00 2001
From: yyb <995253665@qq.com>
Date: 星期二, 21 四月 2026 16:49:05 +0800
Subject: [PATCH] 审批人

---
 src/pages/inventoryManagement/scanIn/index.vue |  233 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 230 insertions(+), 3 deletions(-)

diff --git a/src/pages/inventoryManagement/scanIn/index.vue b/src/pages/inventoryManagement/scanIn/index.vue
index 147a7f0..6502574 100644
--- a/src/pages/inventoryManagement/scanIn/index.vue
+++ b/src/pages/inventoryManagement/scanIn/index.vue
@@ -109,6 +109,51 @@
           </view>
         </view>
       </view>
+      <view class="approval-process">
+        <view class="approval-header">
+          <text class="approval-title">瀹℃牳娴佺▼</text>
+          <text class="approval-desc">姣忎釜姝ラ鍙兘閫夋嫨涓�涓鎵逛汉</text>
+        </view>
+        <view class="approval-steps">
+          <view v-for="(step, stepIndex) in stockApproverNodes"
+                :key="step.id"
+                class="approval-step">
+            <view class="step-title">
+              <text>瀹℃壒浜�</text>
+            </view>
+            <view class="approver-container">
+              <view v-if="step.userName"
+                    class="approver-item">
+                <view class="approver-avatar">
+                  <text class="avatar-text">{{ step.userName.charAt(0) }}</text>
+                </view>
+                <view class="approver-info">
+                  <text class="approver-name">{{ step.userName }}</text>
+                </view>
+                <view class="delete-approver-btn"
+                      @click="removeApprover(stepIndex)">脳</view>
+              </view>
+              <view v-else
+                    class="add-approver-btn"
+                    @click="openApproverPicker(stepIndex)">
+                <view class="add-circle">+</view>
+                <text class="add-label">閫夋嫨瀹℃壒浜�</text>
+              </view>
+            </view>
+            <view class="delete-step-btn"
+                  v-if="stockApproverNodes.length > 1"
+                  @click="removeStockApproverNode(stepIndex)">鍒犻櫎鑺傜偣</view>
+          </view>
+        </view>
+        <view class="add-step-btn">
+          <u-button icon="plus"
+                    plain
+                    type="primary"
+                    style="width: 100%"
+                    @click="addStockApproverNode">鏂板鑺傜偣</u-button>
+        </view>
+      </view>
+
       <view class="footer-btns">
         <u-button class="footer-cancel-btn"
                   @click="cancelForm">杩斿洖</u-button>
@@ -117,11 +162,12 @@
                   @click="confirmInbound">纭鍏ュ簱</u-button>
       </view>
     </scroll-view>
+
   </view>
 </template>
 
 <script setup>
-  import { ref, computed } from "vue";
+  import { ref, computed, onMounted, onUnmounted } from "vue";
   import PageHeader from "@/components/PageHeader.vue";
   import { productList as salesProductList } from "@/api/salesManagement/salesLedger";
   import modal from "@/plugins/modal";
@@ -146,6 +192,8 @@
   const contractKind = ref(CONTRACT_KIND.sales);
   const scanLedgerId = ref(null);
   const submitLoading = ref(false);
+  const stockApproverNodes = ref([{ id: 1, userId: null, userName: "" }]);
+  let nextApproverNodeId = 2;
   const submitConfigByScene = createSubmitConfig(scanLedgerId);
 
   const cardTitleMain = computed(() => {
@@ -315,9 +363,65 @@
     scanLedgerId.value = null;
     expandedByIndex.value = {};
     recordList.value = [];
+    stockApproverNodes.value = [{ id: 1, userId: null, userName: "" }];
   };
 
-  const confirmInbound = async () => {
+  onMounted(() => {
+    uni.$on("selectContact", handleSelectContact);
+  });
+
+  onUnmounted(() => {
+    uni.$off("selectContact", handleSelectContact);
+  });
+
+  const addStockApproverNode = () => {
+    stockApproverNodes.value.push({
+      id: nextApproverNodeId++,
+      userId: null,
+      userName: "",
+    });
+  };
+
+  const removeStockApproverNode = index => {
+    if (stockApproverNodes.value.length <= 1) {
+      modal.msgError("鑷冲皯淇濈暀涓�涓鎵硅妭鐐�");
+      return;
+    }
+    stockApproverNodes.value.splice(index, 1);
+  };
+
+  const removeApprover = stepIndex => {
+    if (!stockApproverNodes.value[stepIndex]) return;
+    stockApproverNodes.value[stepIndex].userId = null;
+    stockApproverNodes.value[stepIndex].userName = "";
+  };
+
+  const openApproverPicker = index => {
+    uni.setStorageSync("stepIndex", index);
+    uni.navigateTo({
+      url: "/pages/cooperativeOffice/collaborativeApproval/contactSelect?approveType=9",
+    });
+  };
+
+  const handleSelectContact = data => {
+    const { stepIndex, contact } = data || {};
+    if (stepIndex === null || stepIndex === undefined) return;
+    const idx = Number(stepIndex);
+    if (Number.isNaN(idx) || !stockApproverNodes.value[idx]) return;
+    stockApproverNodes.value[idx].userId = contact?.userId ?? null;
+    stockApproverNodes.value[idx].userName = contact?.nickName || contact?.userName || "";
+  };
+
+  const validateApproverNodes = () => {
+    const hasEmptyNode = stockApproverNodes.value.some(node => !node.userId);
+    if (hasEmptyNode) {
+      modal.msgError("璇蜂负姣忎釜瀹℃壒鑺傜偣閫夋嫨瀹℃壒浜�");
+      return false;
+    }
+    return true;
+  };
+
+  const submitInbound = async () => {
     if (scanLedgerId.value == null || scanLedgerId.value === "") {
       modal.msgError("缂哄皯璁㈠崟淇℃伅锛岃閲嶆柊鎵爜");
       return;
@@ -334,7 +438,11 @@
       return;
     }
     const runApi = currentSubmitConfig.runApi;
-    const payload = currentSubmitConfig.payloadBuilder(salesLedgerProductList);
+    const inboundApproveUserIds = stockApproverNodes.value.map(node => node.userId).join(",");
+    const payload = currentSubmitConfig.payloadBuilder(
+      salesLedgerProductList,
+      inboundApproveUserIds
+    );
     try {
       submitLoading.value = true;
       modal.loading("鎻愪氦涓�...");
@@ -352,6 +460,11 @@
     } finally {
       submitLoading.value = false;
     }
+  };
+
+  const confirmInbound = () => {
+    if (!validateApproverNodes()) return;
+    submitInbound();
   };
 
   const goBack = () => {
@@ -638,4 +751,118 @@
     color: #fff;
     border: none;
   }
+
+  .approval-process {
+    background: #fff;
+    margin: 20rpx;
+    border-radius: 16rpx;
+    padding: 24rpx;
+  }
+
+  .approval-header {
+    margin-bottom: 16rpx;
+  }
+
+  .approval-title {
+    font-size: 30rpx;
+    font-weight: 600;
+    color: #333;
+    display: block;
+  }
+
+  .approval-desc {
+    font-size: 24rpx;
+    color: #999;
+    margin-top: 6rpx;
+  }
+
+  .approval-step {
+    margin-bottom: 18rpx;
+  }
+
+  .step-title text {
+    font-size: 24rpx;
+    color: #666;
+  }
+
+  .approver-container {
+    display: flex;
+    align-items: center;
+    margin-top: 10rpx;
+  }
+
+  .approver-item {
+    width: 100%;
+    display: flex;
+    align-items: center;
+    gap: 12rpx;
+    padding: 12rpx 0;
+  }
+
+  .approver-avatar {
+    width: 64rpx;
+    height: 64rpx;
+    border-radius: 50%;
+    background: #f3f4f6;
+    border: 2rpx solid #e5e7eb;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+  }
+
+  .avatar-text {
+    font-size: 24rpx;
+    color: #374151;
+    font-weight: 600;
+  }
+
+  .approver-info {
+    flex: 1;
+  }
+
+  .approver-name {
+    font-size: 28rpx;
+    color: #333;
+  }
+
+  .delete-approver-btn {
+    font-size: 32rpx;
+    color: #ff4d4f;
+    padding: 0 8rpx;
+  }
+
+  .add-approver-btn {
+    display: flex;
+    align-items: center;
+    gap: 10rpx;
+    color: #3b82f6;
+    padding: 10rpx 0;
+  }
+
+  .add-circle {
+    width: 52rpx;
+    height: 52rpx;
+    border: 2rpx dashed #a0aec0;
+    border-radius: 50%;
+    color: #6b7280;
+    display: flex;
+    align-items: center;
+    justify-content: center;
+    font-size: 34rpx;
+    line-height: 1;
+  }
+
+  .add-label {
+    font-size: 26rpx;
+  }
+
+  .delete-step-btn {
+    color: #ff4d4f;
+    font-size: 24rpx;
+    margin-top: 8rpx;
+  }
+
+  .add-step-btn {
+    margin-top: 8rpx;
+  }
 </style>

--
Gitblit v1.9.3