From 5da536668e047dbaefbb79731ab2cacfdf70dc56 Mon Sep 17 00:00:00 2001
From: zhang_12370 <z2864490065@outlook.com>
Date: 星期二, 22 七月 2025 17:36:38 +0800
Subject: [PATCH] 1、提交配煤计算器 解除煤种限制 2、增加销售出库的导出功能 3、库存管理正式库的导出功能 4、文档管理优化 5、优化设备管理模块

---
 src/views/archiveManagement/index.vue |  393 ++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 339 insertions(+), 54 deletions(-)

diff --git a/src/views/archiveManagement/index.vue b/src/views/archiveManagement/index.vue
index 81d3a18..8db8de6 100644
--- a/src/views/archiveManagement/index.vue
+++ b/src/views/archiveManagement/index.vue
@@ -34,13 +34,21 @@
             :expand-on-click-node="false"
             :filter-node-method="filterNode"
             :props="props"
+            :lazy="false"
+            :load="undefined"
+            :render-after-expand="true"
+            :auto-expand-parent="true"
+            :indent="20"
             class="custom-tree"
             node-key="id"
             @node-click="handleNodeClick"
+            @node-expand="handleNodeExpand"
           >
             <template #default="{ node, data }">
               <div
                 class="tree-node-content"
+                :data-temp-id="data._tempId"
+                :data-node-id="data.id"
                 @dblclick="headerDbClick(node, data)"
               >
                 <div class="node-icon">
@@ -61,7 +69,7 @@
                   }}</span>
                   <el-input
                     v-else
-                    :ref="(el) => setInputRef(el, data)"
+                    :ref="(el) => setInputRef(data.id || data._tempId, el)"
                     v-model="newName"
                     autofocus
                     class="tree-input"
@@ -69,6 +77,7 @@
                     size="small"
                     @blur="(event) => handleInputBlur(event, data, node)"
                     @keyup.enter="(event) => handleInputBlur(event, data, node)"
+                    @keyup.esc="() => cancelEdit(data, node)"
                   />
                 </div>
                 <div v-show="!data.isEdit" class="node-actions">
@@ -76,7 +85,8 @@
                     icon="Plus"
                     link
                     size="small"
-                    title="鏂板瀛愯妭鐐�"
+                    :title="getNodeDepth(data) >= 7 ? '宸茶揪鍒版渶澶у祵濂楀眰绾э紙7灞傦級' : '鏂板瀛愯妭鐐�'"
+                    :disabled="getNodeDepth(data) >= 7"
                     @click.stop="append(data)"
                   ></el-button>
                   <el-button
@@ -165,7 +175,7 @@
   </el-card>
 </template>
 <script setup>
-import { nextTick, onMounted, reactive, ref } from "vue";
+import { computed, nextTick, onMounted, reactive, ref } from "vue";
 import ETable from "@/components/Table/ETable.vue";
 import {
   ElButton,
@@ -226,6 +236,41 @@
   label: "name",
   children: "children",
   isLeaf: "leaf",
+};
+
+// ===== 璁$畻灞炴�� =====
+// 璁$畻鎬昏妭鐐规暟
+const totalNodeCount = computed(() => {
+  const countNodes = (nodes) => {
+    let count = 0;
+    for (const node of nodes || []) {
+      count += 1;
+      if (node.children) {
+        count += countNodes(node.children);
+      }
+    }
+    return count;
+  };
+  return countNodes(treeData.value);
+});
+
+// 妫�鏌ユ槸鍚︿负澶ч噺鑺傜偣锛堣秴杩�1000涓妭鐐规椂鎻愮ず鎬ц兘浼樺寲锛�
+const isLargeTree = computed(() => totalNodeCount.value > 1000);
+
+// 鑾峰彇鑺傜偣娣卞害鐨勫嚱鏁�
+const getNodeDepth = (nodeData) => {
+  if (!nodeData || !nodeData.id) return 0;
+  
+  let depth = 1;
+  const node = treeRef.value?.getNode(nodeData.id);
+  let parentNode = node?.parent;
+  
+  while (parentNode && parentNode.data && parentNode.data.id) {
+    depth++;
+    parentNode = parentNode.parent;
+  }
+  
+  return depth;
 };
 
 // ===== 宸ュ叿鍑芥暟 =====
@@ -337,6 +382,20 @@
   getArchiveListData();
 };
 
