Parcourir la source

事业部:SKU管理编辑功能

lxf il y a 1 an
Parent
commit
390ae1ce62

+ 3 - 0
src/components/byForm/index.vue

@@ -156,6 +156,9 @@
             :disabled="i.disabled ? i.disabled : false"
             :style="i.style">
           </el-cascader>
+          <div v-else-if="i.type == 'span'">
+            {{ formData[i.prop] }}
+          </div>
           <div class="form-title" v-else-if="i.type == 'title'">
             {{ i.title }}
           </div>

+ 1 - 1
src/components/makeProduct/index.vue

@@ -288,7 +288,7 @@
       </template>
     </el-dialog>
 
-    <el-dialog title="选择BOM" v-if="openDrawingFile" v-model="openDrawingFile" width="70%">
+    <el-dialog title="选择图稿" v-if="openDrawingFile" v-model="openDrawingFile" width="70%">
       <SelectPicture @selectPic="selectPic"></SelectPicture>
       <template #footer>
         <el-button @click="openDrawingFile = false" size="large">关 闭</el-button>

+ 594 - 0
src/components/makeProduct/subsidiary/index.vue

@@ -0,0 +1,594 @@
+<template>
+  <div style="height: calc(100vh - 114px); overflow-y: auto; overflow-x: hidden">
+    <byForm :formConfig="formConfig" :formOption="formOption" v-model="formData.data" :rules="rules" ref="submit">
+      <template #skuClassifyId>
+        <div style="width: 100%">
+          {{ dictKeyValue(formData.data.skuClassifyId, classifyList) }}
+        </div>
+      </template>
+      <template #specification>
+        <div style="width: 100%">
+          <el-table
+            :data="formData.data.skuSpecList"
+            :row-style="{ height: '35px' }"
+            header-row-class-name="tableHeader"
+            :row-key="
+              (row) => {
+                return row.id;
+              }
+            ">
+            <el-table-column type="expand">
+              <template #default="props">
+                <div style="padding: 10px 20px">
+                  <el-row :gutter="20">
+                    <el-col :span="12">
+                      <div style="margin-bottom: 10px">
+                        <el-button type="primary" @click="clickPackingFittings(props)">选择包材配件</el-button>
+                      </div>
+                      <el-table :data="props.row.packagingMaterialList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+                        <el-table-column label="数量" width="120">
+                          <template #default="{ row, $index }">
+                            <el-form-item
+                              :prop="'skuSpecList.' + props.$index + '.packagingMaterialList.' + $index + '.quantity'"
+                              :rules="rulesSpec.quantity"
+                              :inline-message="true"
+                              style="width: 100%">
+                              <el-input-number
+                                onmousewheel="return false;"
+                                v-model="row.quantity"
+                                placeholder="数量"
+                                style="width: 100%"
+                                :controls="false"
+                                :min="0"
+                                :precision="0" />
+                            </el-form-item>
+                          </template>
+                        </el-table-column>
+                        <el-table-column label="名称" prop="name" min-width="220" />
+                        <el-table-column label="操作" align="center" fixed="right" width="60">
+                          <template #default="{ $index }">
+                            <el-button type="danger" @click="clickDeletePackingFittings(props.$index, $index)" text>删除</el-button>
+                          </template>
+                        </el-table-column>
+                      </el-table>
+                    </el-col>
+                    <el-col :span="12">
+                      <div style="margin-bottom: 10px">
+                        <el-button type="primary" @click="clickExpressPacking(props)">选择快递包装</el-button>
+                      </div>
+                      <el-table :data="props.row.expressPackingList" :row-style="{ height: '35px' }" header-row-class-name="tableHeader">
+                        <el-table-column label="数量" width="120">
+                          <template #default="{ row, $index }">
+                            <el-form-item
+                              :prop="'skuSpecList.' + props.$index + '.expressPackingList.' + $index + '.quantity'"
+                              :rules="rulesSpec.quantity"
+                              :inline-message="true"
+                              style="width: 100%">
+                              <el-input-number
+                                onmousewheel="return false;"
+                                v-model="row.quantity"
+                                placeholder="数量"
+                                style="width: 100%"
+                                :controls="false"
+                                :min="0"
+                                :precision="0" />
+                            </el-form-item>
+                          </template>
+                        </el-table-column>
+                        <el-table-column label="名称" prop="name" min-width="220" />
+                        <el-table-column label="操作" align="center" fixed="right" width="60">
+                          <template #default="{ $index }">
+                            <el-button type="danger" @click="clickDeleteExpressPacking(props.$index, $index)" text>删除</el-button>
+                          </template>
+                        </el-table-column>
+                      </el-table>
+                    </el-col>
+                  </el-row>
+                </div>
+              </template>
+            </el-table-column>
+            <el-table-column label="规格图" align="center" width="100">
+              <template #default="{ row, $index }">
+                <el-form-item :prop="'skuSpecList.' + $index + '.specImgUrl'">
+                  <el-upload
+                    class="avatar-uploader"
+                    action="https://winfaster.obs.cn-south-1.myhuaweicloud.com"
+                    :data="uploadData"
+                    :show-file-list="false"
+                    :on-success="
+                      (response, uploadFile) => {
+                        return handleSuccess(uploadFile, $index);
+                      }
+                    "
+                    :before-upload="uploadFile">
+                    <el-image v-if="row.specImgUrl" :src="row.specImgUrl" fit="scale-down" class="avatar" />
+                    <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
+                  </el-upload>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column label="设计图" align="center" width="100">
+              <template #default="{ row, $index }">
+                <el-form-item :prop="'skuSpecList.' + $index + '.designImgUrl'">
+                  <el-image
+                    v-if="row.designImgUrl"
+                    :src="row.designImgUrl"
+                    fit="scale-down"
+                    style="width: 50px; height: 50px; cursor: pointer"
+                    @click="openFile(row.designImgUrl)" />
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column label="品名" min-width="220">
+              <template #default="{ row }">
+                {{ row.name }}
+              </template>
+            </el-table-column>
+            <el-table-column label="品号" width="160">
+              <template #default="{ row }">
+                {{ row.code }}
+              </template>
+            </el-table-column>
+            <el-table-column label="图稿文件" align="center" width="160">
+              <template #default="{ row, $index }">
+                <el-button type="primary" @click="clickDrawingFile($index)" v-if="!row.sharedFolder" text>选择</el-button>
+                <a style="color: #409eff; cursor: pointer; word-break: break-all" @click="clickDrawingFile($index)" v-else>{{ row.sharedFolder }}</a>
+              </template>
+            </el-table-column>
+            <el-table-column label="加工版面" width="140">
+              <template #default="{ row, $index }">
+                <el-form-item :prop="'skuSpecList.' + $index + '.machinedPanel'" style="width: 100%">
+                  <el-select v-model="row.machinedPanel" placeholder="加工版面" clearable>
+                    <el-option v-for="item in useUserStore().allDict['processing_layout']" :key="item.dictKey" :label="item.dictValue" :value="item.dictKey" />
+                  </el-select>
+                </el-form-item>
+              </template>
+            </el-table-column>
+            <el-table-column label="尺寸(长宽高,cm)" align="center" width="180">
+              <template #default="{ row }"> {{ row.length }} * {{ row.width }} * {{ row.height }} </template>
+            </el-table-column>
+            <el-table-column label="净重(g)" width="100">
+              <template #default="{ row }">
+                {{ row.netWeight }}
+              </template>
+            </el-table-column>
+            <el-table-column label="BOM" align="left" width="250">
+              <template #default="{ row }">
+                <div style="width: 100%; display: flex; align-items: center">
+                  <span>{{ row.bomSpecName }}</span>
+                </div>
+              </template>
+            </el-table-column>
+          </el-table>
+        </div>
+      </template>
+      <template #mainImgUrl>
+        <div style="width: 100%">
+          <el-image
+            v-if="formData.data.mainImgUrl"
+            :src="formData.data.mainImgUrl"
+            @click="openFile(formData.data.mainImgUrl)"
+            fit="scale-down"
+            style="width: 150px; height: 150px; cursor: pointer" />
+        </div>
+      </template>
+      <template #detailText>
+        <div style="width: 100%">
+          <div v-html="getStyle(formData.data.detailText)"></div>
+        </div>
+      </template>
+    </byForm>
+    <div style="width: 100%; text-align: center; margin: 10px">
+      <el-button v-if="props.detailStatus" @click="clickCancel()" size="large">关 闭</el-button>
+      <el-button v-if="!props.detailStatus" @click="clickCancel()" size="large">取 消</el-button>
+      <el-button type="primary" @click="submitForm()" v-if="!props.detailStatus" size="large" v-preReClick>确 定</el-button>
+    </div>
+
+    <el-dialog title="选择BOM" v-if="openBOM" v-model="openBOM" width="84%">
+      <SelectBOM :selectStatus="true" :bomClassifyIdList="[1]" @selectBOM="selectBOM"></SelectBOM>
+      <template #footer>
+        <el-button @click="openBOM = false" size="large">关 闭</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="选择包材配件" v-if="openPackingFittings" v-model="openPackingFittings" width="84%">
+      <SelectBOM :selectStatus="true" :bomClassifyIdList="[2, 3]" @selectBOM="selectPackingFittings"></SelectBOM>
+      <template #footer>
+        <el-button @click="openPackingFittings = false" size="large">关 闭</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="选择快递包装" v-if="openExpressPacking" v-model="openExpressPacking" width="84%">
+      <SelectBOM :selectStatus="true" :expressStatus="true" @selectBOM="selectExpressPacking"></SelectBOM>
+      <template #footer>
+        <el-button @click="openExpressPacking = false" size="large">关 闭</el-button>
+      </template>
+    </el-dialog>
+
+    <el-dialog title="选择图稿" v-if="openDrawingFile" v-model="openDrawingFile" width="70%">
+      <SelectPicture @selectPic="selectPic"></SelectPicture>
+      <template #footer>
+        <el-button @click="openDrawingFile = false" size="large">关 闭</el-button>
+      </template>
+    </el-dialog>
+  </div>
+</template>
+
+<script setup>
+import byForm from "@/components/byForm/index";
+import { ElMessage } from "element-plus";
+import SelectBOM from "@/views/group/BOM/management/index";
+import SelectPicture from "@/components/select-picture/index.vue";
+
+const { proxy } = getCurrentInstance();
+const emit = defineEmits(["clickCancel"]);
+const submit = ref(null);
+const formOption = reactive({
+  inline: true,
+  labelWidth: "120px",
+  itemWidth: 100,
+  rules: [],
+  labelPosition: "right",
+});
+const formData = reactive({
+  data: {
+    type: 0,
+    source: 1,
+    mainImgUrl: "",
+    detailText: "",
+    skuSpecList: [
+      {
+        specImgUrl: "",
+        designImgUrl: "",
+        name: "",
+        code: "",
+        barCode: "",
+        machinedPanel: "",
+        length: undefined,
+        width: undefined,
+        height: undefined,
+        netWeight: undefined,
+        sharedFolder: "",
+        bomSpecId: "",
+        remark: "",
+        packagingMaterialList: [],
+        expressPackingList: [],
+      },
+    ],
+  },
+});
+const formConfig = computed(() => {
+  return [
+    {
+      type: "title",
+      title: "基本信息",
+      label: "",
+    },
+    {
+      type: "slot",
+      prop: "skuClassifyId",
+      slotName: "skuClassifyId",
+      label: "类目",
+      itemWidth: 50,
+    },
+    {
+      type: "span",
+      prop: "barCode",
+      label: "条码",
+      itemWidth: 50,
+    },
+    {
+      type: "span",
+      prop: "groupItemNumber",
+      label: "群组品号",
+      itemWidth: 50,
+    },
+    {
+      type: "span",
+      prop: "code",
+      label: "编码",
+      itemWidth: 50,
+    },
+    {
+      type: "span",
+      prop: "name",
+      label: "名称",
+    },
+    {
+      type: "title",
+      title: "材质特征",
+      label: "",
+    },
+    {
+      type: "span",
+      label: "品牌",
+      prop: "brand",
+      itemWidth: 50,
+    },
+    {
+      type: "span",
+      prop: "modelNumber",
+      label: "型号",
+      itemWidth: 50,
+    },
+    {
+      type: "span",
+      prop: "material",
+      label: "材质",
+      itemWidth: 50,
+    },
+    {
+      type: "slot",
+      slotName: "specification",
+      label: "规格",
+    },
+    {
+      type: "title",
+      title: "图片介绍",
+      label: "",
+    },
+    {
+      type: "slot",
+      slotName: "mainImgUrl",
+      label: "主图",
+    },
+    {
+      type: "slot",
+      slotName: "detailText",
+      label: "详情描述",
+    },
+  ];
+});
+const rules = ref({});
+const rulesSpec = ref({
+  quantity: [{ required: true, message: "请输入数量", trigger: "blur" }],
+});
+const classifyList = ref([]);
+const treeToList = (arr) => {
+  let res = [];
+  let fn = (source) => {
+    source.forEach((el) => {
+      res.push(el);
+      el.children && el.children.length > 0 ? fn(el.children) : "";
+    });
+  };
+  fn(arr);
+  return res;
+};
+const getBomClassify = () => {
+  proxy.post("/skuClassify/tree", {}).then((res) => {
+    classifyList.value = treeToList(res).map((item) => {
+      return {
+        ...item,
+        dictKey: item.id,
+        dictValue: item.name,
+      };
+    });
+  });
+};
+getBomClassify();
+const uploadData = ref({});
+const uploadFile = async (file) => {
+  const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+  uploadData.value = res.uploadBody;
+  file.id = res.id;
+  file.fileName = res.fileName;
+  file.fileUrl = res.fileUrl;
+  return true;
+};
+const handleSuccess = (uploadFile, index) => {
+  formData.data.skuSpecList[index].specImgUrl = uploadFile.raw.fileUrl;
+};
+const uploadMainData = ref({});
+const uploadMainFile = async (file) => {
+  const res = await proxy.post("/fileInfo/getSing", { fileName: file.name });
+  uploadMainData.value = res.uploadBody;
+  file.id = res.id;
+  file.fileName = res.fileName;
+  file.fileUrl = res.fileUrl;
+  return true;
+};
+const handleMainSuccess = (response, uploadFile) => {
+  formData.data.mainImgUrl = uploadFile.raw.fileUrl;
+};
+const submitForm = () => {
+  submit.value.handleSubmit(() => {
+    if (formData.data.skuSpecList && formData.data.skuSpecList.length > 0) {
+      let type = "add";
+      if (formData.data.id) {
+        type = "edit";
+      }
+      proxy.post("/sku/" + type, formData.data).then(() => {
+        ElMessage({
+          message: type == "add" ? "添加成功" : "编辑成功",
+          type: "success",
+        });
+        emit("clickCancel", true);
+      });
+    } else {
+      return ElMessage("请添加规格");
+    }
+  });
+};
+const clickCancel = () => {
+  emit("clickCancel", false);
+};
+const props = defineProps({
+  rowData: Object,
+  detailStatus: Boolean,
+});
+onMounted(() => {
+  formOption.disabled = props.detailStatus;
+  if (props.rowData && props.rowData.id) {
+    proxy.post("/sku/detail", { id: props.rowData.id }).then((res) => {
+      for (var text in res) {
+        formData.data[text] = res[text];
+      }
+    });
+  }
+});
+const getStyle = (text) => {
+  if (text) {
+    return text.replace(/\n|\r\n/g, "<br>");
+  } else {
+    return "";
+  }
+};
+const rowIndex = ref(null);
+const openBOM = ref(false);
+const handleOpen = (index) => {
+  rowIndex.value = index;
+  openBOM.value = true;
+};
+const selectBOM = (item) => {
+  if (item.id) {
+    formData.data.skuSpecList[rowIndex.value].bomSpecId = item.id;
+    formData.data.skuSpecList[rowIndex.value].bomSpecName = item.name;
+    formData.data.skuSpecList[rowIndex.value].length = item.length;
+    formData.data.skuSpecList[rowIndex.value].width = item.width;
+    formData.data.skuSpecList[rowIndex.value].height = item.height;
+    formData.data.skuSpecList[rowIndex.value].netWeight = item.netWeight;
+    ElMessage({ message: "选择完成", type: "success" });
+    openBOM.value = false;
+  }
+};
+const clickRemoveBOM = (index) => {
+  formData.data.skuSpecList[index].bomSpecId = "";
+  formData.data.skuSpecList[index].bomSpecName = "";
+};
+const openPackingFittings = ref(false);
+const clickPackingFittings = (item) => {
+  rowIndex.value = item.$index;
+  openPackingFittings.value = true;
+};
+const openExpressPacking = ref(false);
+const clickExpressPacking = (item) => {
+  rowIndex.value = item.$index;
+  openExpressPacking.value = true;
+};
+const selectPackingFittings = (data) => {
+  if (formData.data.skuSpecList[rowIndex.value].packagingMaterialList && formData.data.skuSpecList[rowIndex.value].packagingMaterialList.length > 0) {
+    let list = formData.data.skuSpecList[rowIndex.value].packagingMaterialList.filter((item) => item.bomSpecId === data.id);
+    if (list && list.length > 0) {
+      return ElMessage("包材配件已添加");
+    }
+    formData.data.skuSpecList[rowIndex.value].packagingMaterialList.push({
+      bomSpecId: data.id,
+      quantity: undefined,
+      name: data.name,
+    });
+  } else {
+    formData.data.skuSpecList[rowIndex.value].packagingMaterialList = [
+      {
+        bomSpecId: data.id,
+        quantity: undefined,
+        name: data.name,
+      },
+    ];
+  }
+  ElMessage({ message: "添加成功", type: "success" });
+};
+const selectExpressPacking = (data) => {
+  if (formData.data.skuSpecList[rowIndex.value].expressPackingList && formData.data.skuSpecList[rowIndex.value].expressPackingList.length > 0) {
+    let list = formData.data.skuSpecList[rowIndex.value].expressPackingList.filter((item) => item.bomSpecId === data.id);
+    if (list && list.length > 0) {
+      return ElMessage("快递包材已添加");
+    }
+    formData.data.skuSpecList[rowIndex.value].expressPackingList.push({
+      bomSpecId: data.id,
+      quantity: undefined,
+      name: data.name,
+    });
+  } else {
+    formData.data.skuSpecList[rowIndex.value].expressPackingList = [
+      {
+        bomSpecId: data.id,
+        quantity: undefined,
+        name: data.name,
+      },
+    ];
+  }
+  ElMessage({ message: "添加成功", type: "success" });
+};
+const clickDeletePackingFittings = (index, indexTwo) => {
+  formData.data.skuSpecList[index].packagingMaterialList.splice(indexTwo, 1);
+};
+const clickDeleteExpressPacking = (index, indexTwo) => {
+  formData.data.skuSpecList[index].expressPackingList.splice(indexTwo, 1);
+};
+const drawingFileIndex = ref(0);
+const openDrawingFile = ref(false);
+const clickDrawingFile = (index) => {
+  drawingFileIndex.value = index;
+  openDrawingFile.value = true;
+};
+const selectPic = (row) => {
+  formData.data.skuSpecList[drawingFileIndex.value].sharedFolder = row.artworkName + "/" + row.fileName;
+  formData.data.skuSpecList[drawingFileIndex.value].designImgUrl = row.imgUrl;
+  ElMessage({ message: "选择完成", type: "success" });
+  openDrawingFile.value = false;
+};
+const openFile = (path) => {
+  window.open(path);
+};
+</script>
+
+<style lang="scss" scoped>
+.avatar-uploader .avatar {
+  width: 50px;
+  height: 50px;
+  display: block;
+  background-color: black;
+}
+.avatar-uploader .el-upload {
+  border: 1px dashed var(--el-border-color);
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  transition: var(--el-transition-duration-fast);
+}
+.avatar-uploader .el-upload:hover {
+  border-color: var(--el-color-primary);
+}
+.el-icon.avatar-uploader-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 50px;
+  height: 50px;
+  text-align: center;
+  border: 1px dashed var(--el-border-color);
+}
+::v-deep(.el-input-number .el-input__inner) {
+  text-align: left;
+}
+.avatar-uploader-main .avatar {
+  width: 148px;
+  height: 148px;
+  display: block;
+  background-color: black;
+}
+.avatar-uploader-main .el-upload {
+  border: 1px dashed var(--el-border-color);
+  border-radius: 6px;
+  cursor: pointer;
+  position: relative;
+  overflow: hidden;
+  transition: var(--el-transition-duration-fast);
+}
+.avatar-uploader-main .el-upload:hover {
+  border-color: var(--el-color-primary);
+}
+.el-icon.avatar-uploader-main-icon {
+  font-size: 28px;
+  color: #8c939d;
+  width: 148px;
+  height: 148px;
+  text-align: center;
+  border: 1px dashed var(--el-border-color);
+}
+:deep(.el-dialog) {
+  margin-top: 10px !important;
+  margin-bottom: 10px !important;
+}
+</style>

+ 1 - 1
src/views/subsidiary/product/management/index.vue

@@ -56,7 +56,7 @@
 
 <script setup>
 import byTable from "@/components/byTable/index";
-import MakeSKU from "@/components/makeProduct/index";
+import MakeSKU from "@/components/makeProduct/subsidiary/index";
 
 const { proxy } = getCurrentInstance();
 const sourceList = ref({