From e03b2546f020327bf9fd414d8869a9ccd2270c2d Mon Sep 17 00:00:00 2001
From: 曹睿 <360930172@qq.com>
Date: 星期二, 17 六月 2025 17:31:14 +0800
Subject: [PATCH] Merge branch 'dev' of http://114.132.189.42:9002/r/product-inventory-management into dev

---
 src/views/basicData/product/index.vue |  480 +++++++++++++++++++++++++++++++++++++++++++----------------
 1 files changed, 349 insertions(+), 131 deletions(-)

diff --git a/src/views/basicData/product/index.vue b/src/views/basicData/product/index.vue
index 0275185..506c1db 100644
--- a/src/views/basicData/product/index.vue
+++ b/src/views/basicData/product/index.vue
@@ -3,35 +3,61 @@
     <div class="left">
       <div>
         <el-input
-            v-model="search"
-            style="width: 240px"
-            placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�"
-            @change="searchFilter"
-            @clear="searchFilter"
-            clearable
-            prefix-icon="Search"
+          v-model="search"
+          style="width: 210px"
+          placeholder="杈撳叆鍏抽敭瀛楄繘琛屾悳绱�"
+          @change="searchFilter"
+          @clear="searchFilter"
+          clearable
+          prefix-icon="Search"
         />
-        <el-button type="primary" @click="openProDia('add')" style="margin-left: 10px">鏂板浜у搧</el-button>
+        <el-button
+          type="primary"
+          @click="openProDia('addOne')"
+          style="margin-left: 10px"
+          >鏂板浜у搧澶х被</el-button
+        >
       </div>
-      <div>
-        <el-tree ref="tree" v-loading="treeLoad" :data="list"
-                 :default-expanded-keys="expandedKeys" :draggable="true" :filter-node-method="filterNode"
-                 :props="{ children: 'children', label: 'label' }" highlight-current node-key="label"
-                 style="height: calc(100vh - 190px);overflow-y: scroll;scrollbar-width: none;">
+      <div ref="containerRef">
+        <el-tree
+          ref="tree"
+          v-loading="treeLoad"
+          :data="list"
+          @node-click="handleNodeClick"
+          :expand-on-click-node="false"
+          default-expand-all
+          :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;
+          "
+        >
           <template #default="{ node, data }">
             <div class="custom-tree-node">
               <span>{{ node.label }}</span>
               <div>
-                <el-button type="primary" link @click="openProDia('edit', data)">
+                <el-button
+                  type="primary"
+                  link
+                  @click="openProDia('edit', data)"
+                >
                   缂栬緫
                 </el-button>
-                <!-- 淇敼姝ゅ -->
+                <el-button type="primary" link @click="openProDia('add', data)">
+                  娣诲姞浜у搧
+                </el-button>
                 <el-button
-                    v-if="!node.childNodes.length"
-                    style="margin-left: 4px"
-                    type="danger"
-                    link
-                    @click="remove(node, data)"
+                  v-if="!node.childNodes.length"
+                  style="margin-left: 4px"
+                  type="danger"
+                  link
+                  @click="remove(node, data)"
                 >
                   鍒犻櫎
                 </el-button>
@@ -42,19 +68,47 @@
       </div>
     </div>
     <div class="right">
-      <div style="margin-bottom: 10px">
-        <el-button type="primary" @click="modelDia = true">鏂板瑙勬牸鍨嬪彿</el-button>
-        <el-button type="danger" @click="handleDelete" style="margin-left: 10px" plain>鍒犻櫎</el-button>
+      <div style="margin-bottom: 10px" v-if="isShowButton">
+        <el-button type="primary" @click="openModelDia('add')">
+          鏂板瑙勬牸鍨嬪彿
+        </el-button>
+        <ImportExcel @uploadSuccess="getModelList" />
+        <el-button
+          type="danger"
+          @click="handleDelete"
+          style="margin-left: 10px"
+          plain
+        >
+          鍒犻櫎
+        </el-button>
       </div>
