Ver Fonte

物料库

lxf há 2 anos atrás
pai
commit
745d223aa8

+ 24 - 14
src/router/routerLXF.js

@@ -16,20 +16,30 @@ export function routesLXF() {
       component: () => import("../views/product-material/material-classification/edit.vue"),
     },
     {
-        path: "productClassification",
-        name: "产品分类",
-        component: () => import("../views/product-material/product-classification/index.vue"),
-      },
-      {
-        path: "productClassificationAdd",
-        name: "产品分类添加",
-        component: () => import("../views/product-material/product-classification/add.vue"),
-      },
-      {
-        path: "productClassificationEdit",
-        name: "产品分类编辑",
-        component: () => import("../views/product-material/product-classification/edit.vue"),
-      },
+      path: "productClassification",
+      name: "产品分类",
+      component: () => import("../views/product-material/product-classification/index.vue"),
+    },
+    {
+      path: "productClassificationAdd",
+      name: "产品分类添加",
+      component: () => import("../views/product-material/product-classification/add.vue"),
+    },
+    {
+      path: "productClassificationEdit",
+      name: "产品分类编辑",
+      component: () => import("../views/product-material/product-classification/edit.vue"),
+    },
+    {
+      path: "materialLibrary",
+      name: "物料库",
+      component: () => import("../views/product-material/material-library/index.vue"),
+    },
+    {
+      path: "materialLibraryAdd",
+      name: "物料库添加",
+      component: () => import("../views/product-material/material-library/add.vue"),
+    },
   ];
   return routesLXF;
 }

+ 3 - 0
src/utils/axios.js

