Browse Source

扫码功能

cz 1 year ago
parent
commit
8a0fb6ddd7

+ 18 - 0
src/components/testForm/index.vue

@@ -297,6 +297,23 @@
             :rules="getRules(i.prop)"
             :required="getRequired(i.prop)"
           >
+            <template #input v-if="i.isShowScanCode">
+              <div style="display: flex; height: 24px">
+                <div style="width: calc(100vw - 100px)">
+                  {{ formData[btnConfigCopy.prop][index][i.prop + "Name"] }}
+                </div>
+                <div style="width: 100px; float: right; margin-top: -20px">
+                  <van-button
+                    plain
+                    type="primary"
+                    @click.native.stop="i.scanCode(index)"
+                    size="mini"
+                    style="border: none"
+                    >扫码</van-button
+                  >
+                </div>
+              </div>
+            </template>
           </van-field>
           <!-- 时间选择器 -->
           <van-field
@@ -883,6 +900,7 @@ watch(
     if (
       formOption.value.btnConfig !== undefined &&
       !formOption.value.btnConfig.isNeed &&
+      val &&
       val.length > 0
     ) {
       formDataListShowLabel();

+ 42 - 23
src/views/JXSK/mes/forward/add.vue

@@ -36,9 +36,7 @@ const formData = reactive({
   },
 });
 const rules = {
-  warehouseName: [{ required: true, message: "仓库名称不能为空" }],
-  productName: [{ required: true, message: "物品名称不能为空" }],
-  quantity: [{ required: true, message: "入库数量不能为空" }],
+  receivedUserId: [{ required: true, message: "请选择负责人" }],
 };
 const formOption = reactive({
   readonly: false, //用于控制整个表单是否只读
@@ -70,17 +68,37 @@ const getDict = () => {
 
 const onClickLeft = () => history.back();
 const onSubmit = () => {
-  proxy.post("/productionTask/add", formData.data).then(
-    (res) => {
-      setTimeout(() => {
-        showSuccessToast("添加成功");
-        proxy.$router.push("/main/task");
-      }, 500);
-    },
-    (err) => {
-      return showFailToast(err.message);
-    }
-  );
+  if (route.query.type === "10") {
+    const data = {
+      id: formData.data.id,
+      receivedUserId: formData.data.receivedUserId,
+    };
+    proxy.post("/productionTaskDetail/circulation", data).then(
+      (res) => {
+        setTimeout(() => {
+          showSuccessToast("操作成功");
+          proxy.$router.push("/main/jxskForward");
+        }, 500);
+      },
+      (err) => {
+        return showFailToast(err.message);
+      }
+    );
+  } else {
+    proxy
+      .post("/productionTaskDetail/productStorage", { id: formData.data.id })
+      .then(
+        (res) => {
+          setTimeout(() => {
+            showSuccessToast("操作成功");
+            proxy.$router.push("/main/jxskForward");
+          }, 500);
+        },
+        (err) => {
+          return showFailToast(err.message);
+        }
+      );
+  }
 };
 const getDetails = () => {
   proxy.post("/productionTask/detail", { id: route.query.id }).then(
@@ -98,21 +116,21 @@ const configData = [
       type: "input",
       itemType: "text",
       label: "产品名称",
-      prop: "reamlke",
+      prop: "productName",
       readonly: true,
     },
     {
       type: "input",
       itemType: "text",
       label: "产品SN",
-      prop: "reamlke",
+      prop: "productSn",
       readonly: true,
     },
     {
       type: "input",
       itemType: "text",
       label: "当前工序",
-      prop: "reamlke",
+      prop: "productionProcessesName",
       readonly: true,
     },
     {
@@ -128,13 +146,13 @@ const configData = [
       type: "input",
       itemType: "text",
       label: "目标工序",
-      prop: "reamlke",
+      prop: "nextProductionProcessesName",
       readonly: true,
     },
     {
       type: "picker",
       label: "负责人",
-      prop: "warehouseId",
+      prop: "receivedUserId",
       itemType: "onePicker",
       showPicker: false,
       fieldNames: {
@@ -149,21 +167,21 @@ const configData = [
       type: "input",
       itemType: "text",
       label: "产品名称",
-      prop: "reamlke",
+      prop: "productName",
       readonly: true,
     },
     {
       type: "input",
       itemType: "text",
       label: "产品SN",
-      prop: "reamlke",
+      prop: "productSn",
       readonly: true,
     },
     {
       type: "input",
       itemType: "text",
       label: "当前工序",
-      prop: "reamlke",
+      prop: "productionProcessesName",
       readonly: true,
     },
     {
@@ -179,9 +197,10 @@ onMounted(() => {
     formOption.submitBtnText = "提交";
     getDict();
   } else {
-    formConfig.value = configData[0];
+    formConfig.value = configData[1];
     formOption.submitBtnText = "提交入库";
   }
+  formData.data = { ...route.query };
 });
 </script>
 <style lang="scss" scoped>

+ 17 - 10
src/views/JXSK/mes/forward/index.vue

@@ -5,7 +5,6 @@
       left-text=""
       left-arrow
       @click-left="onClickLeft"
-      @click-right="onClickRight"
     >
       <!-- <template #right> 添加 </template> -->
     </van-nav-bar>
@@ -57,11 +56,11 @@ const listConfig = ref([
 
   {
     label: "产品SN",
-    prop: "quantity",
+    prop: "productSn",
   },
   {
     label: "当前工序",
-    prop: "dueDate",
+    prop: "productionProcessesName",
   },
 ]);
 const onRefresh = () => {
@@ -75,16 +74,25 @@ const onLoad = () => {
 
 const onClickLeft = () => proxy.$router.push("/main/working");
 
-const onClickRight = () => {
-  proxy.$router.push("jxskForwardAdd");
-};
+// const onClickRight = () => {
+//   proxy.$router.push("jxskForwardAdd");
+// };
 
 const toDtl = (row) => {
+  let type = "";
+  if (
+    row.nextProductionProcessesId === "" ||
+    row.nextProductionProcessesId === -1
+  ) {
+    type = "20";
+  } else {
+    type = "10";
+  }
   proxy.$router.push({
     path: "jxskForwardAdd",
     query: {
-      id: row.id,
-      type: "20",
+      ...row,
+      type: type,
     },
   });
 };
@@ -92,9 +100,8 @@ const toDtl = (row) => {
 const getList = (type) => {
   loading.value = true;
   proxy
-    .post("/productionTask/page", req.value)
+    .post("/productionTaskDetail/circulationPage", req.value)
     .then((res) => {
-      res.data.rows = [{ aa: "sss" }];
       listData.value =
         type === "refresh"
           ? res.data.rows

+ 24 - 14
src/views/JXSK/mes/receive/add.vue

@@ -16,9 +16,6 @@
       @otherBtnClick="otherBtnClick"
       ref="formDom"
     >
-      <template #file>
-        <div>aa</div>
-      </template>
     </testForm>
   </div>
 </template>
@@ -47,6 +44,7 @@ const formOption = reactive({
   labelAlign: "top",
   scroll: true,
   labelWidth: "62pk",
+  submitBtnText: "确认接收",
   otherBtn: true,
   otherBtnText: "退回",
   btnConfig: {
@@ -63,37 +61,39 @@ const formConfig = reactive([
     type: "input",
     itemType: "text",
     label: "产品名称",
-    prop: "reamlke",
+    prop: "productionProcessesName",
     readonly: true,
   },
   {
     type: "input",
     itemType: "text",
     label: "产品SN",
-    prop: "reamlke",
+    prop: "productSn",
     readonly: true,
   },
   {
     type: "input",
     itemType: "text",
     label: "前道工序",
-    prop: "reamlke",
+    prop: "productionProcessesName",
     readonly: true,
   },
   {
-    type: "slot",
-    label: "工序图纸",
-    slotName: "file",
+    type: "input",
+    itemType: "text",
+    label: "流转入",
+    prop: "circulationUserName",
+    readonly: true,
   },
 ]);
 
 const onClickLeft = () => history.back();
 const onSubmit = () => {
-  proxy.post("/productionTask/add", formData.data).then(
+  proxy.post("/productionTaskDetail/receive", { id: formData.data.id }).then(
     (res) => {
       setTimeout(() => {
-        showSuccessToast("添加成功");
-        proxy.$router.push("/main/task");
+        showSuccessToast("操作成功");
+        proxy.$router.push("/main/jxskReceive");
       }, 500);
     },
     (err) => {
@@ -102,7 +102,17 @@ const onSubmit = () => {
   );
 };
 const otherBtnClick = () => {
-  console.log("aa");
+  proxy.post("/productionTaskDetail/rejection", { id: formData.data.id }).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast("操作成功");
+        proxy.$router.push("/main/jxskReceive");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
 };
 const getDetails = () => {
   proxy.post("/productionTask/detail", { id: route.query.id }).then(
@@ -116,7 +126,7 @@ const getDetails = () => {
 };
 onMounted(() => {
   if (route.query.id) {
-    getDetails();
+    formData.data = { ...route.query };
   }
 });
 </script>

+ 9 - 19
src/views/JXSK/mes/receive/index.vue

@@ -5,7 +5,6 @@
       left-text=""
       left-arrow
       @click-left="onClickLeft"
-      @click-right="onClickRight"
     >
       <!-- <template #right> 添加 </template> -->
     </van-nav-bar>
@@ -51,25 +50,17 @@ const listData = ref([]);
 
 const listConfig = ref([
   {
-    label: "任务编码",
-    prop: "code",
-  },
-  {
     label: "产品名称",
     prop: "productName",
   },
 
   {
-    label: "任务数量",
-    prop: "quantity",
+    label: "产品SN",
+    prop: "productSn",
   },
   {
-    label: "完成期限",
-    prop: "dueDate",
-  },
-  {
-    label: "负责人",
-    prop: "personLiableName",
+    label: "前道工序",
+    prop: "productionProcessesName",
   },
 ]);
 const onRefresh = () => {
@@ -83,15 +74,15 @@ const onLoad = () => {
 
 const onClickLeft = () => proxy.$router.push("/main/working");
 
-const onClickRight = () => {
-  proxy.$router.push("/main/jxskTaskAdd");
-};
+// const onClickRight = () => {
+//   proxy.$router.push("/main/jxskTaskAdd");
+// };
 
 const toDtl = (row) => {
   proxy.$router.push({
     path: "jxskReceiveAdd",
     query: {
-      id: row.id,
+      ...row,
     },
   });
 };
@@ -99,9 +90,8 @@ const toDtl = (row) => {
 const getList = (type) => {
   loading.value = true;
   proxy
-    .post("/productionTask/page", req.value)
+    .post("/productionTaskDetail/receivePage", req.value)
     .then((res) => {
-      res.data.rows = [{}];
       listData.value =
         type === "refresh"
           ? res.data.rows

+ 105 - 12
src/views/purchase-sales/inbound-outbound/manualInbound/add.vue

@@ -1,7 +1,27 @@
 <template>
   <div class="form">
-    <van-nav-bar title="手动入库" left-text="返回" left-arrow @click-left="onClickLeft"> </van-nav-bar>
-    <testForm v-model="formData.data" :formOption="formOption" :formConfig="formConfig" :rules="rules" @onSubmit="onSubmit" ref="formDom"></testForm>
+    <van-nav-bar
+      title="手动入库"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <testForm
+      v-model="formData.data"
+      :formOption="formOption"
+      :formConfig="formConfig"
+      :rules="rules"
+      @onSubmit="onSubmit"
+      ref="formDom"
+    ></testForm>
+    <video
+      ref="video"
+      id="video"
+      class="scan-video"
+      autoplay
+      v-show="isShowVideo"
+    ></video>
   </div>
 </template>
 
@@ -10,10 +30,14 @@ import { ref, reactive, getCurrentInstance, onMounted } from "vue";
 import { showSuccessToast, showFailToast } from "vant";
 import { useRoute } from "vue-router";
 import testForm from "@/components/testForm/index.vue";
-
+import { BrowserMultiFormatReader } from "@zxing/library";
+const codeReader = new BrowserMultiFormatReader();
 const proxy = getCurrentInstance().proxy;
 const route = useRoute();
 const formDom = ref(null);
+const isShowVideo = ref(false);
+const scanIndex = ref(-1);
+const productData = ref([]);
 const formData = reactive({
   data: {
     warehouseId: "",
@@ -22,8 +46,8 @@ const formData = reactive({
   },
 });
 const rules = {
-  warehouseName: [{ required: true, message: "仓库名称不能为空" }],
-  productName: [{ required: true, message: "物品名称不能为空" }],
+  warehouseId: [{ required: true, message: "仓库名称不能为空" }],
+  productId: [{ required: true, message: "物品名称不能为空" }],
   quantity: [{ required: true, message: "入库数量不能为空" }],
 };
 const formOption = reactive({
@@ -50,6 +74,11 @@ const formOption = reactive({
           value: "id",
         },
         data: [],
+        isShowScanCode: true,
+        scanCode: (index) => {
+          scanIndex.value = index;
+          handleScanCode();
+        },
       },
       {
         type: "input",
@@ -92,12 +121,17 @@ const formConfig = reactive([
 ]);
 const onClickLeft = () => history.back();
 const getDict = async () => {
-  await proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
-    formConfig[0].data = res.data.rows;
-  });
-  await proxy.post("/productInfo/page", { pageNum: 1, pageSize: 9999, definition: "" }).then((res) => {
-    formOption.btnConfig.listConfig[0].data = res.data.rows;
-  });
+  await proxy
+    .post("/warehouse/page", { pageNum: 1, pageSize: 9999 })
+    .then((res) => {
+      formConfig[0].data = res.data.rows;
+    });
+  await proxy
+    .post("/productInfo/page", { pageNum: 1, pageSize: 9999, definition: "" })
+    .then((res) => {
+      formOption.btnConfig.listConfig[0].data = res.data.rows;
+      productData.value = res.data.rows;
+    });
 };
 onMounted(async () => {
   await getDict();
@@ -123,5 +157,64 @@ const onSubmit = () => {
     }
   );
 };
+const showScanData = (id) => {
+  const current = productData.value.find((x) => x.id === id);
+  if (current) {
+    formData.data.list[scanIndex.value].productId = current.id;
+    formData.data.list[scanIndex.value].productIdName = current.name;
+  }
+};
+const decodeFromInputVideoFunc = (firstDeviceId) => {
+  codeReader.reset(); // 重置
+  isShowVideo.value = true;
+  codeReader.decodeFromInputVideoDeviceContinuously(
+    firstDeviceId,
+    "video",
+    (result, err) => {
+      if (result) {
+        codeReader.reset();
+        showSuccessToast("扫描成功");
+        isShowVideo.value = false;
+        showScanData(result.text);
+      }
+      if (err && !err) {
+        console.error(err);
+        isShowVideo.value = true;
+      }
+    }
+  );
+};
+
+const handleScanCode = () => {
+  codeReader
+    .getVideoInputDevices()
+    .then((videoInputDevices) => {
+      // 默认获取第一个摄像头设备id
+      let firstDeviceId = videoInputDevices[0].deviceId;
+      // 获取第一个摄像头设备的名称
+      const videoInputDeviceslablestr = JSON.stringify(
+        videoInputDevices[0].label
+      );
+      if (videoInputDevices.length > 1) {
+        // 判断是否后置摄像头
+        if (videoInputDeviceslablestr.indexOf("back") > -1) {
+          firstDeviceId = videoInputDevices[0].deviceId;
+        } else {
+          firstDeviceId = videoInputDevices[1].deviceId;
+        }
+      }
+      decodeFromInputVideoFunc(firstDeviceId);
+    })
+    .catch((err) => {
+      console.error(err, "错误");
+    });
+};
 </script>
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.scan-video {
+  width: 100vw;
+  position: absolute;
+  z-index: 1000;
+  top: 60px;
+}
+</style>

+ 105 - 12
src/views/purchase-sales/inbound-outbound/manualOutbound/add.vue

@@ -1,7 +1,27 @@
 <template>
   <div class="form">
-    <van-nav-bar title="手动出库" left-text="返回" left-arrow @click-left="onClickLeft"> </van-nav-bar>
-    <testForm v-model="formData.data" :formOption="formOption" :formConfig="formConfig" :rules="rules" @onSubmit="onSubmit" ref="formDom"></testForm>
+    <van-nav-bar
+      title="手动出库"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <testForm
+      v-model="formData.data"
+      :formOption="formOption"
+      :formConfig="formConfig"
+      :rules="rules"
+      @onSubmit="onSubmit"
+      ref="formDom"
+    ></testForm>
+    <video
+      ref="video"
+      id="video"
+      class="scan-video"
+      autoplay
+      v-show="isShowVideo"
+    ></video>
   </div>
 </template>
 
@@ -10,10 +30,14 @@ import { ref, reactive, getCurrentInstance, onMounted } from "vue";
 import { showSuccessToast, showFailToast } from "vant";
 import { useRoute } from "vue-router";
 import testForm from "@/components/testForm/index.vue";
-
+import { BrowserMultiFormatReader } from "@zxing/library";
+const codeReader = new BrowserMultiFormatReader();
 const proxy = getCurrentInstance().proxy;
 const route = useRoute();
 const formDom = ref(null);
+const isShowVideo = ref(false);
+const scanIndex = ref(-1);
+const productData = ref([]);
 const formData = reactive({
   data: {
     warehouseId: "",
@@ -22,8 +46,8 @@ const formData = reactive({
   },
 });
 const rules = {
-  warehouseName: [{ required: true, message: "仓库名称不能为空" }],
-  productName: [{ required: true, message: "物品名称不能为空" }],
+  warehouseId: [{ required: true, message: "仓库名称不能为空" }],
+  productId: [{ required: true, message: "物品名称不能为空" }],
   quantity: [{ required: true, message: "出库数量不能为空" }],
 };
 const formOption = reactive({
@@ -50,6 +74,11 @@ const formOption = reactive({
           value: "id",
         },
         data: [],
+        isShowScanCode: true,
+        scanCode: (index) => {
+          scanIndex.value = index;
+          handleScanCode();
+        },
       },
       {
         type: "input",
@@ -92,12 +121,17 @@ const formConfig = reactive([
 ]);
 const onClickLeft = () => history.back();
 const getDict = async () => {
-  await proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
-    formConfig[0].data = res.data.rows;
-  });
-  await proxy.post("/productInfo/page", { pageNum: 1, pageSize: 9999, definition: "" }).then((res) => {
-    formOption.btnConfig.listConfig[0].data = res.data.rows;
-  });
+  await proxy
+    .post("/warehouse/page", { pageNum: 1, pageSize: 9999 })
+    .then((res) => {
+      formConfig[0].data = res.data.rows;
+    });
+  await proxy
+    .post("/productInfo/page", { pageNum: 1, pageSize: 9999, definition: "" })
+    .then((res) => {
+      formOption.btnConfig.listConfig[0].data = res.data.rows;
+      productData.value = res.data.rows;
+    });
 };
 onMounted(async () => {
   await getDict();
@@ -122,5 +156,64 @@ const onSubmit = () => {
     }
   );
 };
+const showScanData = (id) => {
+  const current = productData.value.find((x) => x.id === id);
+  if (current) {
+    formData.data.list[scanIndex.value].productId = current.id;
+    formData.data.list[scanIndex.value].productIdName = current.name;
+  }
+};
+const decodeFromInputVideoFunc = (firstDeviceId) => {
+  codeReader.reset(); // 重置
+  isShowVideo.value = true;
+  codeReader.decodeFromInputVideoDeviceContinuously(
+    firstDeviceId,
+    "video",
+    (result, err) => {
+      if (result) {
+        codeReader.reset();
+        showSuccessToast("扫描成功");
+        isShowVideo.value = false;
+        showScanData(result.text);
+      }
+      if (err && !err) {
+        console.error(err);
+        isShowVideo.value = true;
+      }
+    }
+  );
+};
+
+const handleScanCode = () => {
+  codeReader
+    .getVideoInputDevices()
+    .then((videoInputDevices) => {
+      // 默认获取第一个摄像头设备id
+      let firstDeviceId = videoInputDevices[0].deviceId;
+      // 获取第一个摄像头设备的名称
+      const videoInputDeviceslablestr = JSON.stringify(
+        videoInputDevices[0].label
+      );
+      if (videoInputDevices.length > 1) {
+        // 判断是否后置摄像头
+        if (videoInputDeviceslablestr.indexOf("back") > -1) {
+          firstDeviceId = videoInputDevices[0].deviceId;
+        } else {
+          firstDeviceId = videoInputDevices[1].deviceId;
+        }
+      }
+      decodeFromInputVideoFunc(firstDeviceId);
+    })
+    .catch((err) => {
+      console.error(err, "错误");
+    });
+};
 </script>
-<style lang="scss" scoped></style>
+<style lang="scss" scoped>
+.scan-video {
+  width: 100vw;
+  position: absolute;
+  z-index: 1000;
+  top: 60px;
+}
+</style>