-      <PIMTable :column="tableColumn" :tableData="tableData" :page="page" :isSelection="true" :handleSelectionChange="handleSelectionChange"
-                :tableLoading="tableLoading" @pagination="pagination" :total="total"></PIMTable>
+      <PIMTable
+        :column="tableColumn"
+        :tableData="tableData"
+        :page="page"
+        :isSelection="true"
+        :handleSelectionChange="handleSelectionChange"
+        :tableLoading="tableLoading"
+        @pagination="pagination"
+        :total="total"
+      ></PIMTable>
     </div>
-    <el-dialog :visible.sync="productDia" title="浜у搧" width="400px">
-      <el-form :model="form" label-width="140px" label-position="top" :rules="rules" ref="formRef">
+    <el-dialog v-model="productDia" title="浜у搧" width="400px">
+      <el-form
+        :model="form"
+        label-width="140px"
+        label-position="top"
+        :rules="rules"
+        ref="formRef"
+      >
         <el-row :gutter="30">
           <el-col :span="24">
             <el-form-item label="浜у搧鍚嶇О锛�" prop="productName">
-              <el-input v-model="form.productName" placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�" clearable/>
+              <el-input
+                v-model="form.productName"
+                placeholder="璇疯緭鍏ヤ骇鍝佸悕绉�"
+                clearable
+              />
             </el-form-item>
           </el-col>
         </el-row>
@@ -66,173 +120,337 @@
         </div>
       </template>
     </el-dialog>
+    <el-dialog
+      v-model="modelDia"
+      title="瑙勬牸鍨嬪彿"
+      width="400px"
+      @close="closeModelDia"
+    >
+      <el-form
+        :model="modelForm"
+        label-width="140px"
+        label-position="top"
+        :rules="modelRules"
+        ref="modelFormRef"
+      >
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="瑙勬牸鍨嬪彿锛�" prop="model">
+              <el-input
+                v-model="modelForm.model"
+                placeholder="璇疯緭鍏ヨ鏍煎瀷鍙�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+        <el-row>
+          <el-col :span="24">
+            <el-form-item label="鍗曚綅锛�" prop="unit">
+              <el-input
+                v-model="modelForm.unit"
+                placeholder="璇疯緭鍏ュ崟浣�"
+                clearable
+              />
+            </el-form-item>
+          </el-col>
+        </el-row>
+      </el-form>
+      <template #footer>
+        <div class="dialog-footer">
+          <el-button type="primary" @click="submitModelForm">纭</el-button>
+          <el-button @click="closeModelDia">鍙栨秷</el-button>
+        </div>
+      </template>
+    </el-dialog>
   </div>
 </template>
 
 <script setup>
-import {ref} from "vue";
-import {listCustomer} from "@/api/basicData/customerFile.js";
-import {ElMessageBox} from "element-plus";
-import {productTreeList} from "@/api/basicData/product.js";
-const { proxy } = getCurrentInstance()
+import { ref } from "vue";
+import { ElMessageBox } from "element-plus";
+import {
+  addOrEditProduct,
+  addOrEditProductModel,
+  delProduct,
+  delProductModel,
+  modelListPage,
+  productTreeList,
+} from "@/api/basicData/product.js";
+import ImportExcel from "./ImportExcel/index.vue";
 
