| | |
| | | :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; |
| | | " |
| | | class="product-tree-scroll" |
| | | style="height: calc(100vh - 190px); overflow-y: auto" |
| | | > |
| | | <template #default="{ node, data }"> |
| | | <div class="custom-tree-node"> |
| | |
| | | <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 |
| | | v-if="node.level > 1" |
| | | type="success" |
| | | link |
| | | @click.stop="handleDownCopy(node, data)" |
| | | > |
| | | 向下复制 |
| | | </el-button> |
| | | <el-button |
| | | type="primary" |
| | | link |
| | |
| | | > |
| | | 编辑 |
| | | </el-button> |
| | | <el-button type="primary" link @click="openProDia('add', data)"> |
| | | <el-button type="primary" link @click="openProDia('add', data)" :disabled="node.level >= 3"> |
| | | 添加产品 |
| | | </el-button> |
| | | <el-button |
| | |
| | | <el-button type="primary" @click="openModelDia('add')"> |
| | | 新增规格型号 |
| | | </el-button> |
| | | <ImportExcel @uploadSuccess="getModelList" /> |
| | | <ImportExcel :product-id="currentId" @uploadSuccess="getModelList" /> |
| | | <el-button |
| | | type="danger" |
| | | @click="handleDelete" |
| | |
| | | @pagination="pagination" |
| | | ></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" |
| | |
| | | <el-input |
| | | v-model="form.productName" |
| | | placeholder="请输入产品名称" |
| | | maxlength="20" |
| | | show-word-limit |
| | | clearable |
| | | @keydown.enter.prevent |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | title="规格型号" |
| | | width="400px" |
| | | @close="closeModelDia" |
| | | @keydown.enter.prevent |
| | | > |
| | | <el-form |
| | | :model="modelForm" |
| | |
| | | > |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="料号:" prop="materialCode"> |
| | | <el-input |
| | | v-model="modelForm.materialCode" |
| | | placeholder="请输入料号" |
| | | clearable |
| | | @keydown.enter.prevent |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | | </el-row> |
| | | <el-row> |
| | | <el-col :span="24"> |
| | | <el-form-item label="规格型号:" prop="model"> |
| | | <el-input |
| | | v-model="modelForm.model" |
| | | placeholder="请输入规格型号" |
| | | clearable |
| | | @keydown.enter.prevent |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | v-model="modelForm.unit" |
| | | placeholder="请输入单位" |
| | | clearable |
| | | @keydown.enter.prevent |
| | | /> |
| | | </el-form-item> |
| | | </el-col> |
| | |
| | | delProductModel, |
| | | modelListPage, |
| | | productTreeList, |
| | | downCopyProductModel, |
| | | } from "@/api/basicData/product.js"; |
| | | import ImportExcel from "./ImportExcel/index.vue"; |
| | | |
| | |
| | | const list = ref([]); |
| | | const expandedKeys = ref([]); |
| | | const tableColumn = ref([ |
| | | { |
| | | label: "料号", |
| | | prop: "materialCode", |
| | | }, |
| | | { |
| | | label: "规格型号", |
| | | prop: "model", |
| | |
| | | productName: "", |
| | | }, |
| | | rules: { |
| | | productName: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | productName: [ |
| | | { required: true, message: "请输入", trigger: "blur" }, |
| | | { max: 20, message: "产品名称不能超过20个字符", trigger: "blur" }, |
| | | ], |
| | | }, |
| | | modelForm: { |
| | | materialCode: "", |
| | | model: "", |
| | | unit: "", |
| | | }, |
| | | modelRules: { |
| | | materialCode: [{ required: true, message: "请输入", trigger: "blur" }, { max: 200, message: "物料编号不能超过200个字符", trigger: "blur" }], |
| | | model: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | unit: [{ required: true, message: "请输入", trigger: "blur" }], |
| | | }, |
| | |
| | | proxy.$refs.formRef.resetFields(); |
| | | productDia.value = false; |
| | | }; |
| | | |
| | | // 删除产品 |
| | | const remove = (node, data) => { |
| | | let ids = []; |
| | |
| | | proxy.$modal.msg("已取消"); |
| | | }); |
| | | }; |
| | | |
| | | // 向下复制 |
| | | const handleDownCopy = (node, data) => { |
| | | if (currentId.value !== data.id) { |
| | | proxy.$modal.msgWarning("请先选中当前产品并勾选需要复制的型号"); |
| | | return; |
| | | } |
| | | |
| | | // 获取同层级节点 |
| | | const parent = node.parent; |
| | | const siblings = parent.childNodes || []; |
| | | // 找到当前节点在同层级中的索引 |
| | | const currentIndex = siblings.findIndex(item => item.data.id === data.id); |
| | | // 获取下一行节点 |
| | | const nextNode = siblings[currentIndex + 1]; |
| | | |
| | | if (!nextNode) { |
| | | proxy.$modal.msgWarning("当前节点是同层级最后一个,没有下一行数据可复制"); |
| | | return; |
| | | } |
| | | |
| | | const modelListId = selectedRows.value.map((item) => item.id); |
| | | if (!modelListId.length) { |
| | | proxy.$modal.msgWarning("没有选择要复制的型号"); |
| | | return; |
| | | } |
| | | |
| | | ElMessageBox.confirm("确认将当前节点的规格型号复制到下一行节点?", "向下复制", { |
| | | confirmButtonText: "确认", |
| | | cancelButtonText: "取消", |
| | | type: "info", |
| | | }) |
| | | .then(() => { |
| | | downCopyProductModel({ |
| | | productId: data.id, |
| | | targetProductId: nextNode.data.id, |
| | | modelListId, |
| | | }).then(() => { |
| | | proxy.$modal.msgSuccess("复制成功"); |
| | | }); |
| | | }) |
| | | .catch(() => {}); |
| | | }; |
| | | // 选择产品 |
| | | const handleNodeClick = (val, node, el) => { |
| | | // 判断是否为叶子节点 |
| | |
| | | // 只有叶子节点才执行以下逻辑 |
| | | currentId.value = val.id; |
| | | currentParentId.value = val.parentId; |
| | | selectedRows.value = []; |
| | | getModelList(); |
| | | }; |
| | | |
| | |
| | | }; |
| | | const getModelList = () => { |
| | | tableLoading.value = true; |
| | | selectedRows.value = []; |
| | | modelListPage({ |
| | | id: currentId.value, |
| | | current: page.current, |
| | |
| | | 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; |
| | |
| | | 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> |