From 22dc76d2d43cb393780c6ffaac8f4f5b71df7c6e Mon Sep 17 00:00:00 2001
From: gaoluyang <2820782392@qq.com>
Date: 星期四, 09 四月 2026 16:00:50 +0800
Subject: [PATCH] 1.产品维护产品大类新增时产品名称字数不做限制

---
 src/views/basicData/product/index.vue |  181 +++++++++++++++++++++++++++++++++++++++-----
 1 files changed, 159 insertions(+), 22 deletions(-)

diff --git a/src/views/basicData/product/index.vue b/src/views/basicData/product/index.vue
index d71d7cb..b3e9672 100644
--- a/src/views/basicData/product/index.vue
+++ b/src/views/basicData/product/index.vue
@@ -25,18 +25,16 @@
           :data="list"
           @node-click="handleNodeClick"
           :expand-on-click-node="false"
-          default-expand-all
+          @node-expand="handleNodeExpand"
+          @node-collapse="handleNodeCollapse"
+          :key="treeKey"
           :default-expanded-keys="expandedKeys"
-          :draggable="true"
           :filter-node-method="filterNode"
           :props="{ children: 'children', label: 'label' }"
           highlight-current
           node-key="id"
-          style="
-            height: calc(100vh - 190px);
-            overflow-y: scroll;
-            scrollbar-width: none;
-          "
+          class="product-tree-scroll"
+          style="height: calc(100vh - 190px); overflow-y: auto"
         >
           <template #default="{ node, data }">
             <div class="custom-tree-node">
@@ -45,7 +43,7 @@
                   <component :is="data.children && data.children.length > 0
                   ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" />
                 </el-icon>
-                {{ data.label }}
+                <span class="tree-node-label">{{ data.label }}</span>
               </span>
               <div>
                 <el-button
@@ -78,7 +76,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"
@@ -97,10 +95,9 @@
         @selection-change="handleSelectionChange"
         :tableLoading="tableLoading"
         @pagination="pagination"
-        :total="total"
       ></PIMTable>
     </div>
-    <el-dialog v-model="productDia" title="浜у搧" width="400px">
+    <el-dialog v-model="productDia" title="浜у搧" width="400px" @keydown.enter.prevent>
       <el-form
         :model="form"
         label-width="140px"
@@ -115,6 +112,7 @@
                 v-model="form.productName"
                 placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
                 clearable
+                @keydown.enter.prevent
               />
             </el-form-item>
           </el-col>
@@ -132,6 +130,7 @@
       title="瑙勬牸鍨嬪彿"
       width="400px"
       @close="closeModelDia"
+      @keydown.enter.prevent
     >
       <el-form
         :model="modelForm"
@@ -147,6 +146,7 @@
                 v-model="modelForm.model"
                 placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
                 clearable
+                @keydown.enter.prevent
               />
             </el-form-item>
           </el-col>
@@ -158,6 +158,7 @@
                 v-model="modelForm.unit"
                 placeholder="璇疯緭鍏ュ崟浣�"
                 clearable
+                @keydown.enter.prevent
               />
             </el-form-item>
           </el-col>
@@ -174,7 +175,7 @@
 </template>
 
 <script setup>
-import { ref } from "vue";
+import { nextTick, ref } from "vue";
 import { ElMessageBox } from "element-plus";
 import {
   addOrEditProduct,
@@ -189,6 +190,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);
@@ -227,18 +314,21 @@
 const tableData = ref([]);
 const tableLoading = ref(false);
 const isShowButton = ref(false);
-const total = ref(0);
 const selectedRows = ref([]);
 const page = reactive({
   current: 1,
   size: 10,
+  total: 0,
 });
 const data = reactive({
   form: {
     productName: "",
   },
   rules: {
-    productName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    productName: [
+      { required: true, message: "璇疯緭鍏�", trigger: "blur" },
+      { max: 20, message: "浜у搧鍚嶇О涓嶈兘瓒呰繃20涓瓧绗�", trigger: "blur" },
+    ],
   },
   modelForm: {
     model: "",
@@ -255,15 +345,29 @@
   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 = () => {
@@ -316,6 +420,7 @@
   proxy.$refs.formRef.resetFields();
   productDia.value = false;
 };
+
 // 鍒犻櫎浜у搧
 const remove = (node, data) => {
   let ids = [];
@@ -388,7 +493,7 @@
   }).then((res) => {
     console.log("res", res);
     tableData.value = res.records;
-    total.value = res.total;
+    page.total = res.total;
     tableLoading.value = false;
   });
 };
@@ -465,18 +570,21 @@
   display: flex;
 }
 .left {
-  width: 380px;
+  width: 450px;
+  min-width: 450px;
   padding: 16px;
   background: #ffffff;
 }
 .right {
-  width: calc(100% - 380px);
+  flex: 1;
+  min-width: 0;
   padding: 16px;
   margin-left: 20px;
   background: #ffffff;
 }
 .custom-tree-node {
   flex: 1;
+  min-width: 0;
   display: flex;
   align-items: center;
   justify-content: space-between;
@@ -484,13 +592,42 @@
   padding-right: 8px;
 }
 .tree-node-content {
+  flex: 1;
+  min-width: 0;
   display: flex;
-  align-items: center; /* 鍨傜洿灞呬腑 */
+  align-items: center;
   height: 100%;
+  overflow: hidden;
+}
+.tree-node-content .orange-icon {
+  flex-shrink: 0;
+}
+.tree-node-label {
+  overflow: hidden;
+  text-overflow: ellipsis;
+  white-space: nowrap;
 }
 .orange-icon {
   color: orange;
   font-size: 18px;
   margin-right: 8px; /* 鍥炬爣涓庢枃瀛椾箣闂村姞鐐归棿璺� */
 }
+.product-tree-scroll {
+  scrollbar-width: thin;
+  scrollbar-color: #c0c4cc #f5f7fa;
+}
+.product-tree-scroll::-webkit-scrollbar {
+  width: 8px;
+}
+.product-tree-scroll::-webkit-scrollbar-track {
+  background: #f5f7fa;
+  border-radius: 4px;
+}
+.product-tree-scroll::-webkit-scrollbar-thumb {
+  background: #c0c4cc;
+  border-radius: 4px;
+}
+.product-tree-scroll::-webkit-scrollbar-thumb:hover {
+  background: #909399;
+}
 </style>

--
Gitblit v1.9.3