-const search = ref('')
-const treeLoad = ref(false)
-const list = ref([])
-const expandedKeys = ref([])
+const { proxy } = getCurrentInstance();
+const tree = ref(null);
+const containerRef = ref(null);
+
+const productDia = ref(false);
+const modelDia = ref(false);
+const modelOperationType = ref("");
+const search = ref("");
+const currentId = ref("");
+const currentParentId = ref("");
+const operationType = ref("");
+const treeLoad = ref(false);
+const list = ref([]);
+const expandedKeys = ref([]);
 const tableColumn = ref([
   {
-    label: '瑙勬牸鍨嬪彿',
-    prop: 'model',
+    label: "瑙勬牸鍨嬪彿",
+    prop: "model",
   },
   {
-    label: '鍗曚綅',
-    prop: 'model',
+    label: "鍗曚綅",
+    prop: "unit",
   },
   {
     dataType: "action",
     label: "鎿嶄綔",
-    align: 'center',
+    align: "center",
     operation: [
       {
         name: "缂栬緫",
         type: "text",
         clickFun: (row) => {
-          openForm('edit', row);
+          openModelDia("edit", row);
         },
       },
     ],
   },
-])
-const tableData = ref([])
-const tableLoading = ref(false)
-const total = ref(0)
-const selectedRows = ref([])
+]);
+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,
-})
-const productDia = ref(false)
-const modelDia = ref(false)
+});
 const data = reactive({
   form: {
-    productName: '',
+    productName: "",
   },
   rules: {
     productName: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
-  }
-})
-const { form, rules } = toRefs(data)
+  },
+  modelForm: {
+    model: "",
+    unit: "",
+  },
+  modelRules: {
+    model: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+    unit: [{ required: true, message: "璇疯緭鍏�", trigger: "blur" }],
+  },
+});
+const { form, rules, modelForm, modelRules } = toRefs(data);
+// 鏌ヨ浜у搧鏍�
 const getProductTreeList = () => {
   treeLoad.value = true;
-  productTreeList().then(res => {
-    list.value = res
-    list.value.forEach((a) => {
-      expandedKeys.value.push(a.label);
+  productTreeList()
+    .then((res) => {
+      list.value = res;
+      list.value.forEach((a) => {
+        expandedKeys.value.push(a.label);
+      });
+      treeLoad.value = false;
+    })
+    .catch((err) => {
+      treeLoad.value = false;
     });
-    treeLoad.value = false;
-  }).catch(err => {
-    treeLoad.value = false;
-  })
-}
+};
+// 杩囨护浜у搧鏍�
 const searchFilter = () => {
   proxy.$refs.tree.filter(search.value);
-}
+};
+// 鎵撳紑浜у搧寮规
 const openProDia = (type, data) => {
-  productDia.value = true
-  console.log('openEditDia', data)
-}
+  operationType.value = type;
+  productDia.value = true;
+  form.value.productName = "";
+  if (type === "edit") {
+    form.value.productName = data.productName;
+  }
+};
+// 鎵撳紑瑙勬牸鍨嬪彿寮规
+const openModelDia = (type, data) => {
+  modelOperationType.value = type;
+  modelDia.value = true;
+  modelForm.value.model = "";
+  modelForm.value.model = "";
+  modelForm.value.id = "";
+  if (type === "edit") {
+    modelForm.value = { ...data };
+  }
+};
+// 鎻愪氦浜у搧鍚嶇О淇敼
 const submitForm = () => {
-}
+  proxy.$refs.formRef.validate((valid) => {
+    if (valid) {
+      if (operationType.value === "add") {
+        form.value.parentId = currentId.value;
+        form.value.id = "";
+      } else if (operationType.value === "addOne") {
+        form.value.id = "";
+        form.value.parentId = "";
+      } else {
+        form.value.id = currentId.value;
+        form.value.parentId = "";
+      }
+      addOrEditProduct(form.value).then((res) => {
+        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+        closeProDia();
+        getProductTreeList();
+      });
+    }
+  });
+};
+// 鍏抽棴浜у搧寮规
 const closeProDia = () => {
   proxy.$refs.formRef.resetFields();
   productDia.value = false;
-}
-const remove = (value) => {
+};
+// 鍒犻櫎浜у搧
+const remove = (node, data) => {
+  let ids = [];
+  ids.push(data.id);
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
+  })
+    .then(() => {
+      tableLoading.value = true;
+      delProduct(ids)
+        .then((res) => {
+          proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+          getProductTreeList();
+        })
+        .finally(() => {
+          tableLoading.value = false;
+        });
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
+// 閫夋嫨浜у搧
+const handleNodeClick = (val, node, el) => {
+  // 鍒ゆ柇鏄惁涓哄彾瀛愯妭鐐�
+  isShowButton.value = !(val.children && val.children.length > 0);
+  // 鍙湁鍙跺瓙鑺傜偣鎵嶆墽琛屼互涓嬮�昏緫
+  currentId.value = val.id;
+  currentParentId.value = val.parentId;
+  getModelList();
+};
 
-}
+// 鎻愪氦瑙勬牸鍨嬪彿淇敼
+const submitModelForm = () => {
+  proxy.$refs.modelFormRef.validate((valid) => {
+    if (valid) {
+      modelForm.value.productId = currentId.value;
+      addOrEditProductModel(modelForm.value).then((res) => {
+        proxy.$modal.msgSuccess("鎻愪氦鎴愬姛");
+        closeModelDia();
+        getModelList();
+      });
+    }
+  });
+};
+// 鍏抽棴鍨嬪彿寮规
+const closeModelDia = () => {
+  proxy.$refs.modelFormRef.resetFields();
+  modelDia.value = false;
+};
 // 琛ㄦ牸閫夋嫨鏁版嵁
 const handleSelectionChange = (selection) => {
-  selectedRows.value = selection
-}
-// 鍒犻櫎
-const handleDelete = () => {
-  let ids = []
-  if (selectedRows.value.length > 0) {
-    ids = selectedRows.value.map(item => item.id);
-  } else {
-    proxy.$modal.msgWarning('璇烽�夋嫨鏁版嵁')
-    return
-  }
-  ElMessageBox.confirm(
-      '閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�',
-      '鍒犻櫎鎻愮ず', {
-        confirmButtonText: '纭',
-        cancelButtonText: '鍙栨秷',
-        type: 'warning',
-      }
-  ).then(() => {
-    tableLoading.value = true
-    delCustomer(ids).then(res => {
-      proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛")
-      getList()
-    }).finally(() => {
-      tableLoading.value = false
-    })
-  }).catch(() => {
-    proxy.$modal.msg("宸插彇娑�")
-  })
-}
+  selectedRows.value = selection;
+};
+
 // 鏌ヨ瑙勬牸鍨嬪彿
