zhangwencui
2 天以前 ba9e41aeb286f381d862e83fbe72a0c696608b22
src/views/basicData/product/index.vue
@@ -24,28 +24,21 @@
                 :props="{ children: 'children', label: 'label' }"
                 highlight-current
                 node-key="id"
                 class="product-tree-scroll"
                 style="height: calc(100vh - 190px); overflow-y: auto">
                 class="product-tree-scroll">
          <template #default="{ node, data }">
            <div class="custom-tree-node">
              <span class="tree-node-content">
                <el-icon class="orange-icon">
                <el-icon class="tree-icon">
                  <component :is="data.children && data.children.length > 0
                  ? node.expanded ? 'FolderOpened' : 'Folder' : 'Tickets'" />
                </el-icon>
                <span class="tree-node-label">{{ data.label }}</span>
              </span>
              <div v-if="!node.childNodes.length">
              <div v-if="data.isLeaf">
                <el-button type="primary"
                           link
                           @click="openProDia('edit', data)">
                  编辑
                </el-button>
                <el-button v-if="data.children && data.children.length > 0"
                           type="primary"
                           link
                           @click="openProDia('add', data)">
                  添加产品
                </el-button>
                <el-button v-if="!node.childNodes.length"
                           style="margin-left: 4px"
@@ -62,14 +55,14 @@
                           @click="openProDia1('edit', data)">
                  编辑
                </el-button>
                <el-button v-if="data.children && data.children.length > 0"
                           type="primary"
                <el-button type="primary"
                           link
                           @click="openProDia('add', data)">
                  添加产品
                </el-button>
                <el-button style="margin-left: 4px"
                           type="danger"
                           v-if="!node.childNodes.length"
                           link
                           @click="remove1(node, data)">
                  删除
@@ -99,11 +92,10 @@
      <PIMTable rowKey="id"
                :column="tableColumn"
                :tableData="tableData"
                :page="page"
                :isSelection="true"
                :isShowPagination="false"
                @selection-change="handleSelectionChange"
                :tableLoading="tableLoading"
                @pagination="pagination"></PIMTable>
                :tableLoading="tableLoading"></PIMTable>
    </div>
    <el-dialog v-model="productDia"
               title="产品"
@@ -204,8 +196,8 @@
        <el-row>
          <el-col :span="24">
            <el-form-item label="规格型号:"
                          prop="model">
              <el-input v-model="modelForm.model"
                          prop="specification">
              <el-input v-model="modelForm.specification"
                        placeholder="请输入规格型号"
                        clearable
                        @keydown.enter.prevent />
@@ -214,78 +206,17 @@
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="单位:"
                          prop="unit">
              <el-input v-model="modelForm.unit"
                        placeholder="请输入单位"
                        clearable
                        @keydown.enter.prevent />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="标识符代码:"
                          prop="identifierCode">
              <el-input v-model="modelForm.identifierCode"
                        placeholder="请输入标识符代码"
                        clearable
                        @keydown.enter.prevent />
            </el-form-item>
          </el-col>
        </el-row>
        <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="specification">
              <el-input v-model="modelForm.specification"
                        placeholder="请输入规格"
                        clearable
                        @keydown.enter.prevent />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="供应类型:"
            <el-form-item label="供应方式:"
                          prop="supplyType">
              <el-input v-model="modelForm.supplyType"
                        placeholder="请输入供应类型"
                        clearable
                        @keydown.enter.prevent />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="创始人姓名:"
                          prop="originatorName">
              <el-input v-model="modelForm.originatorName"
                        placeholder="请输入创始人姓名"
                        clearable
                        @keydown.enter.prevent />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="创始人组织:"
                          prop="originatorOrg">
              <el-input v-model="modelForm.originatorOrg"
                        placeholder="请输入创始人组织"
                        clearable
                        @keydown.enter.prevent />
              <el-select v-model="modelForm.supplyType"
                         placeholder="请选择供应方式"
                         clearable
                         style="width: 100%">
                <el-option label="自制"
                           value="自制" />
                <el-option label="外购"
                           value="外购" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
