From a6667d3351aea21abc363c35285e066ee37f40b2 Mon Sep 17 00:00:00 2001
From: zhang_nuo <zhang_12370@163.com>
Date: 星期二, 15 九月 2026 19:45:07 +0800
Subject: [PATCH] feat(qualityManagement): add batch selection for product binding tree

---
 src/views/qualityManagement/metricBinding/index.vue |  102 ++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 93 insertions(+), 9 deletions(-)

diff --git a/src/views/qualityManagement/metricBinding/index.vue b/src/views/qualityManagement/metricBinding/index.vue
index ba989ea..d353bac 100644
--- a/src/views/qualityManagement/metricBinding/index.vue
+++ b/src/views/qualityManagement/metricBinding/index.vue
@@ -124,13 +124,19 @@
       @close="closeBindingDialog"
     >
       <div class="binding-dialog">
-        <el-input
-          v-model="productSearchKeyword"
-          placeholder="鎼滅储浜у搧"
-          clearable
-          prefix-icon="Search"
-          class="binding-search"
-        />
+        <div class="tree-toolbar">
+          <el-input
+            v-model="productSearchKeyword"
+            placeholder="鎼滅储浜у搧"
+            clearable
+            prefix-icon="Search"
+            class="binding-search"
+          />
+          <div class="tree-actions">
+            <el-button size="small" @click="handleCheckAll">鍏ㄩ��</el-button>
+            <el-button size="small" @click="handleCheckNone">娓呯┖</el-button>
+          </div>
+        </div>
         <el-tree
           ref="productTreeRef"
           :key="productTreeKey"
@@ -143,7 +149,18 @@
           :filter-node-method="filterProductNode"
           class="product-binding-tree"
           @check="handleProductTreeCheck"
-        />
+        >
+          <template #default="{ node, data }">
+            <span class="custom-tree-node">
+              <span class="node-label">{{ node.label }}</span>
+              <span v-if="data.children?.length" class="node-action">
+                <el-button link type="primary" size="small" @click.stop="handleCheckNodeChildren(data)">
+                  鍏ㄩ��
+                </el-button>
+              </span>
+            </span>
+          </template>
+        </el-tree>
         <div v-if="selectedProductLabels.length" class="selected-products">
           <div class="selected-title">宸查�夋嫨锛坽{ selectedProductLabels.length }}锛�</div>
           <div class="selected-tags">
@@ -343,6 +360,45 @@
 
 const handleProductTreeCheck = () => {
   selectedProductIds.value = productTreeRef.value?.getCheckedKeys(true) || []
+}
+
+// 鏀堕泦鎵�鏈夊彾瀛愯妭鐐� id
+const collectLeafNodeIds = (nodes) => {
+  const ids = []
+  const walk = (list) => {
+    ;(list || []).forEach((node) => {
+      if (node.children?.length) {
+        walk(node.children)
+      } else if (!node.disabled && node.id != null) {
+        ids.push(node.id)
+      }
+    })
+  }
+  walk(nodes)
+  return ids
+}
+
+// 鍏ㄩ�夛細閫変腑鎵�鏈夊彾瀛愯妭鐐�
+const handleCheckAll = () => {
+  const leafIds = collectLeafNodeIds(productTreeData.value)
+  productTreeRef.value?.setCheckedKeys(leafIds, false)
+  selectedProductIds.value = leafIds
+}
+
+// 娓呯┖锛氬彇娑堟墍鏈夐�変腑
+const handleCheckNone = () => {
+  productTreeRef.value?.setCheckedKeys([], false)
+  selectedProductIds.value = []
+}
+
+// 閫変腑褰撳墠鑺傜偣涓嬬殑鎵�鏈夊彾瀛愯妭鐐�
+const handleCheckNodeChildren = (data) => {
+  const leafIds = collectLeafNodeIds(data.children || [])
+  // 鍚堝苟褰撳墠宸查�変腑鐨� id
+  const currentChecked = productTreeRef.value?.getCheckedKeys(true) || []
+  const merged = Array.from(new Set([...currentChecked, ...leafIds]))
+  productTreeRef.value?.setCheckedKeys(merged, false)
+  selectedProductIds.value = merged
 }
 
 const removeSelectedProduct = (id) => {
@@ -614,8 +670,20 @@
   gap: 12px;
 }
 
+.tree-toolbar {
+  display: flex;
+  align-items: center;
+  gap: 10px;
+}
+
 .binding-search {
-  width: 100%;
+  flex: 1;
+}
+
+.tree-actions {
+  display: flex;
+  gap: 6px;
+  flex-shrink: 0;
 }
 
 .product-binding-tree {
@@ -626,6 +694,22 @@
   padding: 8px;
 }
 
+.custom-tree-node {
+  display: flex;
+  align-items: center;
+  justify-content: space-between;
+  width: 100%;
+  padding-right: 8px;
+}
+
+.node-label {
+  flex: 1;
+}
+
+.node-action {
+  flex-shrink: 0;
+}
+
 .selected-products {
   border-top: 1px solid #ebeef5;
   padding-top: 12px;

--
Gitblit v1.9.3