-const pagination = ({ current, limit }) => {
-  page.current = current;
-  page.size = limit;
-  getList()
-}
-const getList = () => {
-  tableLoading.value = true
-  listCustomer({...searchForm.value, ...page}).then(res => {
-    tableLoading.value = false
-    tableData.value = res.rows
-    total.value = res.total
+const pagination = (obj) => {
+  page.current = obj.page;
+  page.size = obj.limit;
+  getModelList();
+};
+const getModelList = () => {
+  tableLoading.value = true;
+  modelListPage({
+    id: currentId.value,
+    current: page.current,
+    size: page.size,
+  }).then((res) => {
+    console.log("res", res);
+    tableData.value = res.records;
+    total.value = res.total;
+    tableLoading.value = false;
+  });
+};
+// 鍒犻櫎瑙勬牸鍨嬪彿
+const handleDelete = () => {
+  let ids = [];
+  if (selectedRows.value.length > 0) {
+    ids = selectedRows.value.map((item) => item.id);
+  } else {
+    proxy.$modal.msgWarning("璇烽�夋嫨鏁版嵁");
+    return;
+  }
+  ElMessageBox.confirm("閫変腑鐨勫唴瀹瑰皢琚垹闄わ紝鏄惁纭鍒犻櫎锛�", "鍒犻櫎鎻愮ず", {
+    confirmButtonText: "纭",
+    cancelButtonText: "鍙栨秷",
+    type: "warning",
   })
-}
+    .then(() => {
+      tableLoading.value = true;
+      delProductModel(ids)
+        .then((res) => {
+          proxy.$modal.msgSuccess("鍒犻櫎鎴愬姛");
+          getModelList();
+        })
+        .finally(() => {
+          tableLoading.value = false;
+        });
+    })
+    .catch(() => {
+      proxy.$modal.msg("宸插彇娑�");
+    });
+};
 // 璋冪敤tree杩囨护鏂规硶 涓枃鑻辫繃婊�
 const filterNode = (value, data, node) => {
-  if (!value) {銆�銆�銆�銆�//濡傛灉鏁版嵁涓虹┖锛屽垯杩斿洖true,鏄剧ず鎵�鏈夌殑鏁版嵁椤�
-    return true
+  if (!value) {
+    //濡傛灉鏁版嵁涓虹┖锛屽垯杩斿洖true,鏄剧ず鎵�鏈夌殑鏁版嵁椤�
+    return true;
   }
   // 鏌ヨ鍒楄〃鏄惁鏈夊尮閰嶆暟鎹紝灏嗗�煎皬鍐欙紝鍖归厤鑻辨枃鏁版嵁
-  let val = value.toLowerCase()
-  return chooseNode(val, data, node) // 璋冪敤杩囨护浜屽眰鏂规硶
-}
+  let val = value.toLowerCase();
+  return chooseNode(val, data, node); // 璋冪敤杩囨护浜屽眰鏂规硶
+};
 // 杩囨护鐖惰妭鐐� / 瀛愯妭鐐� (濡傛灉杈撳叆鐨勫弬鏁版槸鐖惰妭鐐逛笖鑳藉尮閰嶏紝鍒欒繑鍥炶鑺傜偣浠ュ強鍏朵笅鐨勬墍鏈夊瓙鑺傜偣锛涘鏋滃弬鏁版槸瀛愯妭鐐癸紝鍒欒繑鍥炶鑺傜偣鐨勭埗鑺傜偣銆俷ame鏄腑鏂囧瓧绗︼紝enName鏄嫳鏂囧瓧绗�.
 const chooseNode = (value, data, node) => {
   if (data.label.indexOf(value) !== -1) {
-    return true
+    return true;
   }
-  const level = node.level
+  const level = node.level;
   // 濡傛灉浼犲叆鐨勮妭鐐规湰韬氨鏄竴绾ц妭鐐瑰氨涓嶇敤鏍¢獙浜�
   if (level === 1) {
-    return false
+    return false;
   }
   // 鍏堝彇褰撳墠鑺傜偣鐨勭埗鑺傜偣
-  let parentData = node.parent
+  let parentData = node.parent;
   // 閬嶅巻褰撳墠鑺傜偣鐨勭埗鑺傜偣
-  let index = 0
+  let index = 0;
   while (index < level - 1) {
     // 濡傛灉鍖归厤鍒扮洿鎺ヨ繑鍥烇紝姝ゅname鍊兼槸涓枃瀛楃锛宔nName鏄嫳鏂囧瓧绗︺�傚垽鏂尮閰嶄腑鑻辨枃杩囨护
     if (parentData.data.label.indexOf(value) !== -1) {
-      return true
+      return true;
     }
     // 鍚﹀垯鐨勮瘽鍐嶅線涓婁竴灞傚仛鍖归厤
-    parentData = parentData.parent
-    index++
+    parentData = parentData.parent;
+    index++;
   }
   // 娌″尮閰嶅埌杩斿洖false
-  return false
-}
-getProductTreeList()
+  return false;
+};
+getProductTreeList();
 </script>
 
 <style scoped>
@@ -258,4 +476,4 @@
   font-size: 14px;
   padding-right: 8px;
 }
-</style>
\ No newline at end of file
+</style>

--
Gitblit v1.9.3