瀏覽代碼

jxst售后管理库存查询

cz 1 年之前
父節點
當前提交
7e2d3816d5

+ 68 - 0
src/components/ShowFormData.vue

@@ -0,0 +1,68 @@
+<template>
+  <div class="box" @click="handleClickItem(showMore)">
+    <div class="content">
+      <div v-for="j in config" :key="j.prop" class="row">
+        <div class="left">{{ j.label }}</div>
+        <div class="right">
+          {{ data[j.prop] }}
+        </div>
+      </div>
+    </div>
+    <div class="more" v-if="showMore">
+      <van-icon name="arrow" />
+    </div>
+  </div>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted, defineProps } from "vue";
+const proxy = getCurrentInstance().proxy;
+defineProps({
+  showMore: {
+    type: Boolean,
+    default: false,
+  },
+  data: {
+    type: Object,
+    default: {},
+  },
+  config: {
+    type: Object,
+    default: [],
+  },
+});
+
+const handleClickItem = (showMore) => {
+  if (showMore) {
+    proxy.$emit("onClickItem", "ss");
+  }
+};
+</script>
+<style lang="scss" scope>
+.box {
+  width: 100%;
+  display: flex;
+  align-items: center;
+  // border-bottom: 1px solid #999999;
+  // justify-content: space-between;
+  .content {
+    flex: 1;
+    .row {
+      display: flex;
+      line-height: 24px;
+      .left {
+        text-align: right;
+        min-width: 60px;
+        color: #999999;
+      }
+      .right {
+        flex: 1;
+        padding-left: 15px;
+      }
+    }
+  }
+  .more {
+    width: 30px;
+    text-align: center;
+  }
+}
+</style>

+ 16 - 9
src/components/testForm/index.vue

@@ -33,6 +33,9 @@
             :readonly="getFieldReadonly(i)"
             :rules="getRules(i.prop)"
             :required="getRequired(i.prop)"
+            :right-icon="i.isNeedRightBtn ? i.rightIcon : ''"
+            @click-right-icon="i.isNeedRightBtn ? i.rightIconClick() : () => {}"
+            @blur="i.isNeedBlurMethon ? i.blurMethon(formData[i.prop]) : () => {}"
           >
           </van-field>
           <!-- switch -->
@@ -217,7 +220,12 @@
             />
           </van-popup>
           <!-- 文件上传 -->
-          <van-field name="uploader" v-if="i.type == 'upload'" :label="i.label">
+          <van-field
+            name="uploader"
+            v-if="i.type == 'upload'"
+            :label="i.label"
+            :readonly="i.readonly ? true : false"
+          >
             <template #input>
               <van-uploader
                 v-model="formData[i.prop]"
@@ -237,7 +245,7 @@
             :required="getRequired(i.prop)"
           >
             <template #input>
-              <div>
+              <div style="width: 100%">
                 <slot :name="i.slotName"> {{ i.slotName }}插槽占位符 </slot>
               </div>
             </template>
@@ -255,7 +263,7 @@
           <van-button
             plain
             type="primary"
-            @click="handleRemove(index,item)"
+            @click="handleRemove(index, item)"
             size="mini"
             style="border: none; background: #ecebeb"
             v-if="
@@ -725,14 +733,13 @@ const handlePush = () => {
   }
 };
 // remove
