Bläddra i källkod

SKU SKU管理,分类

lxf 1 år sedan
förälder
incheckning
7e1917ed71

+ 1 - 1
src/views/group/product/classification/index.vue

@@ -18,7 +18,7 @@
       @get-list="getList"
       @clickReset="clickReset">
     </byTable>
-    <el-table :data="sourceList.data" row-key="id" default-expand-all>
+    <el-table :data="sourceList.data" :row-style="{ height: '35px' }" header-row-class-name="tableHeader" row-key="id" default-expand-all>
       <el-table-column prop="name" label="分类名称" min-width="180" />
       <el-table-column prop="sort" label="排序" align="center" width="100" />
       <!-- <el-table-column label="操作" align="center" width="180">

+ 199 - 0
src/views/subsidiary/product/classification/index.vue

@@ -0,0 +1,199 @@
+<template>
+  <el-card class="box-card">
+    <byTable
+      :hideTable="true"
+      :hidePagination="true"
+      :source="sourceList.data"
+      :pagination="sourceList.pagination"
+      :config="config"
+      :loading="loading"
+      :searchConfig="searchConfig"
+      highlight-current-row
+      :action-list="[
+        // {
+        //   text: '新增',
+        //   action: () => clickModal(),
+        // },
+      ]"
+      @get-list="getList"
+      @clickReset="clickReset">
+    </byTable>
+    <el-table :data="sourceList.data" row-key="id" :row-style="{ height: '35px' }" header-row-class-name="tableHeader" default-expand-all>
+      <el-table-column prop="name" label="分类名称" min-width="180" />
+      <el-table-column prop="sort" label="排序" align="center" width="100" />
+      <!-- <el-table-column label="操作" align="center" width="180">
+        <template #default="{ row }">
+          <div>
+            <el-button type="primary" @click="addChildNode(row)" text>添加子节点</el-button>
+            <el-button type="primary" @click="clickUpdate(row)" v-if="row.parentId" text>编辑</el-button>
+            <el-button type="danger" @click="clickDelete(row)" v-if="row.parentId" text>删除</el-button>
+          </div>
+        </template>
+      </el-table-column> -->
+    </el-table>
+
+    <el-dialog :title="modalType == 'add' ? '新增分类' : '编辑分类'" v-if="openDialog" v-model="openDialog" width="400">
+      <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
+        <template #parentId>
+          <div style="width: 100%">
+            <el-cascader
+              v-model="formData.data.parentId"
+              :options="sourceList.data"
+              :props="{ checkStrictly: true, value: 'id', label: 'name', emitPath: false }"
+              clearable
+              style="width: 100%" />
+          </div>
+        </template>
+      </byForm>
+      <template #footer>
+        <el-button @click="openDialog = false" size="large">取 消</el-button>
+        <el-button type="primary" @click="submitForm()" size="large" v-preReClick>确 定</el-button>
+      </template>
+    </el-dialog>
+  </el-card>
+</template>
+
+<script setup>
+import byTable from "@/components/byTable/index";
+import byForm from "@/components/byForm/index";
+import { ElMessage, ElMessageBox } from "element-plus";
+
+const { proxy } = getCurrentInstance();
+const sourceList = ref({
+  data: [],
+  pagination: {
+    total: 0,
+    name: "",
+  },
+});
+const loading = ref(false);
+const searchConfig = computed(() => {
+  return [
+    {
+      type: "input",
+      prop: "name",
+      label: "分类名称",
+    },
+  ];
+});
+const config = computed(() => {
+  return [];
+});
+const getList = async (req) => {
+  sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  loading.value = true;
+  proxy.post("/skuClassify/tree", sourceList.value.pagination).then((res) => {
+    sourceList.value.data = res;
+    setTimeout(() => {
+      loading.value = false;
+    }, 200);
+  });
+};
+getList();
+const clickReset = () => {
+  getList({ name: "" });
+};
+const modalType = ref("add");
+const submit = ref(null);
+const openDialog = ref(false);
+const formOption = reactive({
+  inline: true,
+  labelWidth: 100,
+  itemWidth: 100,
+  rules: [],
+});
+const formData = reactive({
+  data: {},
+});
+const formConfig = computed(() => {
+  return [
+    {
+      type: "slot",
+      prop: "parentId",
+      slotName: "parentId",
+      label: "上级分类",
+    },
+    {
+      type: "input",
+      prop: "name",
+      label: "分类名称",
+      itemType: "text",
+    },
+    {
+      type: "input",
+      prop: "code",
+      label: "分类编码",
+      itemType: "text",
+    },
+    {
+      type: "number",
+      prop: "sort",
+      label: "排序",
+      precision: 0,
+    },
+    {
+      type: "input",
+      prop: "remark",
+      label: "备注",
+      itemType: "textarea",
+    },
+  ];
+});
+const rules = ref({
+  parentId: [{ required: true, message: "请选择上级分类", trigger: "change" }],
+  name: [{ required: true, message: "请输入分类名称", trigger: "blur" }],
+  code: [{ required: true, message: "请输入分类编码", trigger: "blur" }],
+});
+const clickModal = () => {
+  modalType.value = "add";
+  formData.data = {};
+  openDialog.value = true;
+};
+const addChildNode = (row) => {
+  modalType.value = "add";
+  formData.data = {
+    parentId: row.id,
+  };
+  openDialog.value = true;
+};
+const submitForm = () => {
+  submit.value.handleSubmit(() => {
+    proxy.post("/skuClassify/" + modalType.value, formData.data).then(() => {
+      ElMessage({
+        message: modalType.value == "add" ? "添加成功" : "编辑成功",
+        type: "success",
+      });
+      openDialog.value = false;
+      getList();
+    });
+  });
+};
+const clickUpdate = (row) => {
+  modalType.value = "edit";
+  formData.data = {
+    id: row.id,
+    parentId: row.parentId,
+    name: row.name,
+    code: row.code,
+    sort: row.sort,
+    remark: row.remark,
+  };
+  openDialog.value = true;
+};
+const clickDelete = (row) => {
+  ElMessageBox.confirm("你是否确认此操作", "提示", {
+    confirmButtonText: "确定",
+    cancelButtonText: "取消",
+    type: "warning",
+  })
+    .then(() => {
+      proxy.post("/skuClassify/delete", { id: row.id }).then(() => {
+        ElMessage({ message: "删除成功", type: "success" });
+        getList();
+      });
+    })
+    .catch(() => {});
+};
+</script>
+
+<style lang="scss" scoped></style>