@@ -26,6 +26,9 @@ service.interceptors.request.use(config => {
   if ( getToken() || !isToken) {
     config.headers['Authorization'] = 'Bearer ' + getToken()// 让每个请求携带自定义token 请根据实际情况自行修改
   }
+  if (config.url === 'https://winfaster.obs.cn-south-1.myhuaweicloud.com') {
+    config.headers['Content-Type'] = 'multipart/form-data'
+  }
   // get请求映射params参数
   if (config.method === 'get' && config.params) {
     let url = config.url + '?' + tansParams(config.params);

+ 293 - 0
src/views/product-material/material-library/add.vue

@@ -0,0 +1,293 @@
+<template>
+  <div class="form">
+    <van-nav-bar title="仓库维护" left-text="返回" left-arrow @click-left="onClickLeft"> </van-nav-bar>
+    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field
+          v-model="formData.productClassifyName"
+          is-link
+          readonly
+          label="物料分类"
+          placeholder="请选择物料分类"
+          @click="show = true"
+          :rules="[{ required: true, message: '物料分类不能为空' }]"
+          required />
+        <van-popup v-model:show="show" round position="bottom">
+          <van-cascader
+            title="请选择物料分类"
+            :options="classification"
+            :field-names="fieldNames"
+            @close="show = false"
+            @change="onChange"
+            @finish="onFinish" />
+        </van-popup>
+        <van-field
+          v-model="formData.typeName"
+          is-link
+          readonly
+          label="物料类型"
+          placeholder="选择物料类型"
+          @click="typeModal = true"
+          :rules="[{ required: true, message: '物料类型不能为空' }]"
+          required />
+        <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker :columns="typeList" @cancel="typeModal = false" @confirm="onConfirmType" />
+        </van-popup>
+        <van-field
+          v-model="formData.name"
+          name="物料名称"
+          label="物料名称"
+          placeholder="请填写物料名称"
+          :rules="[{ required: true, message: '物料名称不能为空' }]"
+          required />
+        <van-field
+          v-model="formData.spec"
+          name="规格型号"
+          label="规格型号"
+          placeholder="请填写规格型号"
+          :rules="[{ required: true, message: '规格型号不能为空' }]"
+          required />
+        <van-field
+          v-model="formData.unit"
+          is-link
+          readonly
+          label="单位"
+          placeholder="选择单位"
+          @click="unitModal = true"
+          :rules="[{ required: true, message: '单位不能为空' }]"
+          required />
+        <van-popup v-model:show="unitModal" round position="bottom">
+          <van-picker :columns="unitList" @cancel="unitModal = false" @confirm="onConfirmUnit" />
+        </van-popup>
+        <van-field name="uploader" label="文件上传">
+          <template #input>
+            <van-uploader v-model="fileList" :after-read="afterRead" multiple :max-count="9" :max-size="5 * 1024 * 1024" @oversize="onOversize" />
+          </template>
+        </van-field>
+        <van-field v-model="formData.remark" rows="3" type="textarea" name="备注" label="备注" placeholder="请填写备注" />
+      </van-cell-group>
+      <div style="margin: 16px">
+        <van-button round block type="primary" native-type="submit"> 提交 </van-button>
+      </div>
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted } from "vue";
+import { showSuccessToast, showToast } from "vant";
+import { useRoute } from "vue-router";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const show = ref(false);
+const typeModal = ref(false);
+const unitModal = ref(false);
+const classification = ref([]);
+const fieldNames = {
+  text: "label",
+  value: "id",
+};
+const typeList = ref([
+  {
+    text: "原料",
+    value: "1",
+  },
+  {
+    text: "辅料",
+    value: "2",
+  },
+  {
+    text: "配件",
+    value: "3",
+  },
+  {
+    text: "包材",
+    value: "4",
+  },
+  {
+    text: "其他",
+    value: "5",
+  },
+]);
+const unitList = ref([
+  {
+    text: "个",
+    value: "个",
+  },
+  {
+    text: "双",
+    value: "双",
+  },
+]);
+const formData = ref({
+  id: null,
+  definition: "2",
+  productClassifyId: null,
+  productClassifyName: null,
+  code: null,
+  customCode: null,
+  type: null,
+  typeName: null,
+  name: null,
+  spec: null,
+  unit: null,
+  remark: null,
+  fileList: [],
+});
+const onConfirmType = ({ selectedOptions }) => {
+  formData.value.type = selectedOptions[0].value;
+  formData.value.typeName = selectedOptions[0].text;
+  typeModal.value = false;
+};
+const onConfirmUnit = ({ selectedOptions }) => {
+  formData.value.unit = selectedOptions[0].value;
+  unitModal.value = false;
+};
+const onChange = ({ selectedOptions }) => {
+  if (selectedOptions && selectedOptions.length > 0) {
+    formData.value.productClassifyId = selectedOptions[selectedOptions.length - 1].id;
+    formData.value.productClassifyName = selectedOptions[selectedOptions.length - 1].label;
+  }
+};
+const onFinish = ({ selectedOptions }) => {
+  show.value = false;
+  if (selectedOptions && selectedOptions.length > 0) {
+    formData.value.productClassifyId = selectedOptions[selectedOptions.length - 1].id;
+    formData.value.productClassifyName = selectedOptions[selectedOptions.length - 1].label;
+  }
+};
+const fileList = ref([]);
+const afterRead = (file) => {
+  if (file && file.length > 0) {
+    for (let i = 0; i < file.length; i++) {
+      file[i].status = "uploading";
+      file[i].message = "上传中...";
+      proxy.post("/fileInfo/getSing", { fileName: file[i].file.name }).then(
+        (res) => {
+          let forms = new FormData();
+          forms.append("file", file[i].file);
+          proxy.post("https://winfaster.obs.cn-south-1.myhuaweicloud.com", { ...res.data.uploadBody, file: forms.get("file") }).then(
+            () => {
+              file[i].id = res.data.id;
+              file[i].url = res.data.fileUrl;
+              file[i].fileName = res.data.fileName;
+              delete file[i].status;
+              delete file[i].message;
+            },
+            () => {
+              file[i].status = "failed";
+              file[i].message = "上传失败";
+            }
+          );
+        },
+        () => {
+          file[i].status = "failed";
+          file[i].message = "上传失败";
+        }
+      );
+    }
+  } else {
+    file.status = "uploading";
+    file.message = "上传中...";
+    proxy.post("/fileInfo/getSing", { fileName: file.file.name }).then(
+      (res) => {
+        let forms = new FormData();
+        forms.append("file", file.file);
+        proxy.post("https://winfaster.obs.cn-south-1.myhuaweicloud.com", { ...res.data.uploadBody, file: forms.get("file") }).then(
+          () => {
+            file.id = res.data.id;
+            file.url = res.data.fileUrl;
+            file.fileName = res.data.fileName;
+            delete file.status;
+            delete file.message;
+          },
+          () => {
+            file.status = "failed";
+            file.message = "上传失败";
+          }
+        );
+      },
+      () => {
+        file.status = "failed";
+        file.message = "上传失败";
+      }
+    );
+  }
+};
+const onOversize = () => {
+  showToast("文件大小不能超过 5MB");
+};
+const onClickLeft = () => history.back();
+const onSubmit = () => {
+  if (fileList.value && fileList.value.length > 0) {
+    formData.value.fileList = fileList.value.map((item) => {
+      return {
+        id: item.id,
+        fileName: item.fileName,
+      };
+    });
+  } else {
+    formData.value.fileList = [];
+  }
+  proxy.post("/productInfo/" + route.query.type, formData.value).then(() => {
+    showSuccessToast("添加成功");
+    setTimeout(() => {
+      history.back();
+    }, 500);
+  });
+};
+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;
+};
+onMounted(() => {
+  proxy.post("/productClassify/tree", { parentId: "", name: "", definition: "2" }).then((res) => {
+    classification.value = res.data;
+    let classList = treeToList(res.data);
+    if (route.query.id) {
+      proxy.post("/productInfo/detail", { id: route.query.id }).then((resDetail) => {
+        formData.value.id = route.query.id;
+        formData.value.productClassifyId = resDetail.data.productClassifyId;
+        let data = classList.filter((item) => item.id === resDetail.data.productClassifyId);
+        if (data && data.length > 0) {
+          formData.value.productClassifyName = data[0].label;
+        }
+        formData.value.code = resDetail.data.code;
+        formData.value.customCode = resDetail.data.customCode;
+        formData.value.type = resDetail.data.type;
+        let typeNameList = typeList.value.filter((item) => item.value == resDetail.data.type);
+        if (typeNameList && typeNameList.length > 0) {
+          formData.value.typeName = typeNameList[0].text;
+        }
+        formData.value.name = resDetail.data.name;
+        formData.value.spec = resDetail.data.spec;
+        formData.value.unit = resDetail.data.unit;
+        formData.value.remark = resDetail.data.remark;
+      });
+      proxy.post("/fileInfo/getList", { businessIdList: [route.query.id] }).then((res) => {
+        if (res.data[route.query.id] && res.data[route.query.id].length > 0) {
+          formData.value.fileList = res.data[route.query.id];
+          fileList.value = res.data[route.query.id].map((item) => {
+            return {
+              ...item,
+              url: item.fileUrl,
+            };
+          });
+        } else {
+          formData.value.fileList = [];
+          fileList.value = [];
+        }
+      });
+    }
+  });
+});
+</script>

+ 125 - 0
src/views/product-material/material-library/index.vue

@@ -0,0 +1,125 @@
+<template>
+  <van-nav-bar title="仓库维护" left-text="" left-arrow @click-left="onClickLeft" @click-right="onClickRight">
+    <template #right> 添加 </template>
+  </van-nav-bar>
+  <van-search v-model="req.keyword" placeholder="请输入搜索关键词" @search="onRefresh" />
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list v-model:loading="loading" :finished="finished" finished-text="没有更多了" @load="onLoad" style="margin-bottom: 60px">
+        <commonList :data="listData" @onClick="toDtl" :config="listConfig"></commonList>
+      </van-list>
+    </div>
+  </van-pull-refresh>
+</template>
+<script setup>
+import { ref, getCurrentInstance } from "vue";
+import commonList from "@/components/common-list.vue";
+import { useRoute } from "vue-router";
+
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  keyword: null,
+  definition: "2",
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+const classification = ref([]);
+const listConfig = ref([
+  {
+    label: "物料分类",
+    prop: "productClassifyName",
+  },
+  {
+    label: "物料编码",
+    prop: "code",
+  },
+  {
+    label: "物料名称",
+    prop: "name",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getClassification();
+};
+const onClickLeft = () => proxy.$router.push("/main/working");
+const onClickRight = () => {
+  proxy.$router.push({
+    path: "materialLibraryAdd",
+    query: {
+        type: 'add'
+    },
+  });
+};
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "materialLibraryAdd",
+    query: {
+      id: row.id,
+      type: 'edit'
+    },
+  });
+};
+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 getClassification = () => {
+  if (classification.value && classification.value.length > 0) {
+    getList();
+  } else {
+    proxy.post("/productClassify/tree", { parentId: "", name: "", definition: "2" }).then((res) => {
+      classification.value = treeToList(res.data);
+      getList();
+    });
+  }
+};
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/productInfo/page", req.value)
+    .then((res) => {
+      res.data.rows = res.data.rows.map((item) => {
+        let data = classification.value.filter((filterItem) => filterItem.id === item.productClassifyId);
+        let productClassifyName = "";
+        if (data && data.length > 0) {
+          productClassifyName = data[0].label;
+        }
+        return {
+          ...item,
+          productClassifyName: productClassifyName,
+        };
+      });
+      listData.value = type === "refresh" ? res.data.rows : listData.value.concat(res.data.rows);
+      if (req.value.pageNum * 10 >= res.data.total) {
+        finished.value = true;
+      }
+      req.value.pageNum++;
+      loading.value = false;
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>