-const handleRemove = (index,item) => {
-  console.log(item)
-  if(item.deleteFn) {
-    item.deleteFn(index,item)
-  }else{
+const handleRemove = (index, item) => {
+  console.log(item);
+  if (item.deleteFn) {
+    item.deleteFn(index, item);
+  } else {
     formData.value[btnConfigCopy.prop].splice(index, 1);
   }
-  
 };
 // 拉去城市最近数据及处理
 const getAreaInfo = (selectedOptions, item, index) => {

+ 30 - 0
src/router/jxskRouter.js

@@ -10,6 +10,26 @@ export function jxskRouter() {
       component: () => import("../views/JXSK/salesContract/add.vue"),
     },
     {
+      path: "jxskAfterSales",
+      name: "jxsk_售后管理",
+      component: () => import("../views/JXSK/afterSales/index.vue"),
+    },
+    {
+      path: "jxskAfterSalesAdd",
+      name: "jxsk_售后管理添加",
+      component: () => import("../views/JXSK/afterSales/add.vue"),
+    },
+    {
+      path: "jxskAfterSalesEdit",
+      name: "jxsk_售后管理编辑",
+      component: () => import("../views/JXSK/afterSales/edit.vue"),
+    },
+    {
+      path: "jxskAfterSalesEditItem",
+      name: "jxsk_售后管理编辑子项",
+      component: () => import("../views/JXSK/afterSales/editItem.vue"),
+    },
+    {
       path: "jxskTask",
       name: "jxsk_生产任务",
       component: () => import("../views/JXSK/mes/task/index.vue"),
@@ -39,6 +59,16 @@ export function jxskRouter() {
       name: "jxsk_任务接收添加",
       component: () => import("../views/JXSK/mes/receive/add.vue"),
     },
+    {
+      path: "jxskInventoryQuery",
+      name: "jxsk_库存查询",
+      component: () => import("../views/JXSK/inventoryQuery/index.vue"),
+    },
+    {
+      path: "jxskKuwei",
+      name: "jxsk_查看库位",
+      component: () => import("../views/JXSK/inventoryQuery/kuwei.vue"),
+    },
 
   ];
   return jxskRouter;

+ 224 - 0
src/views/JXSK/afterSales/add.vue

@@ -0,0 +1,224 @@
+<template>
+  <div class="form">
+    <van-nav-bar
+      title="售后管理"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+      @click-right="onClickRight"
+    >
+      <template #right>
+        <div v-show="isShowVideo">关闭摄像头</div>
+      </template>
+    </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>
+
+<script setup>
+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 { getUserInfo } from "@/utils/auth";
+import { BrowserMultiFormatReader } from "@zxing/library";
+const codeReader = new BrowserMultiFormatReader();
+const isShowVideo = ref(false);
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const formDom = ref(null);
+const formData = reactive({
+  data: {},
+});
+const rules = {
+  productSn: [{ required: true, message: "请输入设备SN" }],
+  afterSalesPersonId: [{ required: true, message: "请选择售后人员" }],
+  remark: [{ required: true, message: "请输入售后原因" }],
+};
+const formOption = reactive({
+  readonly: false, //用于控制整个表单是否只读
+  disabled: false,
+  labelAlign: "top",
+  scroll: true,
+  labelWidth: "62pk",
+  hiddenSubmitBtn: false,
+});
+const formConfig = reactive([
+  {
+    type: "input",
+    label: "设备SN",
+    prop: "productSn",
+    isNeedBlurMethon: true,
+    blurMethon: (val) => {
+      showScanData(val);
+    },
+    isNeedRightBtn: true,
+    rightIcon: "scan",
+    rightIconClick: () => {
+      handleScanCode();
+    },
+  },
+  {
+    type: "input",
+    label: "合同编码",
+    prop: "code",
+    readonly: true,
+  },
+  {
+    type: "input",
+    label: "产品名称",
+    prop: "productName",
+    readonly: true,
+  },
+  {
+    type: "picker",
+    label: "售后人员",
+    prop: "afterSalesPersonId",
+    itemType: "onePicker",
+    showPicker: false,
+    fieldNames: {
+      text: "label",
+      value: "value",
+    },
+    data: [],
+  },
+  {
+    type: "input",
+    itemType: "textarea",
+    label: "售后原因",
+    prop: "remark",
+  },
+]);
+const onClickLeft = () => history.back();
+
+const getDict = () => {
+  proxy.get("/system/user/list?pageNum=1&pageSize=9999").then((res) => {
+    formConfig[3].data = res.rows.map((item) => {
+      return {
+        label: item.userName,
+        value: item.userId,
+      };
+    });
+  });
+};
+
+const getDetails = (id) => {
+  proxy.post("/salesContract/detail", { id }).then((res) => {
+    if (res.data && res.data.contractDetailsList.length > 0) {
+      res.data.salesContractDetailsList = res.data.contractDetailsList;
+    } else {
+      res.data.salesContractDetailsList = [];
+    }
+    formData.data = res.data;
+  });
+};
+
+onMounted(() => {
+  formData.data.afterSalesPersonId = getUserInfo().userId;
+  getDict();
+  if (route.query.id) {
+    getDetails(route.query.id);
+  }
+});
+
+const onSubmit = () => {
+  proxy.post("/afterSalesRecord/add", formData.data).then(
+    () => {
+      showSuccessToast("操作成功");
+      setTimeout(() => {
+        onClickLeft();
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+
+const showScanData = (val) => {
+  proxy.post("/productionTaskDetail/snInfo", { productSn: val }).then((res) => {
+    if (res.data && res.data.productId) {
+      formData.data.productId = res.data.productId;
+      formData.data.code = res.data.code;
+      formData.data.productName = res.data.productName;
+    }
+  });
+};
+
+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 = false;
+      }
+    }
+  );
+};
+
+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, "错误");
+    });
+};
+
+const onClickRight = () => {
+  codeReader.reset();
+  isShowVideo.value = false;
+};
+</script>
+<style lang="scss" scoped>
+.form {
+  margin-bottom: 60px;
+}
+.scan-video {
+  width: 100vw;
+  position: absolute;
+  z-index: 1000;
+  top: 60px;
+}
+</style>

