yyb
2 天以前 868e08bf0513b2e6ad0360bc2000119a7e376548
src/views/basicData/product/index.vue
@@ -17,6 +17,9 @@
          style="margin-left: 10px"
          >新增产品大类</el-button
        >
        <el-button type="success" style="margin-left: 10px" @click="openExportDia">
          导出
        </el-button>
      </div>
      <div ref="containerRef">
        <el-tree
@@ -25,18 +28,13 @@
          :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">
@@ -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"
@@ -99,7 +97,7 @@
        @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"
@@ -113,7 +111,10 @@
              <el-input
                v-model="form.productName"
                placeholder="请输入产品名称"
                maxlength="20"
                show-word-limit
                clearable
                @keydown.enter.prevent
              />
            </el-form-item>
          </el-col>
@@ -131,6 +132,7 @@
      title="规格型号"
      width="400px"
      @close="closeModelDia"
      @keydown.enter.prevent
    >
      <el-form
        :model="modelForm"
@@ -146,6 +148,7 @@
                v-model="modelForm.model"
                placeholder="请输入规格型号"
                clearable
                @keydown.enter.prevent
              />
            </el-form-item>
          </el-col>
@@ -157,6 +160,7 @@
                v-model="modelForm.unit"
                placeholder="请输入单位"
                clearable
                @keydown.enter.prevent
              />
            </el-form-item>
          </el-col>
@@ -166,6 +170,42 @@
        <div class="dialog-footer">
          <el-button type="primary" @click="submitModelForm">确认</el-button>
          <el-button @click="closeModelDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
    <el-dialog
      v-model="exportDia"
      title="导出产品数据"
      width="420px"
      @keydown.enter.prevent
    >
      <el-form label-position="top">
        <el-form-item label="选择产品大类(可不选)">
          <el-select
            v-model="exportProductId"
            clearable
            filterable
            placeholder="不选则导出全部产品"
            style="width: 100%"
          >
            <el-option
              v-for="item in rootProductOptions"
              :key="item.id"
              :label="item.label"
              :value="item.id"
            />
          </el-select>
          <div class="export-tip">
            已选:导出该大类及其子类;未选:导出全部
          </div>
        </el-form-item>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" :loading="exportLoading" :disabled="exportLoading" @click="handleExport">
            确认导出
          </el-button>
          <el-button @click="closeExportDia">取消</el-button>
        </div>
      </template>
    </el-dialog>
@@ -180,6 +220,7 @@
  addOrEditProductModel,
  delProduct,
  delProductModel,
  exportProductData,
  modelListPage,
  productTreeList,
} from "@/api/basicData/product.js";
@@ -191,14 +232,18 @@
const productDia = ref(false);
const modelDia = ref(false);
const exportDia = ref(false);
const exportLoading = ref(false);
const modelOperationType = ref("");
const search = ref("");
const currentId = ref("");
const currentParentId = ref("");
const exportProductId = ref("");
const operationType = ref("");
const treeLoad = ref(false);
const list = ref([]);
const expandedKeys = ref([]);
const rootProductOptions = ref([]);
const tableColumn = ref([
  {
    label: "规格型号",
@@ -237,7 +282,10 @@
    productName: "",
  },
  rules: {
    productName: [{ required: true, message: "请输入", trigger: "blur" }],
    productName: [
      { required: true, message: "请输入", trigger: "blur" },
      { max: 20, message: "产品名称不能超过20个字符", trigger: "blur" },
    ],
  },
  modelForm: {
    model: "",
@@ -255,6 +303,7 @@
  productTreeList()
    .then((res) => {
      list.value = res;
      rootProductOptions.value = Array.isArray(res) ? res : [];
      list.value.forEach((a) => {
        expandedKeys.value.push(a.label);
      });
@@ -315,6 +364,7 @@
  proxy.$refs.formRef.resetFields();
  productDia.value = false;
};
// 删除产品
const remove = (node, data) => {
  let ids = [];
@@ -420,6 +470,42 @@
      proxy.$modal.msg("已取消");
    });
};
const openExportDia = () => {
  exportDia.value = true;
};
const closeExportDia = () => {
  exportDia.value = false;
};
// 导出产品(可按大类,含子类)
const handleExport = () => {
  if (exportLoading.value) return;
  exportLoading.value = true;
  const params = exportProductId.value ? { productId: exportProductId.value } : {};
  exportProductData(params)
    .then((blobData) => {
      const blob =
        blobData instanceof Blob
          ? blobData
          : new Blob([blobData], {
              type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
            });
      const url = window.URL.createObjectURL(blob);
      const link = document.createElement("a");
      link.href = url;
      link.download = "产品数据.xlsx";
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      window.URL.revokeObjectURL(url);
      closeExportDia();
    })
    .catch(() => {
      proxy.$modal.msgError("导出失败,请稍后重试");
    })
    .finally(() => {
      exportLoading.value = false;
    });
};
// 调用tree过滤方法 中文英过滤
const filterNode = (value, data, node) => {
  if (!value) {
@@ -464,18 +550,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;
@@ -483,13 +572,47 @@
  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;
}
.export-tip {
  margin-top: 8px;
  font-size: 12px;
  color: #909399;
}
</style>