+// 鑺傜偣灞曞紑浜嬩欢澶勭悊
+const handleNodeExpand = (data, node, instance) => {
+  // 灞曞紑鍚庣◢寰欢杩燂紝纭繚瀛愯妭鐐规覆鏌撳畬鎴�
+  setTimeout(() => {
+    // 濡傛灉鏈夋柊娣诲姞鐨勭紪杈戠姸鎬佽妭鐐癸紝鑱氱劍鍒板畠
+    if (data.children && data.children.length > 0) {
+      const editingChild = data.children.find(child => child.isEdit && child._tempId);
+      if (editingChild) {
+        focusInput(editingChild._tempId, 200);
+      }
+    }
+  }, 100);
+};
+
 const handlePageChange = (pagination) => {
   try {
     const { page, limit } = pagination;
@@ -427,22 +486,62 @@
   }
 };
 // ===== 鏍戣妭鐐圭紪杈戝嚱鏁� =====
-const setInputRef = (el, data) => {
-  if (el) {
-    inputRefs.value.set(data.id || data, el);
+const setInputRef = (key, el) => {
+  if (el && key) {
+    inputRefs.value.set(key, el);
   }
 };
 
 const headerDbClick = (node, data) => {
-  data.isEdit = true;
-  newName.value = data.name;
-  nextTick(() => {
-    const inputEl = inputRefs.value.get(data.id || data);
-    if (inputEl) {
-      inputEl.focus();
-      inputEl.select();
+  try {
+    data.isEdit = true;
+    newName.value = data.name;
+    
+    nextTick(() => {
+      const key = data._tempId || data.id;
+      if (key) {
+        focusInput(key, 50);
+      }
+    });
+  } catch (error) {
+    console.error('杩涘叆缂栬緫妯″紡澶辫触:', error);
+    ElMessage.error('杩涘叆缂栬緫妯″紡澶辫触');
+  }
+};
+
+// 鍙栨秷缂栬緫鍔熻兘
+const cancelEdit = (data, node) => {
+  try {
+    data.isEdit = false;
+    
+    // 濡傛灉鏄柊鍒涘缓鐨勪复鏃惰妭鐐癸紝鍒犻櫎瀹�
+    if (data._tempId && !data.id) {
+      if (node.parent) {
+        const parent = node.parent.data;
+        const index = parent.children?.indexOf(data);
+        if (index > -1) {
+          parent.children.splice(index, 1);
+        }
+      } else {
+        // 鏍硅妭鐐�
+        const index = treeData.value.indexOf(data);
+        if (index > -1) {
+          treeData.value.splice(index, 1);
+        }
+      }
+      
+      // 娓呯悊杈撳叆妗嗗紩鐢�
+      const key = data._tempId;
+      if (inputRefs.value.has(key)) {
+        inputRefs.value.delete(key);
+      }
     }
-  });
+    
+    // 閲嶇疆鍚嶇О
+    newName.value = "";
+  } catch (error) {
+    console.error('鍙栨秷缂栬緫澶辫触:', error);
+  }
 };
 
 const expandParentNodes = (node) => {
@@ -460,11 +559,21 @@
     comeTreeData.isEdit = false;
     const newValue = newName.value.trim();
 
-    if (comeTreeData.name === newValue) return;
-
+    // 濡傛灉鍚嶇О涓虹┖锛屽鐞嗙┖鍚嶇О鎯呭喌
     if (!newValue) {
-      newName.value = comeTreeData.name || "鏂拌妭鐐�";
+      // 濡傛灉鏄柊鍒涘缓鐨勪复鏃惰妭鐐癸紝鍒犻櫎瀹�
+      if (comeTreeData._tempId && !comeTreeData.id) {
+        cancelEdit(comeTreeData, node);
+      } else {
+        // 宸插瓨鍦ㄧ殑鑺傜偣锛屾仮澶嶅師鍚嶇О
+        newName.value = comeTreeData.name || "鏂拌妭鐐�";
+      }
       ElMessage.warning("鑺傜偣鍚嶇О涓嶈兘涓虹┖");
+      return;
+    }
+
+    // 濡傛灉鍚嶇О娌℃湁鏀瑰彉锛岀洿鎺ヨ繑鍥�
+    if (comeTreeData.name === newValue) {
       return;
     }
 
@@ -480,6 +589,20 @@
       comeTreeData.name = newValue;
       if (!comeTreeData.id && result.data) {
         comeTreeData.id = result.data.id || result.data;
+        // 娓呯悊涓存椂ID
+        if (comeTreeData._tempId) {
+          const tempKey = comeTreeData._tempId;
+          delete comeTreeData._tempId;
+          
+          // 鏇存柊寮曠敤鏄犲皠
+          if (inputRefs.value.has(tempKey)) {
+            const inputEl = inputRefs.value.get(tempKey);
+            inputRefs.value.delete(tempKey);
+            if (comeTreeData.id && inputEl) {
+              inputRefs.value.set(comeTreeData.id, inputEl);
+            }
+          }
+        }
       }
       showSuccess("淇濆瓨鎴愬姛");
 
@@ -490,18 +613,42 @@
         if (currentNodeId && treeRef.value) {
           const targetNode = treeRef.value.getNode(currentNodeId);
           if (targetNode) {
+            // 灞曞紑褰撳墠鑺傜偣
             targetNode.expanded = true;
+            
+            // 灞曞紑鎵�鏈夌埗鑺傜偣
             expandParentNodes(targetNode);
+            
+            // 婊氬姩鍒拌妭鐐逛綅缃�
+            setTimeout(() => {
+              const nodeElement = document.querySelector(`[data-node-id="${currentNodeId}"]`);
+              if (nodeElement) {
+                nodeElement.scrollIntoView({
+                  behavior: 'smooth',
+                  block: 'center'
+                });
+              }
+            }, 300);
           }
         }
       });
     } else {
-      comeTreeData.name = comeTreeData.name || "鏂拌妭鐐�";
+      // 淇濆瓨澶辫触锛屾仮澶嶅師鍚嶇О鎴栧垹闄や复鏃惰妭鐐�
+      if (comeTreeData._tempId && !comeTreeData.id) {
+        cancelEdit(comeTreeData, node);
+      } else {
+        comeTreeData.name = comeTreeData.name || "鏂拌妭鐐�";
+      }
       ElMessage.error("淇濆瓨澶辫触: " + (result.msg || "鏈煡閿欒"));
     }
   } catch (error) {
     handleError(error, "淇濆瓨鑺傜偣澶辫触");
-    comeTreeData.name = comeTreeData.name || "鏂拌妭鐐�";
+    // 鍑洪敊鏃跺鐞嗕复鏃惰妭鐐�
+    if (comeTreeData._tempId && !comeTreeData.id) {
+      cancelEdit(comeTreeData, node);
+    } else {
+      comeTreeData.name = comeTreeData.name || "鏂拌妭鐐�";
+    }
   }
 };
 