+ 212 - 0
src/views/JXSK/afterSales/edit.vue

@@ -0,0 +1,212 @@
+<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"
+    >
+      <template #top>
+        <div style="width: 100%">
+          <ShowFormData :data="formData.data" :config="topConfig">
+          </ShowFormData>
+        </div>
+      </template>
+
+      <template #list>
+        <div style="width: 100%">
+          <div
+            v-for="(item, index) in formData.data.bomDetailList"
+            :key="index"
+          >
+            <ShowFormData
+              :data="item"
+              :config="listConfig"
+              :showMore="
+                item.afterSalesRecordDetail &&
+                item.afterSalesRecordDetail.length > 0
+                  ? true
+                  : false
+              "
+              @onClickItem="handleClickItem(item)"
+            >
+            </ShowFormData>
+          </div>
+        </div>
+      </template>
+    </testForm>
+  </div>
+</template>
+
+<script setup>
+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 ShowFormData from "@/components/ShowFormData.vue";
+
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const formDom = ref(null);
+const formData = reactive({
+  data: {},
+});
+const rules = {
+  customerId: [{ required: true, message: "请选择客户名称" }],
+};
+const formOption = reactive({
+  readonly: false, //用于控制整个表单是否只读
+  disabled: false,
+  labelAlign: "top",
+  scroll: true,
+  labelWidth: "62pk",
+  hiddenSubmitBtn: false,
+});
+const formConfig = reactive([
+  {
+    type: "slot",
+    slotName: "top",
+  },
+  {
+    type: "title",
+    title: "原配件清单",
+  },
+  {
+    type: "slot",
+    slotName: "list",
+  },
+  {
+    type: "title",
+    title: "程序文件",
+  },
+  {
+    type: "upload",
+    label: " ",
+    readonly: true,
+    prop: "fileList",
+  },
+]);
+
+const topConfig = ref([
+  {
+    label: "售后编码",
+    prop: "code",
+  },
+  {
+    label: "产品名称",
+    prop: "productName",
+  },
+  {
+    label: "产品SN",
+    prop: "productSn",
+  },
+]);
+
+const listConfig = ref([
+  {
+    label: "配件名称",
+    prop: "productName",
+  },
+  {
+    label: "数量",
+    prop: "quantity",
+  },
+]);
+
+const onClickLeft = () => history.back();
+
+const getDetails = (id) => {
+  proxy.post("/afterSalesRecord/detail", { id }).then((res) => {
+    formData.data = res.data;
+    const obj = JSON.parse(window.localStorage.getItem("jxstAfterSalesData"));
+    for (let i = 0; i < formData.data.bomDetailList.length; i++) {
+      const e = formData.data.bomDetailList[i];
+      if (e.afterSalesRecordDetail && e.afterSalesRecordDetail.length > 0) {
+        e.productName = e.productName + " (售后)";
+      }
+      for (const key in obj) {
+        if (e.id === key) {
+          e.accessoriesId = key;
+          e.remark = obj[key].remark;
+          e.fileList = obj[key].fileList;
+        }
+      }
+    }
+    if (res.data.bomInfoId) {
+      proxy
+        .post("/fileInfo/getList", { businessIdList: [res.data.bomInfoId] })
+        .then((file) => {
+          formData.data.fileList = file.data[res.data.bomInfoId].map((x) => ({
+            ...x,
+            url: x.fileUrl,
+          }));
+        });
+    }
+  });
+};
+
+onMounted(() => {
+  if (route.query.id) {
+    getDetails(route.query.id);
+    if (route.query.status == 1) {
+      formOption.hiddenSubmitBtn = true; //隐藏提交按钮
+    }
+  }
+});
+
+const onSubmit = () => {
+  proxy
+    .post("/afterSalesRecord/afterSales", {
+      id: formData.data.id,
+      afterSalesRecordDetailList: formData.data.bomDetailList.map((x) => ({
+        accessoriesId: x.accessoriesId,
+        remark: x.remark,
+        fileList: x.fileList,
+      })),
+    })
+    .then(
+      () => {
+        showSuccessToast("操作成功");
+        setTimeout(() => {
+          onClickLeft();
+        }, 500);
+      },
+      (err) => {
+        return showFailToast(err.message);
+      }
+    );
+};
+
+const handleClickItem = (item) => {
+  if (item.afterSalesRecordDetail && item.afterSalesRecordDetail.length > 0) {
+    proxy.$router.push({
+      path: "jxskAfterSalesEditItem",
+      query: {
+        data: JSON.stringify({
+          bomDetailList: [item],
+          code: formData.data.code,
+          productName: formData.data.productName,
+          productSn: formData.data.productSn,
+          remark: item.remark,
+          fileList: item.fileList,
+          status: route.query.status,
+        }),
+      },
+    });
+  }
+};
+</script>
+<style lang="scss" scoped>
+.form {
+  margin-bottom: 60px;
+}
+</style>