@@ -295,6 +226,37 @@
          <el-button type="primary"
                     @click="submitModelForm">确认</el-button>
          <el-button @click="closeModelDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog v-model="configDia"
               title="产品大类"
               width="400px"
               @keydown.enter.prevent>
      <el-form :model="configForm"
               label-width="140px"
               label-position="top"
               :rules="configRules"
               ref="configFormRef">
        <el-row :gutter="30">
          <el-col :span="24">
            <el-form-item label="配置名称:"
                          prop="configName">
              <el-input v-model="configForm.configName"
                        placeholder="请输入配置名称"
                        maxlength="20"
                        show-word-limit
                        clearable
                        @keydown.enter.prevent />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary"
                     @click="submitConfigForm">确认</el-button>
          <el-button @click="closeConfigDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
@@ -327,7 +289,9 @@
  const productDia = ref(false);
  const modelDia = ref(false);
  const configDia = ref(false);
  const modelOperationType = ref("");
  const configOperationType = ref("");
  const search = ref("");
  const currentId = ref("");
  const currentParentId = ref("");
@@ -397,11 +361,7 @@
  const tableLoading = ref(false);
  const isShowButton = ref(false);
  const selectedRows = ref([]);
  const page = reactive({
    current: 1,
    size: 10,
    total: 0,
  });
  const data = reactive({
    form: {
      materialTypeId: null,
@@ -421,27 +381,28 @@
      baseUnit: [{ required: true, message: "请输入", trigger: "blur" }],
    },
    modelForm: {
      model: "",
      unit: "",
      identifierCode: "",
      materialCode: "",
      specification: "",
      supplyType: "",
      originatorName: "",
      originatorOrg: "",
      id: null,
    },
    modelRules: {
      model: [{ required: true, message: "请输入", trigger: "blur" }],
      unit: [{ required: true, message: "请输入", trigger: "blur" }],
      identifierCode: [{ required: true, message: "请输入", trigger: "blur" }],
      materialCode: [{ required: true, message: "请输入", trigger: "blur" }],
      specification: [{ required: true, message: "请输入", trigger: "blur" }],
      supplyType: [{ required: true, message: "请输入", trigger: "blur" }],
      originatorName: [{ required: true, message: "请输入", trigger: "blur" }],
      originatorOrg: [{ required: true, message: "请输入", trigger: "blur" }],
      supplyType: [{ required: true, message: "请选择", trigger: "change" }],
    },
    configForm: {
      configName: "",
      type: 1,
      id: null,
    },
    configRules: {
      configName: [
        { required: true, message: "请输入", trigger: "blur" },
        { max: 20, message: "配置名称不能超过20个字符", trigger: "blur" },
      ],
    },
  });
  const { form, rules, modelForm, modelRules } = toRefs(data);
  const { form, rules, modelForm, modelRules, configForm, configRules } =
    toRefs(data);
  // 查询产品树
  const getProductTreeList = () => {
    treeLoad.value = true;
@@ -455,8 +416,10 @@
          const categoryNode = {
            label: category.configName,
            id: category.configId,
            isLeaf: false,
            children: category.materialList.map(item => ({
              id: item.id,
              isLeaf: true,
              label: item.materialName,
              inventoryCategoryId: item.inventoryCategoryId,
              materialTypeId: item.materialTypeId,
@@ -503,24 +466,36 @@
      form.value.materialTypeId = data.id || null;
    }
  };
  // 打开产品大类弹框
  const openProDia1 = (type, data) => {
    configOperationType.value = type;
    configDia.value = true;
    // 重置表单
    configForm.value = {
      configName: "",
      type: 1,
      id: null,
    };
    if (type === "edit" && data) {
      // 编辑模式,回填数据
      configForm.value.configName = data.label || "";
      configForm.value.id = data.id || null;
    }
  };
  // 打开规格型号弹框
  const openModelDia = (type, data) => {
    modelOperationType.value = type;
    modelDia.value = true;
    // 重置所有字段
    modelForm.value.model = "";
    modelForm.value.unit = "";
    modelForm.value.identifierCode = "";
    modelForm.value.materialCode = "";
    modelForm.value.specification = "";
    modelForm.value.supplyType = "";
    modelForm.value.originatorName = "";
    modelForm.value.originatorOrg = "";
    modelForm.value.id = "";
    modelForm.value.id = null;
    if (type === "edit" && data) {
      // 编辑模式,回填数据
      modelForm.value = { ...data };
      modelForm.value.specification = data.specification || "";
      modelForm.value.supplyType = data.supplyType || "";
      modelForm.value.id = data.skuId || null;
    }
  };
  // 提交产品名称修改
@@ -572,7 +547,60 @@
    form.value.remark = "";
    productDia.value = false;
  };
  // 提交产品大类修改
  const submitConfigForm = () => {
    proxy.$refs.configFormRef.validate(valid => {
      if (valid) {
        const params = {
          configName: configForm.value.configName,
          type: 1,
        };
        if (configOperationType.value === "edit") {
          params.id = configForm.value.id;
          updateOrEditProductConfig(params).then(res => {
            proxy.$modal.msgSuccess("提交成功");
            closeConfigDia();
            getProductTreeList();
          });
        } else {
          addOrEditProductConfig(params).then(res => {
            proxy.$modal.msgSuccess("提交成功");
            closeConfigDia();
            getProductTreeList();
          });
        }
      }
    });
  };
  // 关闭产品大类弹框
  const closeConfigDia = () => {
    proxy.$refs.configFormRef.resetFields();
    configDia.value = false;
  };
  // 删除产品大类
  const remove1 = (node, data) => {
    let ids = [];
    ids.push(data.id);
    ElMessageBox.confirm("选中的内容将被删除,是否确认删除?", "删除提示", {
      confirmButtonText: "确认",
      cancelButtonText: "取消",
      type: "warning",
    })
      .then(() => {
        tableLoading.value = true;
        delProductConfig(ids)
          .then(res => {
            proxy.$modal.msgSuccess("删除成功");
            getProductTreeList();
          })
          .finally(() => {
            tableLoading.value = false;
          });
      })
      .catch(() => {
        proxy.$modal.msg("已取消");
      });
  };
  // 删除产品
  const remove = (node, data) => {
    let ids = [];
@@ -599,6 +627,10 @@
  };
  // 选择产品
  const handleNodeClick = (val, node, el) => {
    // 点击非叶子节点时,不执行以下逻辑
    if (!val.isLeaf) {
      return;
    }
    // 判断是否为叶子节点
    isShowButton.value = !(val.children && val.children.length > 0);
    // 只有叶子节点才执行以下逻辑
@@ -614,12 +646,8 @@
        // 构建提交参数
        const params = {
          materialId: currentId.value,
          identifierCode: modelForm.value.identifierCode,
          materialCode: modelForm.value.materialCode,
          specification: modelForm.value.specification,
          supplyType: modelForm.value.supplyType,
          originatorName: modelForm.value.originatorName,
          originatorOrg: modelForm.value.originatorOrg,
        };
        if (modelOperationType.value === "add") {
          // 添加规格型号
@@ -630,6 +658,7 @@
          });
        } else if (modelOperationType.value === "edit") {
          // 修改规格型号
          params.id = modelForm.value.id;
          updateOrEditProductModel(params).then(res => {
            proxy.$modal.msgSuccess("提交成功");
            closeModelDia();
@@ -650,11 +679,6 @@
  };
  // 查询规格型号
  const pagination = obj => {
    page.current = obj.page;
    page.size = obj.limit;
    getModelList();
  };
  const getModelList = () => {
    if (!currentId.value) {
      return;
@@ -662,12 +686,9 @@
    tableLoading.value = true;
    modelListPage({
      materialId: currentId.value,
      current: page.current,
      size: page.size,
    }).then(res => {
      console.log("res", res);
      tableData.value = res.data;
      page.total = res.total;
      tableLoading.value = false;
    });
  };
@@ -675,7 +696,7 @@
  const handleDelete = () => {
    let ids = [];
    if (selectedRows.value.length > 0) {
      ids = selectedRows.value.map(item => item.id);
      ids = selectedRows.value.map(item => item.skuId);
    } else {
      proxy.$modal.msgWarning("请选择数据");
      return;
@@ -745,19 +766,49 @@
<style scoped>
  .product-view {
    display: flex;
    min-height: 100vh;
    background-color: #f5f7fa;
    padding: 20px;
    gap: 20px;
  }
  .left {
    width: 450px;
    min-width: 450px;
    padding: 16px;
    background: #ffffff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  .left > div:first-child {
    padding: 16px;
    border-bottom: 1px solid #e4e7ed;
    background-color: #fafafa;
  }
  .left > div:last-child {
    flex: 1;
    overflow: hidden;
  }
  .right {
    flex: 1;
    min-width: 0;
    padding: 16px;
    margin-left: 20px;
    background: #ffffff;
    border-radius: 8px;
    box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
    overflow: hidden;
    display: flex;
    flex-direction: column;
  }
  .right > div:first-child {
    padding: 16px;
    border-bottom: 1px solid #e4e7ed;
    background-color: #fafafa;
  }
  .right > div:last-child {
    flex: 1;
    overflow: auto;
    padding: 16px;
  }
  .custom-tree-node {
    flex: 1;
@@ -766,7 +817,13 @@
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
    padding: 8px 12px;
    margin: 2px 0;
    border-radius: 4px;
    transition: all 0.3s ease;
  }
  .custom-tree-node:hover {
    background-color: #f5f7fa;
  }
  .tree-node-content {
    flex: 1;
@@ -776,35 +833,117 @@
    height: 100%;
    overflow: hidden;
  }
  .tree-node-content .orange-icon {
  .tree-node-content .tree-icon {
    flex-shrink: 0;
  }
  .tree-node-label {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 500;
    color: #303133;
  }
  .orange-icon {
    color: orange;
  .tree-icon {
    color: #409eff;
    font-size: 18px;
    margin-right: 8px; /* 图标与文字之间加点间距 */
    margin-right: 10px;
    transition: color 0.3s ease;
  }
  .custom-tree-node:hover .tree-icon {
    color: #66b1ff;
  }
  .product-tree-scroll {
    height: calc(100vh - 240px);
    overflow-y: auto;
    scrollbar-width: thin;
    scrollbar-color: #c0c4cc #f5f7fa;
  }
  .product-tree-scroll::-webkit-scrollbar {
    width: 8px;
    width: 6px;
  }
  .product-tree-scroll::-webkit-scrollbar-track {
    background: #f5f7fa;
    border-radius: 4px;
    border-radius: 3px;
  }
  .product-tree-scroll::-webkit-scrollbar-thumb {
    background: #c0c4cc;
    border-radius: 4px;
    border-radius: 3px;
  }
  .product-tree-scroll::-webkit-scrollbar-thumb:hover {
    background: #909399;
  }
  .el-button {
    border-radius: 4px;
    font-size: 13px;
  }
  .el-button--primary {
    background-color: #fff;
    border-color: #409eff;
    color: #409eff;
  }
  .el-button--primary.is-link {
    background-color: transparent;
    border-color: transparent;
    color: #409eff;
  }
  .el-button--primary.is-link:hover {
    background-color: transparent;
    border-color: transparent;
    color: #0033ff;
  }
  .el-button--primary:hover {
    background-color: #e3f1ff;
    border-color: #66b1ff;
  }
  .el-input {
    border-radius: 4px;
  }
  .el-input__wrapper {
    border-radius: 4px;
  }
  .el-dialog {
    border-radius: 8px;
  }
  .el-dialog__header {
    border-bottom: 1px solid #e4e7ed;
    padding: 16px 20px;
  }
  .el-dialog__title {
    font-size: 16px;
    font-weight: 600;
    color: #303133;
  }
  .el-dialog__body {
    padding: 20px;
  }
  .el-form-item {
    margin-bottom: 16px;
  }
  .el-form-item__label {
    font-weight: 500;
    color: #606266;
  }
  .dialog-footer {
    display: flex;
    justify-content: flex-end;
    gap: 10px;
    padding: 16px 20px;
    border-top: 1px solid #e4e7ed;
    background-color: #fafafa;
  }
  .PIMTable {
    border-radius: 4px;
    overflow: hidden;
  }
  .el-table {
    border-radius: 4px;
  }
  .el-table th {
    background-color: #fafafa;
    font-weight: 600;
    color: #303133;
  }
  .el-table tr:hover {
    background-color: #f5f7fa;
  }
</style>