From 0c4bdf3dca76f9b8c348f2f7e48f9a6319dee4e1 Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期五, 17 四月 2026 17:09:22 +0800
Subject: [PATCH] 进销存升级 1.销售台账不能删除和编辑别人维护的数据 2.产品维护固定产品大类为:成品、半成品、原材料。

---
 src/views/basicData/product/index.vue |  134 ++++++++++++++++++++++++++++++++++++++++++--
 1 files changed, 127 insertions(+), 7 deletions(-)

diff --git a/src/views/basicData/product/index.vue b/src/views/basicData/product/index.vue
index c9058aa..10b51bf 100644
--- a/src/views/basicData/product/index.vue
+++ b/src/views/basicData/product/index.vue
@@ -12,6 +12,7 @@
           prefix-icon="Search"
         />
         <el-button
+          v-if="false"
           type="primary"
           @click="openProDia('addOne')"
           style="margin-left: 10px"
@@ -25,6 +26,9 @@
           :data="list"
           @node-click="handleNodeClick"
           :expand-on-click-node="false"
+          @node-expand="handleNodeExpand"
+          @node-collapse="handleNodeCollapse"
+          :key="treeKey"
           :default-expanded-keys="expandedKeys"
           :filter-node-method="filterNode"
           :props="{ children: 'children', label: 'label' }"
@@ -46,11 +50,12 @@
                 <el-button
                   type="primary"
                   link
+                  :disabled="isTopLevelNode(data, node)"
                   @click="openProDia('edit', data)"
                 >
                   缂栬緫
                 </el-button>
-                <el-button type="primary" link @click="openProDia('add', data)" :disabled="node.level >= 3">
+                <el-button type="primary" link @click="openProDia('add', data)">
                   娣诲姞浜у搧
                 </el-button>
                 <el-button
@@ -58,6 +63,7 @@
                   style="margin-left: 4px"
                   type="danger"
                   link
+                  :disabled="isTopLevelNode(data, node)"
                   @click="remove(node, data)"
                 >
                   鍒犻櫎
@@ -73,7 +79,7 @@
         <el-button type="primary" @click="openModelDia('add')">
           鏂板瑙勬牸鍨嬪彿
         </el-button>
-        <ImportExcel @uploadSuccess="getModelList" />
+        <ImportExcel :product-id="currentId" @uploadSuccess="getModelList" />
         <el-button
           type="danger"
           @click="handleDelete"
@@ -174,7 +180,7 @@
 </template>
 
 <script setup>
-import { ref } from "vue";
+import { nextTick, ref } from "vue";
 import { ElMessageBox } from "element-plus";
 import {
   addOrEditProduct,
@@ -189,6 +195,92 @@
 const { proxy } = getCurrentInstance();
 const tree = ref(null);
 const containerRef = ref(null);
+const treeKey = ref(0);
+const expandedKeySet = new Set();
+const EXPANDED_STORAGE_KEY = "basicData_product_tree_expanded_keys_v2";
+
+const loadExpandedKeys = () => {
+  if (typeof window === "undefined") {
+    return [];
+  }
+  try {
+    const saved = localStorage.getItem(EXPANDED_STORAGE_KEY);
+    return saved ? JSON.parse(saved) : [];
+  } catch (error) {
+    console.error(error);
+    return [];
+  }
+};
+
+const saveExpandedKeys = () => {
+  if (typeof window === "undefined") {
+    return;
+  }
+  localStorage.setItem(
+    EXPANDED_STORAGE_KEY,
+    JSON.stringify(Array.from(expandedKeySet))
+  );
+};
+
+loadExpandedKeys().forEach((key) => expandedKeySet.add(key));
+
+const syncExpandedKeysFromTree = () => {
+  const keys = [];
+  const walk = (nodes) => {
+    (nodes || []).forEach((item) => {
+      if (item.expanded && item.data?.id !== undefined) {
+        keys.push(item.data.id);
+      }
+      if (item.childNodes && item.childNodes.length) {
+        walk(item.childNodes);
+      }
+    });
+  };
+
+  walk(tree.value?.root?.childNodes);
+  expandedKeySet.clear();
+  keys.forEach((key) => expandedKeySet.add(key));
+  expandedKeys.value = keys;
+  saveExpandedKeys();
+};
+
+const normalizeExpandedKeys = (treeData) => {
+  const parentMap = new Map();
+  const walk = (nodes, parentId = null) => {
+    (nodes || []).forEach((item) => {
+      parentMap.set(item.id, parentId);
+      if (item.children && item.children.length) {
+        walk(item.children, item.id);
+      }
+    });
+  };
+
+  walk(treeData);
+
+  const normalizedKeys = Array.from(expandedKeySet).filter((key) => {
+    if (!parentMap.has(key)) {
+      return false;
+    }
+    let currentId = key;
+    while (parentMap.has(currentId)) {
+      const parentId = parentMap.get(currentId);
+      if (!parentId) {
+        return true;
+      }
+      if (!expandedKeySet.has(parentId)) {
+        return false;
+      }
+      currentId = parentId;
+    }
+    return true;
+  });
+
+  if (normalizedKeys.length !== expandedKeySet.size) {
+    expandedKeySet.clear();
+    normalizedKeys.forEach((key) => expandedKeySet.add(key));
+    saveExpandedKeys();
+  }
+};
 
 const productDia = ref(false);
 const modelDia = ref(false);
@@ -258,22 +350,46 @@
   treeLoad.value = true;
   productTreeList()
     .then((res) => {
-      list.value = res;
-      list.value.forEach((a) => {
-        expandedKeys.value.push(a.label);
+      list.value = res || [];
+      normalizeExpandedKeys(list.value);
+      expandedKeys.value = Array.from(expandedKeySet);
+      treeKey.value += 1;
+      nextTick(() => {
+        tree.value?.setDefaultExpandedKeys?.(expandedKeys.value);
       });
-      treeLoad.value = false;
     })
     .catch((err) => {
+      console.error(err);
+    })
+    .finally(() => {
       treeLoad.value = false;
     });
+};
+const handleNodeExpand = (data) => {
+  nextTick(syncExpandedKeysFromTree);
+};
+const handleNodeCollapse = (data, node) => {
+  node?.eachNode?.((item) => {
+    item.collapse();
+  });
+  nextTick(syncExpandedKeysFromTree);
 };
 // 杩囨护浜у搧鏍�
 const searchFilter = () => {
   proxy.$refs.tree.filter(search.value);
 };
+const isTopLevelNode = (data, node) => {
+  if (node?.level !== undefined) {
+    return node.level === 1;
+  }
+  return [null, undefined, "", 0, "0"].includes(data?.parentId);
+};
 // 鎵撳紑浜у搧寮规
 const openProDia = (type, data) => {
+  if (data && type === "edit" && isTopLevelNode(data)) {
+    proxy.$modal.msgWarning("涓�绾ц妭鐐逛笉鑳界紪杈戞垨鍒犻櫎");
+    return;
+  }
   operationType.value = type;
   productDia.value = true;
   form.value.productName = "";
@@ -322,6 +438,10 @@
 
 // 鍒犻櫎浜у搧
 const remove = (node, data) => {
+  if (isTopLevelNode(data, node)) {
+    proxy.$modal.msgWarning("涓�绾ц妭鐐逛笉鑳界紪杈戞垨鍒犻櫎");
+    return;
+  }
   let ids = [];
   ids.push(data.id);
   ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {

--
Gitblit v1.9.3