+ 163 - 0
src/views/JXSK/afterSales/editItem.vue

@@ -0,0 +1,163 @@
+<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"
+    >
+      <template #top>
+        <div style="width: 100%">
+          <ShowFormData :data="formData.data" :config="topConfig">
+          </ShowFormData>
+        </div>
+      </template>
+
+      <template #list>
+        <div style="width: 100%">
+          <div
+            v-for="(item, index) in formData.data.bomDetailList"
+            :key="index"
+          >
+            <ShowFormData :data="item" :config="listConfig"> </ShowFormData>
+          </div>
+        </div>
+      </template>
+    </testForm>
+  </div>
+</template>
+
+<script setup>
+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 ShowFormData from "@/components/ShowFormData.vue";
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const formDom = ref(null);
+const formData = reactive({
+  data: {},
+});
+const rules = {
+  remark: [{ required: true, message: "请输入售后记录" }],
+};
+const formOption = reactive({
+  readonly: false, //用于控制整个表单是否只读
+  disabled: false,
+  labelAlign: "top",
+  scroll: true,
+  labelWidth: "62pk",
+  hiddenSubmitBtn: false,
+  submitBtnText: "保存",
+});
+const formConfig = reactive([
+  {
+    type: "slot",
+    slotName: "top",
+  },
+  {
+    type: "title",
+    title: "原配件清单",
+  },
+  {
+    type: "slot",
+    slotName: "list",
+  },
+  {
+    type: "title",
+    title: "售后记录",
+  },
+  {
+    type: "input",
+    itemType: "textarea",
+    label: "售后记录",
+    prop: "remark",
+  },
+  {
+    type: "upload",
+    label: "现场照片",
+    prop: "fileList",
+  },
+]);
+
+const topConfig = ref([
+  {
+    label: "售后编码",
+    prop: "code",
+  },
+  {
+    label: "产品名称",
+    prop: "productName",
+  },
+  {
+    label: "产品SN",
+    prop: "productSn",
+  },
+]);
+const listConfig = ref([
+  {
+    label: "配件名称",
+    prop: "productName",
+  },
+  {
+    label: "数量",
+    prop: "quantity",
+  },
+]);
+const onClickLeft = () => history.back();
+const getDetails = (id) => {
+  proxy.post("/salesContract/detail", { id }).then((res) => {
+    if (res.data && res.data.contractDetailsList.length > 0) {
+      res.data.salesContractDetailsList = res.data.contractDetailsList;
+    } else {
+      res.data.salesContractDetailsList = [];
+    }
+    formData.data = res.data;
+  });
+};
+onMounted(() => {
+  if (route.query) {
+    formData.data = JSON.parse(route.query.data);
+    if (formData.data.status == 1) {
+      formOption.hiddenSubmitBtn = true;
+    }
+  }
+});
+const onSubmit = () => {
+  if (formData.data.fileList && formData.data.fileList.length > 0) {
+    const obj = JSON.parse(window.localStorage.getItem("jxstAfterSalesData"));
+    const key = formData.data.bomDetailList[0].id;
+    window.localStorage.setItem(
+      "jxstAfterSalesData",
+      JSON.stringify({
+        ...obj,
+        [key]: {
+          accessoriesId: key,
+          remark: formData.data.remark,
+          fileList: formData.data.fileList,
+        },
+      })
+    );
+    onClickLeft();
+  } else {
+    return showFailToast("请上传现场照片");
+  }
+
+  // onClickLeft();
+};
+</script>
+<style lang="scss" scoped>
+.form {
+  margin-bottom: 60px;
+}
+</style>