@@ -509,51 +656,167 @@
 const createNewNode = (name, isEdit = true) => ({
   name,
   isEdit,
+  _tempId: Date.now() + Math.random(), // 娣诲姞涓存椂ID
 });
 
-const focusInput = (nodeData, delay = 50) => {
+const focusInput = (nodeKey, delay = 100) => {
   setTimeout(() => {
-    const inputEl = inputRefs.value.get(nodeData.id || nodeData);
+    const inputEl = inputRefs.value.get(nodeKey);
     if (inputEl) {
-      inputEl.focus();
-      inputEl.select();
-      inputEl.$el?.scrollIntoView?.({
-        behavior: "smooth",
-        block: "nearest",
-      });
+      try {
+        // 鍏堟粴鍔ㄥ埌鍙鍖哄煙
+        inputEl.$el?.scrollIntoView?.({
+          behavior: "smooth",
+          block: "center",
+        });
+        
+        // 鑱氱劍骞堕�変腑鎵�鏈夋枃鏈紝纭繚鍙互鐩存帴缂栬緫
+        setTimeout(() => {
+          inputEl.focus();
+          inputEl.select();
+          
+          // 纭繚鍏夋爣鍦ㄨ緭鍏ユ鏈熬锛堝鏋渟elect澶辫触鐨勮瘽锛�
+          const inputElement = inputEl.ref || inputEl.input || inputEl.$el?.querySelector('input');
+          if (inputElement) {
+            inputElement.setSelectionRange(0, inputElement.value.length);
+            
+            // 纭繚杈撳叆妗嗗湪瑙嗗彛涓ぎ
+            setTimeout(() => {
+              inputElement.scrollIntoView({
+                behavior: 'smooth',
+                block: 'center'
+              });
+            }, 100);
+          }
+        }, 100);
+      } catch (error) {
+        console.warn('鑱氱劍杈撳叆妗嗗け璐�:', error);
+        // 澶囩敤鏂规锛氱洿鎺ヨ仛鐒�
+        try {
+          inputEl.focus();
+          // 灏濊瘯閫変腑鏂囨湰
+          setTimeout(() => {
+            const inputElement = inputEl.ref || inputEl.input || inputEl.$el?.querySelector('input');
+            if (inputElement) {
+              inputElement.select();
+            }
+          }, 200);
+        } catch (e) {
+          console.warn('澶囩敤鑱氱劍鏂规涔熷け璐�:', e);
+        }
+      }
+    } else {
+      console.warn('鏈壘鍒拌緭鍏ユ鍏冪礌锛宬ey:', nodeKey);
     }
   }, delay);
 };
 
 const append = async (data) => {
-  if (data === "") {
-    // 鏂板鏍硅妭鐐�
-    const newNode = createNewNode("鏂拌妭鐐�");
-    treeData.value.push(newNode);
-    newName.value = "鏂拌妭鐐�";
+  try {
+    // 妫�鏌ュ祵濂楀眰绾ч檺鍒�
+    const getNodeDepth = (nodeData, currentDepth = 1) => {
+      if (!nodeData || data === "") return 0; // 鏍硅妭鐐逛笉绠楀眰绾�
+      
+      let depth = currentDepth;
+      let current = nodeData;
+      
+      // 閫氳繃鏍戠粍浠惰幏鍙栫埗鑺傜偣鏉ヨ绠楁繁搴�
+      if (current.id) {
+        const node = treeRef.value?.getNode(current.id);
+        let parentNode = node?.parent;
+        
+        while (parentNode && parentNode.data && parentNode.data.id) {
+          depth++;
+          parentNode = parentNode.parent;
+        }
+      }
+      
+      return depth;
+    };
 
-    nextTick(() => focusInput(newNode));
-  } else {
-    const hasChildren = data.children;
-    const nodeKey = data.id || data;
-    const node = treeRef.value?.getNode(nodeKey);
-    const isExpanded = node?.expanded;
-
-    // 濡傛灉鏈夊瓙绾т笖鏈睍寮�锛屽厛灞曞紑鑺傜偣
-    if (hasChildren && !isExpanded && treeRef.value?.store?.nodesMap[nodeKey]) {
-      treeRef.value.store.nodesMap[nodeKey].expanded = true;
+    const currentDepth = getNodeDepth(data);
+    
+    // 闄愬埗鏈�澶�7灞傚祵濂�
+    if (currentDepth >= 7) {
+      ElMessage.warning('鏈�澶氬彧鑳藉祵濂�7灞傝妭鐐癸紝褰撳墠宸茶揪鍒版渶澶у眰绾ч檺鍒�');
+      return;
     }
 
-    const newNode = createNewNode("鏂板瓙鑺傜偣");
-
-    if (!data.children) {
-      data.children = [];
+    // 鍦ㄥぇ閲忚妭鐐规椂鎻愮ず鎬ц兘娉ㄦ剰浜嬮」
+    if (isLargeTree.value && totalNodeCount.value > 2000) {
+      const confirmed = await ElMessageBox.confirm(
+        `褰撳墠鏍戠粨鏋勫寘鍚� ${totalNodeCount.value} 涓妭鐐癸紝鑺傜偣杈冨鍙兘褰卞搷鎬ц兘銆傚缓璁�冭檻鍒嗗眰绠$悊銆傛槸鍚︾户缁坊鍔狅紵`,
+        '鎬ц兘鎻愮ず',
+        {
+          confirmButtonText: '缁х画娣诲姞',
+          cancelButtonText: '鍙栨秷',
+          type: 'warning',
+        }
+      ).catch(() => false);
+      
+      if (!confirmed) return;
     }
-    data.children.push(newNode);
-    newName.value = "鏂板瓙鑺傜偣";
 
-    const delay = hasChildren && !isExpanded ? 200 : 50;
-    nextTick(() => focusInput(newNode, delay));
+    if (data === "") {
+      // 鏂板鏍硅妭鐐�
+      const newNode = createNewNode("鏂拌妭鐐�");
+      treeData.value.push(newNode);
+      newName.value = "鏂拌妭鐐�";
+
+      await nextTick();
+      focusInput(newNode._tempId, 200);
+    } else {
+      const hasChildren = data.children && data.children.length > 0;
+      const nodeKey = data.id || data;
+      const node = treeRef.value?.getNode(nodeKey);
+
+      // 鍒涘缓鏂板瓙鑺傜偣
+      const newNode = createNewNode("鏂板瓙鑺傜偣");
+
+      if (!data.children) {
+        data.children = [];
+      }
+      data.children.push(newNode);
+      newName.value = "鏂板瓙鑺傜偣";
+
+      // 寮哄埗鏇存柊鏍戠粨鏋�
+      await nextTick();
+      
+      // 纭繚鐖惰妭鐐瑰睍寮�浠ユ樉绀烘柊鑺傜偣
+      if (node) {
+        node.expanded = true;
+        
+        // 濡傛灉鏄涓�娆℃坊鍔犲瓙鑺傜偣锛岀瓑寰呭睍寮�鍔ㄧ敾骞剁‘淇濆彲瑙�
+        if (!hasChildren) {
+          await new Promise(resolve => setTimeout(resolve, 300));
+          
+          // 灞曞紑鍚庢粴鍔ㄥ埌鏂拌妭鐐逛綅缃�
+          setTimeout(() => {
+            const newNodeElement = document.querySelector(`[data-temp-id="${newNode._tempId}"]`);
+            if (newNodeElement) {
+              newNodeElement.scrollIntoView({
+                behavior: 'smooth',
+                block: 'center'
+              });
+            }
+          }, 100);
+        }
+        
+        // 灞曞紑鎵�鏈夌埗鑺傜偣纭繚瀹屽叏鍙
+        let parentNode = node.parent;
+        while (parentNode && parentNode.data && parentNode.data.id) {
+          parentNode.expanded = true;
+          parentNode = parentNode.parent;
+        }
+      }
+      
+      // 鑱氱劍鍒版柊鍒涘缓鐨勮緭鍏ユ
+      const delay = hasChildren ? 150 : 500; // 濡傛灉涔嬪墠娌℃湁瀛愯妭鐐癸紝寤惰繜鏇撮暱鏃堕棿绛夊睍寮�
+      focusInput(newNode._tempId, delay);
+    }
+  } catch (error) {
+    console.error('鏂板鑺傜偣澶辫触:', error);
+    ElMessage.error('鏂板鑺傜偣澶辫触锛岃閲嶈瘯');
   }
 };
 
@@ -618,18 +881,27 @@
   border-radius: 8px;
   background: #fff;
   box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
+  max-height: calc(100vh - 240px); // 闄愬埗鏈�澶ч珮搴︼紝鍚敤婊氬姩
 
   .custom-tree {
     padding: 8px;
     background: transparent;
+    // 浣跨敤GPU鍔犻�熸彁鍗囨粴鍔ㄦ�ц兘
+    transform: translateZ(0);
+    will-change: scroll-position;
 
     :deep(.el-tree-node) {
+      // 鍑忓皯涓嶅繀瑕佺殑閲嶇粯
+      contain: layout style;
+      
       .el-tree-node__content {
         height: 36px;
         padding: 0 8px;
         border-radius: 6px;
         margin: 2px 0;
         transition: all 0.2s ease;
+        // 浼樺寲娓叉煋鎬ц兘
+        will-change: background-color;
 
         &:hover {
           background-color: #f0f9ff;
@@ -709,13 +981,19 @@
       color: #909399;
       min-height: auto;
 
-      &:hover {
+      &:hover:not(:disabled) {
         color: #1890ff;
         background-color: #f0f9ff;
       }
 
-      &.el-button--text:hover {
+      &.el-button--text:hover:not(:disabled) {
         background-color: #f0f9ff;
+      }
+      
+      &:disabled {
+        color: #c0c4cc;
+        cursor: not-allowed;
+        background-color: transparent;
       }
     }
   }
@@ -731,11 +1009,13 @@
 
   :deep(.el-input__wrapper) {
     border-radius: 4px;
-    border: 1px solid #d9d9d9;
+    border: 1px solid #40a9ff;
     transition: all 0.2s ease;
+    box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.1);
 
     &:hover {
-      border-color: #40a9ff;
+      border-color: #1890ff;
+      box-shadow: 0 0 0 2px rgba(24, 144, 255, 0.15);
     }
 
     &.is-focus {
@@ -748,10 +1028,15 @@
     padding: 4px 8px;
     font-size: 14px;
     color: #303133;
+    background-color: #fff;
 
     &::placeholder {
       color: #bfbfbf;
     }
+    
+    &:focus {
+      background-color: #f8fcff;
+    }
   }
 }
 

--
Gitblit v1.9.3