+ 237 - 0
src/views/subsidiary/product/management/index.vue

@@ -0,0 +1,237 @@
+<template>
+  <div>
+    <el-card class="box-card">
+      <byTable
+        :source="sourceList.data"
+        :pagination="sourceList.pagination"
+        :config="config"
+        :loading="loading"
+        :searchConfig="searchConfig"
+        highlight-current-row
+        @get-list="getList"
+        @clickReset="clickReset">
+        <template #typeExpand="{ item }">
+          <div style="padding: 0px 20px; box-sizing: border-box" v-if="item.skuSpecList && item.skuSpecList.length > 0">
+            <div
+              v-for="spec in item.skuSpecList"
+              :key="spec.id"
+              style="display: flex; padding: 8px 16px; align-items: center; box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.1); margin-bottom: 8px">
+              <div style="width: 80px">
+                <div v-if="spec.specImgUrl">
+                  <img
+                    style="width: 40px; height: 40px; object-fit: contain; vertical-align: middle; border: none; cursor: pointer"
+                    :src="spec.specImgUrl"
+                    @click="openFile(spec.specImgUrl)" />
+                </div>
+                <div
+                  v-else
+                  class="el-icon-picture-outline"
+                  style="width: 40px; height: 40px; font-size: 36px; line-height: 40px; text-align: center; color: rgb(229 228 228)"></div>
+              </div>
+              <div style="width: 180px">
+                {{ spec.code }}
+              </div>
+              <div style="flex: 1">
+                {{ spec.name }}
+              </div>
+              <div style="width: 180px">
+                {{ `${spec.length}  *  ${spec.width}  *  ${spec.height}(cm³)` }}
+              </div>
+            </div>
+          </div>
+        </template>
+        <template #name="{ item }">
+          <div>
+            <a style="color: #409eff; cursor: pointer; word-break: break-all" @click="clickName(item)">{{ item.name }}</a>
+          </div>
+        </template>
+      </byTable>
+    </el-card>
+
+    <el-dialog :title="modalTitle" v-if="openDialog" v-model="openDialog" width="90%">
+      <MakeSKU :rowData="rowData" :detailStatus="detailStatus" @clickCancel="clickCancel"></MakeSKU>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import byTable from "@/components/byTable/index";
+import MakeSKU from "@/components/makeProduct/index";
+
+const { proxy } = getCurrentInstance();
+const sourceList = ref({
+  data: [],
+  pagination: {
+    total: 0,
+    pageNum: 1,
+    pageSize: 10,
+    name: "",
+    code: "",
+    type: 0,
+    brand: "",
+  },
+});
+const loading = ref(false);
+const searchConfig = computed(() => {
+  return [
+    {
+      type: "input",
+      prop: "name",
+      label: "品名",
+    },
+    {
+      type: "input",
+      prop: "code",
+      label: "品号",
+    },
+    {
+      type: "select",
+      prop: "brand",
+      dictKey: "wlnBrand",
+      label: "品牌",
+    },
+  ];
+});
+const config = computed(() => {
+  return [
+    {
+      type: "expand",
+      attrs: {
+        label: " ",
+        slot: "typeExpand",
+        width: 50,
+      },
+    },
+    {
+      attrs: {
+        label: "群组品号",
+        prop: "code",
+        width: 180,
+      },
+    },
+    {
+      attrs: {
+        label: "群组品名",
+        slot: "name",
+        "min-width": 240,
+      },
+    },
+    {
+      attrs: {
+        label: "产品来源",
+        prop: "source",
+        width: 120,
+      },
+      render(val) {
+        return val == 1 ? "MES" : "万里牛";
+      },
+    },
+    {
+      attrs: {
+        label: "品牌",
+        prop: "brand",
+        width: 120,
+      },
+      render(val) {
+        return proxy.dictKeyValue(val, proxy.useUserStore().allDict["wlnBrand"]);
+      },
+    },
+    {
+      attrs: {
+        label: "型号",
+        prop: "modelNumber",
+        width: 200,
+      },
+    },
+    {
+      attrs: {
+        label: "材质",
+        prop: "material",
+        width: 200,
+      },
+    },
+    {
+      attrs: {
+        label: "操作",
+        width: 80,
+        align: "center",
+        fixed: "right",
+      },
+      renderHTML(row) {
+        return [
+          {
+            attrs: {
+              label: "编辑",
+              type: "primary",
+              text: true,
+            },
+            el: "button",
+            click() {
+              clickUpdate(row);
+            },
+          },
+        ];
+      },
+    },
+  ];
+});
+const getList = async (req, status) => {
+  if (status) {
+    sourceList.value.pagination = {
+      pageNum: sourceList.value.pagination.pageNum,
+      pageSize: sourceList.value.pagination.pageSize,
+    };
+  } else {
+    sourceList.value.pagination = { ...sourceList.value.pagination, ...req };
+  }
+  loading.value = true;
+  proxy.post("/sku/page", sourceList.value.pagination).then((res) => {
+    sourceList.value.data = res.rows;
+    sourceList.value.pagination.total = res.total;
+    setTimeout(() => {
+      loading.value = false;
+    }, 200);
+  });
+};
+getList();
+const clickReset = () => {
+  getList("", true);
+};
+const modalTitle = ref("编辑SKU");
+const openDialog = ref(false);
+const rowData = ref({});
+const detailStatus = ref(false);
+const clickUpdate = (row) => {
+  modalTitle.value = "编辑SKU";
+  rowData.value = row;
+  detailStatus.value = false;
+  openDialog.value = true;
+};
+const clickCancel = (status) => {
+  openDialog.value = false;
+  if (status) {
+    getList();
+  }
+};
+const openFile = (path) => {
+  window.open(path);
+};
+const clickName = (row) => {
+  modalTitle.value = "SKU详情";
+  rowData.value = row;
+  detailStatus.value = true;
+  openDialog.value = true;
+};
+</script>
+
+<style lang="scss" scoped>
+:deep(.el-dialog) {
+  margin-top: 10px !important;
+  margin-bottom: 10px !important;
+}
+.select-card {
+  height: calc(100vh - 184px);
+  overflow-y: auto;
+  overflow-x: hidden;
+}
+</style>