+ 125 - 0
src/views/JXSK/afterSales/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="没有更多了"
+        :offset="300"
+        @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: "1",
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+const listConfig = ref([
+  {
+    label: "售后编码",
+    prop: "code",
+  },
+  {
+    label: "产品名称",
+    prop: "productName",
+  },
+  {
+    label: "产品SN",
+    prop: "productSn",
+  },
+  {
+    label: "售后状态",
+    prop: "statusName",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+const onClickLeft = () => proxy.$router.push("/main/working");
+const onClickRight = () => {
+  proxy.$router.push({
+    path: "jxskAfterSalesAdd",
+    query: {
+      type: "add",
+    },
+  });
+};
+
+const toDtl = (row) => {
+  window.localStorage.setItem("jxstAfterSalesData", JSON.stringify({}));
+  proxy.$router.push({
+    path: "jxskAfterSalesEdit",
+    query: {
+      id: row.id,
+      status: row.status,
+    },
+  });
+};
+
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/afterSalesRecord/page", req.value)
+    .then((res) => {
+      res.data.rows = res.data.rows.map((x) => ({
+        ...x,
+        statusName: x.status ? "处理完成" : "处理中",
+      }));
+      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>

+ 166 - 0
src/views/JXSK/inventoryQuery/index.vue

@@ -0,0 +1,166 @@
+<template>
+  <van-nav-bar
+    title="库存查询"
+    left-text=""
+    left-arrow
+    @click-left="onClickLeft"
+  >
+  </van-nav-bar>
+  <van-search
+    v-model="req.keyword"
+    placeholder="请输入关键词"
+    @search="onRefresh"
+  />
+  <van-tabs v-model:active="active" @change="handleChangeTab">
+    <van-tab title="全部" name="all"></van-tab>
+    <van-tab
+      v-for="(item, index) in warehouseData"
+      :title="item.name"
+      :name="item.id"
+    >
+    </van-tab>
+  </van-tabs>
+  <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 v-show="active !== 'all'">
+        <van-button class="btn" @click="handleLook">查看库位</van-button>
+      </div>
+    </div>
+  </van-pull-refresh>
+</template>
+<script setup>
+import { ref, getCurrentInstance, onMounted } 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,
+  id: "",
+  keyword: null,
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+const warehouseData = ref([]);
+
+const active = ref("all");
+let currentData = ref({});
+const listConfig = ref([
+  {
+    label: "物品分类",
+    prop: "productClassifyName",
+  },
+  {
+    label: "物品名称",
+    prop: "productName",
+  },
+  {
+    label: "库存数量",
+    prop: "quantity",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  getList();
+};
+
+const onClickLeft = () => proxy.$router.push("/main/working");
+
+const onClickRight = () => {
+  proxy.$router.push("/main/manualInboundAdd");
+};
+
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "outInList",
+    query: {
+      productId: row.productId,
+      warehouseId: row.warehouseId,
+    },
+  });
+};
+const handleLook = () => {
+  proxy.$router.push({
+    path: "jxskKuwei",
+    query: {
+      warehouseId: active.value,
+      name: currentData.value.name,
+      keeperName: currentData.value.keeperName,
+    },
+  });
+};
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/stock/page", req.value)
+    .then((res) => {
+      res.data.rows.map((item) => {
+        item.type = item.type === 1 ? "产品" : "物料";
+      });
+      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;
+      console.log(listData.value, "wssa");
+    })
+    .catch((err) => {
+      loading.value = false;
+    });
+};
+
+const getWarehouseData = () => {
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+    warehouseData.value = res.data.rows;
+  });
+};
+
+const handleChangeTab = () => {
+  const current = warehouseData.value.find((x) => x.id === active.value);
+  if (current) {
+    currentData.value = current;
+  }
+  req.value.id = active.value === "all" ? "" : active.value;
+  req.value.pageNum = 1;
+  listData.value = [];
+  getList();
+};
+getWarehouseData();
+getList();
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+.btn {
+  color: #fff;
+  background-color: #ff8800;
+  width: calc(100% - 30px);
+  margin: 0 15px;
+  // position: fixed;
+  // bottom: 60px;
+}
+</style>

+ 107 - 0
src/views/JXSK/inventoryQuery/kuwei.vue

@@ -0,0 +1,107 @@
+<template>
+  <div class="form">
+    <van-nav-bar
+      title="库存查询"
+      left-text="返回"
+      left-arrow
+      @click-left="onClickLeft"
+    >
+    </van-nav-bar>
+    <div style="width: 100%; background: #fff">
+      <div style="border-bottom: 1px solid #999999; padding: 10px 10px">
+        <ShowFormData :data="formData.data" :config="topConfig"> </ShowFormData>
+      </div>
+      <div v-for="(item, index) in formData.data.list" :key="index">
+        <div>
+          <div class="_title" style="padding: 0px 10px">
+            库位 {{ item.name }}
+          </div>
+          <div
+            v-for="(i, j) in item.productInfoList"
+            :key="j"
+            style="border-bottom: 1px solid #999999; padding: 10px 10px"
+          >
+            <ShowFormData :data="i" :config="listConfig"> </ShowFormData>
+          </div>
+        </div>
+      </div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+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 ShowFormData from "@/components/ShowFormData.vue";
+const proxy = getCurrentInstance().proxy;
+const route = useRoute();
+const formDom = ref(null);
+const formData = reactive({
+  data: {},
+});
+const rules = {};
+const formOption = reactive({
+  readonly: false, //用于控制整个表单是否只读
+  disabled: false,
+  labelAlign: "top",
+  scroll: true,
+  labelWidth: "62pk",
+  hiddenSubmitBtn: false,
+  submitBtnText: "保存",
+});
+const formConfig = reactive([
+  {
+    type: "slot",
+    slotName: "top",
+  },
+  {
+    type: "slot",
+    slotName: "list",
+  },
+]);
+
+const topConfig = ref([
+  {
+    label: "仓库名称",
+    prop: "name",
+  },
+  {
+    label: "仓管员",
+    prop: "keeperName",
+  },
+]);
+const listConfig = ref([
+  {
+    label: "物品分类",
+    prop: "productClassifyName",
+  },
+  {
+    label: "物品名称",
+    prop: "name",
+  },
+]);
+const onClickLeft = () => history.back();
+const getDetails = (id) => {
+  proxy.post("/warehouseLocationInfo/list", { warehouseId: id }).then((res) => {
+    formData.data.list = res.data;
+  });
+};
+onMounted(() => {
+  if (route.query.warehouseId) {
+    getDetails(route.query.warehouseId);
+    formData.data = route.query;
+  }
+});
+</script>
+<style lang="scss" scoped>
+.form {
+  margin-bottom: 60px;
+}
+._title {
+  font-size: 14px;
+  font-weight: 700;
+  margin: 5px 0;
+}
+</style>

+ 7 - 1
src/views/purchase-sales/inbound-outbound/manualInbound/add.vue

@@ -5,7 +5,9 @@
       left-text="返回"
       left-arrow
       @click-left="onClickLeft"
+      @click-right="onClickRight"
     >
+      <template #right> <div v-show="isShowVideo">关闭摄像头</div> </template>
     </van-nav-bar>
     <testForm
       v-model="formData.data"
@@ -179,7 +181,7 @@ const decodeFromInputVideoFunc = (firstDeviceId) => {
       }
       if (err && !err) {
         console.error(err);
-        isShowVideo.value = true;
+        isShowVideo.value = false;
       }
     }
   );
@@ -209,6 +211,10 @@ const handleScanCode = () => {
       console.error(err, "错误");
     });
 };
+const onClickRight = () => {
+  codeReader.reset();
+  isShowVideo.value = false;
+};
 </script>
 <style lang="scss" scoped>
 .scan-video {

+ 7 - 1
src/views/purchase-sales/inbound-outbound/manualOutbound/add.vue

@@ -5,7 +5,9 @@
       left-text="返回"
       left-arrow
       @click-left="onClickLeft"
+      @click-right="onClickRight"
     >
+      <template #right> <div v-show="isShowVideo">关闭摄像头</div> </template>
     </van-nav-bar>
     <testForm
       v-model="formData.data"
@@ -178,7 +180,7 @@ const decodeFromInputVideoFunc = (firstDeviceId) => {
       }
       if (err && !err) {
         console.error(err);
-        isShowVideo.value = true;
+        isShowVideo.value = false;
       }
     }
   );
@@ -208,6 +210,10 @@ const handleScanCode = () => {
       console.error(err, "错误");
     });
 };
+const onClickRight = () => {
+  codeReader.reset();
+  isShowVideo.value = false;
+};
 </script>
 <style lang="scss" scoped>
 .scan-video {

+ 5 - 6
src/views/purchase-sales/inventory-management/inventoryQuery/index.vue

@@ -57,8 +57,8 @@ const warehouseData = ref([]);
 const active = ref("all");
 const listConfig = ref([
   {
-    label: "物品类",
-    prop: "type",
+    label: "物品类",
+    prop: "productClassifyName",
   },
   {
     label: "物品名称",
@@ -94,15 +94,14 @@ const toDtl = (row) => {
   });
 };
 
-
 const getList = (type) => {
   loading.value = true;
   proxy
     .post("/stock/page", req.value)
     .then((res) => {
-      res.data.rows.map(item => {
-        item.type = item.type === 1 ? '产品' : '物料'
-      })
+      res.data.rows.map((item) => {
+        item.type = item.type === 1 ? "产品" : "物料";
+      });
       listData.value =
         type === "refresh"
           ? res.data.rows