Browse Source

库存盘点、查询功能

cz 1 year ago
parent
commit
29429044eb

BIN
src.zip


+ 33 - 0
src/components/TitleInfo/index.vue

@@ -0,0 +1,33 @@
+<template>
+  <div style="background: #fff; padding-left: 10px;">
+    <div class="_title">
+      <div class="line"></div>
+      <div> {{ title }}</div>
+    </div>
+  </div>
+</template>
+
+<script setup>
+import { defineProps } from "vue";
+defineProps({
+  title: String,
+});
+</script>
+
+<style lang="scss" scoped>
+._title {
+  display: flex;
+  align-items: center;
+  font-size: 15px;
+  font-weight: 700;
+  line-height: 36px;
+  // border-bottom: 1px solid #000;
+
+  .line {
+    width: 4px;
+    background-color: #0084ff;
+    height: 15px;
+    margin-right: 8px;
+  }
+}
+</style>

+ 12 - 17
src/components/common-list.vue

@@ -1,30 +1,25 @@
 <template>
   <div class="common-list">
-    <ul>
+    <ul v-if="listData && listData.length>0">
       <li v-for="i in listData" :key="i.id">
         <div class="left-box" style="margin-right: 20px" v-if="isCheckbox">
-          <van-checkbox
-            v-model="i.checked"
-            icon-size="15px"
-            shape="square"
-            @change="listCheck"
-            :disabled="optionalValue ? optionalValue != i[optionalKey] : false"
-          ></van-checkbox>
+          <van-checkbox v-model="i.checked" icon-size="15px" shape="square" @change="listCheck"
+                        :disabled="optionalValue ? optionalValue != i[optionalKey] : false"></van-checkbox>
         </div>
-        <div
-          class="center-content"
-          style="line-height: 24px"
-          @click="listCk(i)"
-        >
+        <p>
+
+        </p>
+        <div class="center-content" style="line-height: 24px" @click="listCk(i)">
           <div v-for="j in config" :key="j.prop" style="display: flex">
-            <span style="width: 90px">{{ j.label }}:</span>
-            <span v-if="j.type && j.type === 'slot'" style="flex: 1">
+            <span style="min-width:80px;">{{ j.label }} <span v-if="j.label">:</span> </span>
+            <span v-if="j.type && j.type === 'slot'" style="flex: 1;">
               <slot :name="j.slotName" :row="i">
                 {{ j.slotName }}插槽占位符
               </slot>
             </span>
-            <span v-else style="flex: 1">
-              {{ i[j.prop] }}
+            <span v-else style="flex: 1;" :style="j.style?j.style:{}">
+              <span v-if="i[j.prop]!= undefined">{{ i[j.prop] }}</span>
+              <span v-else></span>
             </span>
           </div>
         </div>

+ 10 - 0
src/router/index.js

@@ -357,6 +357,16 @@ const routes = [{
 				component: () => import('../views/purchase-sales/inbound-outbound/waitInbound/add.vue')
 			},
 			{
+				path: 'manyGoods',
+				name: '多货登记',
+				component: () => import('../views/purchase-sales/inbound-outbound/waitInbound/manyGoods.vue')
+			},
+			{
+				path: 'selectGood',
+				name: '物品选择',
+				component: () => import('../views/purchase-sales/inbound-outbound/waitInbound/selectGood.vue')
+			},
+			{
 				path: 'waitOutbound',
 				name: '待出库',
 				component: () => import('../views/purchase-sales/inbound-outbound/waitOutbound/index.vue')

+ 23 - 0
src/store/manyGood.js

@@ -0,0 +1,23 @@
+import {
+  defineStore
+} from 'pinia'
+const useSelectGoodStore = defineStore(
+  'manyGood', {
+    state: () => ({
+      selectGood: [], //多货登记选择的物品
+    }),
+    actions: {
+      pushGood(row) {
+        this.selectGood.push({
+          productId: row.id,
+          productCode: row.customCode,
+          productName: row.name,
+          productSpec: row.spec,
+        })
+      },
+      clearGood() {
+        this.selectGood = []
+      }
+    }
+  })
+export default useSelectGoodStore

+ 160 - 161
src/views/main.vue

@@ -1,125 +1,124 @@
 <template>
-	<div class="main" id="main">
-		<!-- <KeepAlive>
+  <div class="main" id="main">
+    <!-- <KeepAlive>
 			<router-view />
     	</KeepAlive> -->
-		<router-view v-slot="{ Component, route }">
-			<keep-alive  include="working">
-				<component v-if="!route.meta.link" :is="Component" :key="route.fullPath"/>
-			</keep-alive>
-		</router-view>
-		
-	</div>
-	<van-tabbar v-model="tabType" v-if="routerName != '/main/processDtl'" :style="isIos() ? 'height:65px' : ''">
-		<van-tabbar-item to="/main/message" :badge="msgCount" :style="isIos() ? 'padding-bottom:15px' : ''">
-			{{$t('common.message')}}
-			<template #icon="props">
-				<i class="icon iconfont icon-btn_shengc_gray1 footer-icon" :class="props.active ? 'footer-icon-active' : ''"></i>
-			</template>
-		</van-tabbar-item>
-		<van-tabbar-item to="/main/working" :style="isIos() ? 'padding-bottom:15px' : ''">
-			{{$t('common.workbench')}}
-			<template #icon="props">
-				<i class="icon iconfont icon-btn_gongz footer-icon" :class="props.active ? 'footer-icon-active' : ''"></i>
-			</template>
-		</van-tabbar-item>
-		<van-tabbar-item
-			:style="isIos() ? 'padding-bottom:15px' : ''"
-			:to="tenantId == 'smt' ? '/main/xiamenList' : '/main/equipment'"
-			>{{$t('common.things')}}
-			<template #icon="props">
-				<i class="icon iconfont icon-btn_wulw footer-icon" :class="props.active ? 'footer-icon-active' : ''"></i>
-			</template>
-		</van-tabbar-item>
-		<van-tabbar-item icon="setting-o" to="/main/home" :style="isIos() ? 'padding-bottom:15px' : ''">
-			{{$t('common.mine')}}
-			<template #icon="props">
-				<i class="icon iconfont icon-btn_mine footer-icon" :class="props.active ? 'footer-icon-active' : ''"></i>
-			</template>
-		</van-tabbar-item>
-	</van-tabbar>
+    <router-view v-slot="{ Component, route }">
+      <keep-alive :include="['working','manyGoods']">
+        <component v-if="!route.meta.link" :is="Component" :key="route.fullPath" />
+      </keep-alive>
+    </router-view>
+
+  </div>
+  <van-tabbar v-model="tabType" v-if="routerName != '/main/processDtl'" :style="isIos() ? 'height:65px' : ''">
+    <van-tabbar-item to="/main/message" :badge="msgCount" :style="isIos() ? 'padding-bottom:15px' : ''">
+      {{$t('common.message')}}
+      <template #icon="props">
+        <i class="icon iconfont icon-btn_shengc_gray1 footer-icon" :class="props.active ? 'footer-icon-active' : ''"></i>
+      </template>
+    </van-tabbar-item>
+    <van-tabbar-item to="/main/working" :style="isIos() ? 'padding-bottom:15px' : ''">
+      {{$t('common.workbench')}}
+      <template #icon="props">
+        <i class="icon iconfont icon-btn_gongz footer-icon" :class="props.active ? 'footer-icon-active' : ''"></i>
+      </template>
+    </van-tabbar-item>
+    <van-tabbar-item :style="isIos() ? 'padding-bottom:15px' : ''"
+                     :to="tenantId == 'smt' ? '/main/xiamenList' : '/main/equipment'">{{$t('common.things')}}
+      <template #icon="props">
+        <i class="icon iconfont icon-btn_wulw footer-icon" :class="props.active ? 'footer-icon-active' : ''"></i>
+      </template>
+    </van-tabbar-item>
+    <van-tabbar-item icon="setting-o" to="/main/home" :style="isIos() ? 'padding-bottom:15px' : ''">
+      {{$t('common.mine')}}
+      <template #icon="props">
+        <i class="icon iconfont icon-btn_mine footer-icon" :class="props.active ? 'footer-icon-active' : ''"></i>
+      </template>
+    </van-tabbar-item>
+  </van-tabbar>
 </template>
 <script setup>
-import { ref, getCurrentInstance, watch } from 'vue'
-import { getUserInfo,getToken } from '@/utils/auth'
-import { useRouter } from 'vue-router'
-import { lang } from '@/lang/cn'
-import * as dd from 'dingtalk-jsapi'
-import '@/assets/icon/iconfont.css'
-import 'vant/lib/index.css'
-import axios from 'axios'
-import { uploadDdRightBtn } from '@/utils/ddAdapter'
-import { showDialog,showNotify } from 'vant'
-const tenantId = getUserInfo().tenantId
-const proxy = getCurrentInstance().proxy
-const tabType = ref('home')
-const msgCount = ref(0)
+import { ref, getCurrentInstance, watch } from "vue";
+import { getUserInfo, getToken } from "@/utils/auth";
+import { useRouter } from "vue-router";
+import { lang } from "@/lang/cn";
+import * as dd from "dingtalk-jsapi";
+import "@/assets/icon/iconfont.css";
+import "vant/lib/index.css";
+import axios from "axios";
+import { uploadDdRightBtn } from "@/utils/ddAdapter";
+import { showDialog, showNotify } from "vant";
+const tenantId = getUserInfo().tenantId;
+const proxy = getCurrentInstance().proxy;
+const tabType = ref("home");
+const msgCount = ref(0);
 const socketInit = () => {
-	window.ws = new WebSocket(
-		'ws://'+ process.env.VUE_APP_IP + process.env.VUE_APP_WS_API +'/webStock/' +
-			getToken()
-		// 'ws://192.168.1.97:8300/webStock/' + window.localStorage.getItem('token')
-	)
-	//申请一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,WebSocket协议的url使用ws://开头,另外安全的WebSocket协议使用wss://开头
-	window.ws.onopen = function () {
-		//当WebSocket创建成功时,触发onopen事件
-		console.log('open')
-	}
-	window.ws.onmessage = function (e) {
-		//当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据
-		//在data.value前面插入
-		const res = JSON.parse(e.data)
-		console.log(res)
-		
-		
-		if(res.type == 1) {
-			
-			if(res.list.length > 0) {
-				showDialog({
-					title: res.list[0].title,
-					message: res.list[0].businessData,
-				}).then(() => {
-					proxy.post('/pushInfo/read', {
-						idList: [res.list[0].id],
-					}).then((res) => {
-						if(res.code == 200) {
-							showNotify({ type: 'primary', message: '确认已读' });
-						}
-					})
-				})
-			}
-		}
-		if(res.type == 2) {
-			msgCount.value = res.count * 1
-		}
-		if(res.type == 3) {
-			// ElNotification({
-			// 	title: '提示',
-			// 	message: res.title,
-			// 	position: 'bottom-right',
-			// 	duration:0,
-			// })
-		}
-		
-	}
-	window.ws.onclose = function (e) {
-		//当客户端收到服务端发送的关闭连接请求时,触发onclose事件
-		console.log('close')
-	}
-	window.ws.onerror = function (e) {
-		//如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
-		console.log(e)
-	}
-}
-socketInit()
+  window.ws = new WebSocket(
+    "ws://" +
+      process.env.VUE_APP_IP +
+      process.env.VUE_APP_WS_API +
+      "/webStock/" +
+      getToken()
+    // 'ws://192.168.1.97:8300/webStock/' + window.localStorage.getItem('token')
+  );
+  //申请一个WebSocket对象,参数是服务端地址,同http协议使用http://开头一样,WebSocket协议的url使用ws://开头,另外安全的WebSocket协议使用wss://开头
+  window.ws.onopen = function () {
+    //当WebSocket创建成功时,触发onopen事件
+    console.log("open");
+  };
+  window.ws.onmessage = function (e) {
+    //当客户端收到服务端发来的消息时,触发onmessage事件,参数e.data包含server传递过来的数据
+    //在data.value前面插入
+    const res = JSON.parse(e.data);
+    console.log(res);
+
+    if (res.type == 1) {
+      if (res.list.length > 0) {
+        showDialog({
+          title: res.list[0].title,
+          message: res.list[0].businessData,
+        }).then(() => {
+          proxy
+            .post("/pushInfo/read", {
+              idList: [res.list[0].id],
+            })
+            .then((res) => {
+              if (res.code == 200) {
+                showNotify({ type: "primary", message: "确认已读" });
+              }
+            });
+        });
+      }
+    }
+    if (res.type == 2) {
+      msgCount.value = res.count * 1;
+    }
+    if (res.type == 3) {
+      // ElNotification({
+      // 	title: '提示',
+      // 	message: res.title,
+      // 	position: 'bottom-right',
+      // 	duration:0,
+      // })
+    }
+  };
+  window.ws.onclose = function (e) {
+    //当客户端收到服务端发送的关闭连接请求时,触发onclose事件
+    console.log("close");
+  };
+  window.ws.onerror = function (e) {
+    //如果出现连接、处理、接收、发送数据失败的时候触发onerror事件
+    console.log(e);
+  };
+};
+socketInit();
 
 //判断是否是ios系统
 const isIos = () => {
-	const u = navigator.userAgent
-	const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/) //ios终端
-	return isIOS
-}
-
+  const u = navigator.userAgent;
+  const isIOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端
+  return isIOS;
+};
 
 //判断是否为开发环境.如果是开发环境,则同步前后台中文配置表
 // const isDev = process.env.NODE_ENV === 'development'
@@ -137,67 +136,67 @@ const isIos = () => {
 // 		} catch (error) {}
 // 	}
 // }
-const corpId = window.localStorage.getItem('corpId')
-let routerName = ref(null)
+const corpId = window.localStorage.getItem("corpId");
+let routerName = ref(null);
 //监听路由变化
-const router = useRouter()
+const router = useRouter();
 //获取当前path
-routerName.value = router.currentRoute.value.path
+routerName.value = router.currentRoute.value.path;
 watch(router.currentRoute, (to, from) => {
-	routerName.value = to.path
-	console.log('routerName', routerName.value)
-	//滚动条回到顶部
-	document.documentElement.scrollTop = 0
-	if (!corpId) return
-	dd.biz.navigation.setTitle({
-		title: router.currentRoute.value.name,
-		onSuccess: function (result) {},
-		onFail: function (err) {},
-	})
-	//设置右侧按钮
-	proxy.uploadDdRightBtn(function () {}, ' ')
+  routerName.value = to.path;
+  console.log("routerName", routerName.value);
+  //滚动条回到顶部
+  document.documentElement.scrollTop = 0;
+  if (!corpId) return;
+  dd.biz.navigation.setTitle({
+    title: router.currentRoute.value.name,
+    onSuccess: function (result) {},
+    onFail: function (err) {},
+  });
+  //设置右侧按钮
+  proxy.uploadDdRightBtn(function () {}, " ");
 
-	//获取元素的绑定事件
-	setTimeout(() => {
-		if (!corpId) {
-			return
-		}
-		let el = document.getElementsByClassName('van-nav-bar__content')[0]
-		if (el) {
-			//删除el元素
-			el.parentNode.removeChild(el)
-		}
-	}, 10)
-})
+  //获取元素的绑定事件
+  setTimeout(() => {
+    if (!corpId) {
+      return;
+    }
+    let el = document.getElementsByClassName("van-nav-bar__content")[0];
+    if (el) {
+      //删除el元素
+      el.parentNode.removeChild(el);
+    }
+  }, 10);
+});
 </script>
 <style lang="scss">
 .main {
-	position: absolute;
-	top: 0;
-	left: 0;
-	right: 0;
-	bottom: 0;
-	padding-bottom:65px;
-	overflow-y: auto;
-	z-index: 1000;
+  position: absolute;
+  top: 0;
+  left: 0;
+  right: 0;
+  bottom: 0;
+  padding-bottom: 65px;
+  overflow-y: auto;
+  z-index: 1000;
 }
-.footer-icon{
-	font-size: 20px;
-	color: #BBBBBB;
+.footer-icon {
+  font-size: 20px;
+  color: #bbbbbb;
 }
-.footer-icon-active{
-	color: #3E7BFA;
+.footer-icon-active {
+  color: #3e7bfa;
 }
-.footer-icon{
-	font-size: 20px;
-	color: #BBBBBB;
+.footer-icon {
+  font-size: 20px;
+  color: #bbbbbb;
 }
-.footer-icon-active{
-	color: #3E7BFA;
+.footer-icon-active {
+  color: #3e7bfa;
 }
 </style>
 <style>
-.van-pull-refresh{
-    flex: 1;
+.van-pull-refresh {
+  flex: 1;
 }
 </style>

+ 253 - 51
src/views/purchase-sales/inbound-outbound/waitInbound/add.vue

@@ -1,55 +1,122 @@
 <template>
   <div class="form">
-    <van-nav-bar
-      :title="$t('waitInbound.name')"
-      :left-text="$t('common.back')"
-      left-arrow
-      @click-left="onClickLeft"
-    >
+    <van-nav-bar :title="$t('waitInbound.name')" :left-text="$t('common.back')" left-arrow @click-left="onClickLeft" @click-right="onClickRight">
+      <template #right> 多货登记 </template>
     </van-nav-bar>
-    <van-form @submit="onSubmit" label-align="top" style="margin-top: 20px">
-      <van-cell-group inset>
-        <van-field
-          v-model="formData.businessTypeName"
-          readonly
-          :label="$t('waitInbound.dataSource')"
-        />
-        <van-field v-model="formData.businessCode" readonly :label="$t('waitInbound.orderNumber')" />
-        <van-field v-model="formData.productName" readonly :label="$t('waitInbound.goodsName')" />
-        <van-field v-model="formData.inQuantity" readonly :label="$t('waitInbound.waitInboundQuantity')" />
-      </van-cell-group>
-      <div style="padding: 5px 0 5px 15px; color: #999999">{{$t('waitInbound.thisTimeInbound')}}</div>
-      <van-cell-group inset>
-        <van-field
-          v-model="formData.warehouseName"
-          is-link
-          readonly
-          :label="$t('waitInbound.warehouseName')"
-          :placeholder="$t('waitInbound.selectWarehouseName')"
-          @click="typeModal = true"
-          :rules="[{ required: true, message: $t('waitInbound.warehouseNameCanNotBeEmpty') }]"
-          required
-        />
+    <van-tabs v-model:active="active">
+      <van-tab title="入库明细" :name="0" />
+      <van-tab title="基本信息" :name="1" />
+    </van-tabs>
+
+    <van-form @submit="onSubmit" @failed="onFailed" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset v-show="active==1">
+        <van-field v-model="formData.businessTypeName" readonly :label="$t('waitInbound.dataSource')" />
+        <van-field v-model="formData.businessCode" readonly label="入库单号" />
+        <van-field v-model="formData.code" readonly label="物流信息" />
+        <van-field v-model="formData.warehouseName" is-link label="仓库名称" readonly :placeholder="'请选择仓库名称'" @click="typeModal = true"
+                   :rules="[{ required: true, message: '请选择仓库名称'}]" required />
+        <van-field v-model="formData.arrivalRemark" label="到货物流备注" type="textarea" />
         <van-popup v-model:show="typeModal" round position="bottom">
-          <van-picker
-            :columns="columns"
-            @cancel="typeModal = false"
-            @confirm="onConfirm"
-          />
+          <van-picker :columns="columns" @cancel="typeModal = false" @confirm="onConfirm" />
         </van-popup>
-        <van-field
-          v-model="formData.quantity"
-          :label="$t('waitInbound.warehousingQuantity')"
-          :placeholder="$t('waitInbound.pleaseEnterWarehousingQuantity')"
-          :rules="[{ required: true, message: $t('waitInbound.warehousingQuantityCanNotBeEmpty') }]"
-          required
-        />
       </van-cell-group>
-      <div style="margin: 16px">
+      <!-- overflow-x: auto;width:calc(100% - 20px) -->
+      <van-cell-group inset v-show="active==0" style="padding:10px;">
+        <table class="table">
+          <thead>
+            <tr>
+              <th style="width:40%;text-align:left;">物品信息</th>
+              <th style="width:15%">采购数量</th>
+              <th style="width:15%">本次发货</th>
+              <th style="width:15%">已入库</th>
+              <th style="width:15%">本次清点
+                累计
+              </th>
+            </tr>
+          </thead>
+        </table>
+        <div style="height:calc(100vh - 280px);overflow-y:auto">
+          <table class="table">
+            <tbody>
+              <template v-for="(row,index) in formData.stockWaitDetailsList" :key="row.id">
+                <div style="height:10px">
+
+                </div>
+                <tr>
+                  <td style="text-align:left;width:40%">
+                    <div>编码:{{row.productCustomCode}}</div>
+                    <div>名称:{{row.productName}}</div>
+                    <div>规格:{{row.productSpec}}</div>
+                  </td>
+                  <td style="width:15%">
+                    <div>{{row.purchaseQuantity}}</div>
+                  </td>
+                  <td style="width:15%">
+                    <div>{{row.arrivalQuantity}}</div>
+                  </td>
+                  <td style="width:15%">
+                    <div>{{row.receiptQuantity}}</div>
+                  </td>
+                  <td style="width:15%">
+                    <div style="color:red">{{row.quantity}}</div>
+                  </td>
+                </tr>
+                <tr style="border-bottom:1px solid #dbd4d4;">
+                  <td colspan="5" style="padding:0 6px">
+                    <div style="text-align:center;color:#b7b0b0;margin-bottom:10px" @click="row.isArrow =!row.isArrow">
+                      <span>在线清点登记</span>
+                      <van-icon :name="!row.isArrow ?'arrow-down':'arrow-up'" style="margin-left:5px" />
+                    </div>
+                    <div v-show="row.isArrow" style="margin-top:5px;margin-bottom:10px">
+                      <div style="display:flex;margin-bottom:8px ;align-items:center">
+                        <van-field v-model="row.addQuantity" type="digit" label="" placeholder="请输入临时清点数量" style="background-color:#f7f7f7;" />
+                        <van-button type="success" size="small" style="width:60px;margin-left:10px" @click="handleStag(row,index)">暂存</van-button>
+                      </div>
+                      <div>
+                        <table class="tableTwo">
+                          <thead>
+                            <tr>
+                              <th>时间</th>
+                              <th style="width:70px">清点数量</th>
+                              <th style="width:70px">提交状态</th>
+                              <th style="width:50px">操作</th>
+                            </tr>
+                          </thead>
+                          <tbody>
+
+                            <tr v-for="(sonRow,sonIndex) in row.stockWaitDetailsCheckList" :key="sonIndex">
+                              <td>
+                                {{sonRow.createTime}}
+                              </td>
+                              <td>
+                                {{sonRow.quantity}}
+                              </td>
+                              <td>
+                                {{sonRow.status==2?'已提交':'未提交'}}
+                              </td>
+                              <td>
+                                <span style="color:#409EFF;cursor:pointer" v-if="sonRow.status !=2" @click="handleDelete(row,index,sonRow)">删除</span>
+                              </td>
+                            </tr>
+                          </tbody>
+                        </table>
+                      </div>
+                    </div>
+                  </td>
+                </tr>
+              </template>
+            </tbody>
+          </table>
+        </div>
+
+      </van-cell-group>
+
+      <div style="margin: 10px">
         <van-button round block type="primary" native-type="submit">
           {{$t('common.submit')}}
         </van-button>
       </div>
+
     </van-form>
   </div>
 </template>
@@ -58,8 +125,10 @@
 import { ref, getCurrentInstance, onMounted } from "vue";
 import { showSuccessToast, showFailToast } from "vant";
 import { useRoute } from "vue-router";
+import { parseTime } from "@/utils/ruoyi";
 
 const proxy = getCurrentInstance().proxy;
+const active = ref(0);
 const route = useRoute();
 const typeModal = ref(false);
 const formData = ref({});
@@ -93,12 +162,12 @@ const onConfirm = ({ selectedOptions }) => {
 const onClickLeft = () => history.back();
 
 const onSubmit = () => {
-  const data = {
-    id: formData.value.id,
-    warehouseId: formData.value.warehouseId,
-    quantity: formData.value.quantity,
-  };
-  proxy.post("/stockWait/add", data).then(
+  const list = formData.value.stockWaitDetailsList;
+  const total = list.reduce((total, x) => (total += Number(x.quantity)), 0);
+  if (!(total > 0)) {
+    return showFailToast("清点累计不能为0");
+  }
+  proxy.post("/stockWait/addByWdly", formData.value).then(
     (res) => {
       setTimeout(() => {
         showSuccessToast(proxy.$t("manualInbound.warehousingSuccess"));
@@ -111,15 +180,111 @@ const onSubmit = () => {
   );
 };
 
+const onFailed = () => {
+  return showFailToast("数据未填完整");
+};
+const businessType = ref([
+  { label: "线边回仓", value: "1" },
+  { label: "完工入库", value: "2" },
+  { label: "采购到货", value: "3" },
+  { label: "退货出库", value: "4" },
+]);
+
 onMounted(() => {
-  if (route.query) {
-    formData.value = { ...route.query };
-    formData.value.inQuantity = formData.value.quantity;
+  if (route.query && route.query.id) {
+    proxy
+      .post("/stockWait/detailByWdly", { id: route.query.id })
+      .then((data) => {
+        let res = data.data;
+        const json = res.victoriatouristJson
+          ? JSON.parse(res.victoriatouristJson)
+          : {};
+        formData.value = {
+          id: route.query.id,
+          type: "1",
+          businessCode: res.businessCode,
+          businessType: res.businessType + "",
+          businessTypeName: proxy.dictValueLabel(
+            res.businessType,
+            businessType.value
+          ),
+          warehouseId: "",
+          code: json.logisticsCompanyName + "( " + json.code + " )",
+          stockWaitDetailsList: res.stockWaitDetailsList.map((x) => ({
+            ...x,
+            arrivalQuantity: x.quantity,
+            quantity: x.stockWaitDetailsCheckList
+              ? x.stockWaitDetailsCheckList
+                  .filter((x) => x.status != 2)
+                  .reduce((total, y) => (total += Number(y.quantity)), 0)
+              : 0,
+            isArrow: false,
+            stockWaitDetailsCheckList: x.stockWaitDetailsCheckList || [],
+          })),
+        };
+      });
   }
   getDict();
 });
+
+const getSonList = (query, index) => {
+  proxy.post("/stockWaitDetailsCheck/list", query).then((res) => {
+    formData.value.stockWaitDetailsList[index].stockWaitDetailsCheckList =
+      res.data;
+    formData.value.stockWaitDetailsList[index].quantity = res.data
+      .filter((x) => x.status != 2)
+      .reduce((total, y) => (total += Number(y.quantity)), 0);
+  });
+};
+
+const handleStag = (row, index) => {
+  if (Number(row.addQuantity) > 0) {
+    let obj = {
+      stockWaitId: formData.value.id,
+      stockWaitDetailsId: row.id,
+      createTime: parseTime(new Date()),
+      quantity: Number(row.addQuantity),
+      status: 0,
+    };
+    // row.stockWaitDetailsCheckList.push(obj);
+
+    proxy.post("/stockWaitDetailsCheck/add", obj).then((res) => {
+      row.addQuantity = "";
+      getSonList({ stockWaitDetailsId: row.id }, index);
+      return showSuccessToast("暂存成功");
+    });
+  } else {
+    return showFailToast("数量必须大于0");
+  }
+};
+
+const handleDelete = (row, index, sonRow) => {
+  // formData.value.stockWaitDetailsList[index].stockWaitDetailsCheckList.splice(
+  //   sonIndex,
+  //   1
+  // );
+  proxy.post("/stockWaitDetailsCheck/delete", { id: sonRow.id }).then((res) => {
+    getSonList({ stockWaitDetailsId: row.id }, index);
+    return showSuccessToast("删除成功");
+  });
+};
+
+const onClickRight = () => {
+  proxy.$router.push({
+    path: "/main/manyGoods",
+    query: {
+      id: formData.value.id,
+      businessTypeName: formData.value.businessTypeName,
+      businessCode: formData.value.businessCode,
+      code: formData.value.code,
+    },
+  });
+};
 </script>
 <style lang="scss" scoped>
+* {
+  font-size: 12px;
+}
 .row {
   display: flex;
   padding: 5px 10px 0 10px;
@@ -134,4 +299,41 @@ onMounted(() => {
     text-align: center;
   }
 }
+.table {
+  border-collapse: collapse;
+  border-spacing: 0;
+  width: 100%;
+  border-color: #ebeef5;
+  color: #606266;
+  thead tr th {
+    padding: 6px 2px;
+    text-align: center;
+    color: #000;
+  }
+  td {
+    text-align: center;
+    padding: 6px 2px;
+    // height: 40px;
+    height: 30px;
+  }
+}
+
+.tableTwo {
+  border-collapse: collapse;
+  border-spacing: 0;
+  width: 100%;
+  background-color: #f7f7f7;
+  color: #606266;
+  thead tr th {
+    text-align: center;
+    padding: 6px 2px;
+    height: 30px;
+    color: #000;
+  }
+  td {
+    text-align: center;
+    padding: 6px 2px;
+    height: 30px;
+  }
+}
 </style>

+ 108 - 52
src/views/purchase-sales/inbound-outbound/waitInbound/index.vue

@@ -2,25 +2,39 @@
   <van-nav-bar :title="$t('waitInbound.name')" left-text="" left-arrow @click-left="onClickLeft">
     <!-- <template #right> 添加 </template> -->
   </van-nav-bar>
-  <van-search
-    v-model="req.keyword"
-    :placeholder="$t('common.pleaseEnterKeywords')"
-    @search="onRefresh"
-  />
+  <van-search v-model="req.keyword" :placeholder="$t('common.pleaseEnterKeywords')" @search="onRefresh" />
   <van-pull-refresh v-model="loading" @refresh="onRefresh">
     <div class="list">
-      <van-list
-        v-model:loading="loading"
-        :finished="finished"
-        :finished-text="$t('common.noMore')"
-        @load="onLoad"
-        style="margin-bottom: 60px"
-      >
-        <commonList
-          :data="listData"
-          @onClick="toDtl"
-          :config="listConfig"
-        ></commonList>
+      <van-list v-model:loading="loading" :finished="finished" :finished-text="$t('common.noMore')" @load="onLoad" style="margin-bottom: 60px">
+        <commonList :data="listData" @onClick="toDtl" :config="listConfig" :showMore="false">
+          <template #businessType="{row}">
+            <div style="width:100%">
+              {{dictValueLabel(row.businessType,businessType)}}
+            </div>
+          </template>
+          <template #logistics="{row}">
+            <div style="width:100%">
+              {{ row.logisticsCompanyName }} (
+              <span style="cursor: pointer; color: #409eff"> {{ row.code }} </span>
+              )
+            </div>
+          </template>
+
+          <template #status="{row}">
+            <div style="width:100%">
+
+              <span :class="{'aa':row.status=='1'}"> {{dictValueLabel(row.status,statusData)}}</span>
+            </div>
+          </template>
+
+          <template #btn="{row}">
+            <div style="width:100%;text-align:right">
+              <van-button type="primary" size="small" style="margin-right:10px" @click="toDtl(row)">入库</van-button>
+              <van-button type="default" size="small" @click="handleEndInbound(row)">结束入库</van-button>
+            </div>
+          </template>
+
+        </commonList>
         <div></div>
       </van-list>
     </div>
@@ -30,6 +44,8 @@
 import { ref, getCurrentInstance, onMounted } from "vue";
 import commonList from "@/components/common-list.vue";
 import { useRoute } from "vue-router";
+import { showSuccessToast, showConfirmDialog } from "vant";
+
 const loading = ref(false);
 const router = useRoute();
 const req = ref({
@@ -43,16 +59,40 @@ const listData = ref([]);
 
 const listConfig = ref([
   {
-    label: proxy.t('waitInbound.dataSource'),
-    prop: "businessTypeName",
+    type: "slot",
+    slotName: "businessType",
+    label: "数据来源",
+  },
+  {
+    label: "单号",
+    prop: "businessCode",
+  },
+  {
+    type: "slot",
+    slotName: "logistics",
+    label: "物流/快递信息",
+  },
+  {
+    label: "仓库名称",
+    prop: "receiptWarehouseName",
+  },
+  {
+    label: "操作人",
+    prop: "operatorName",
+  },
+  {
+    label: "操作时间",
+    prop: "createTime",
   },
   {
-    label: proxy.t('waitInbound.goodsName'),
-    prop: "productName",
+    type: "slot",
+    slotName: "status",
+    label: "入库状态",
   },
   {
-    label: proxy.t('waitInbound.toBeDoneQuantity'),
-    prop: "quantity",
+    type: "slot",
+    slotName: "btn",
+    label: "",
   },
 ]);
 const onRefresh = () => {
@@ -74,55 +114,45 @@ const toDtl = (row) => {
   proxy.$router.push({
     path: "waitInboundAdd",
     query: {
-      ...row,
+      id: row.id,
     },
   });
 };
 const businessType = ref([
+  { label: "线边回仓", value: "1" },
+  { label: "完工入库", value: "2" },
+  { label: "采购到货", value: "3" },
+  { label: "退货出库", value: "4" },
+]);
+
+const statusData = ref([
   {
-    label: proxy.t('waitInbound.lineSideReturnWarehouse'),
-    value: 1,
-  },
-  {
-    label: proxy.t('waitInbound.completedWarehouse'),
-    value: 2,
-  },
-  {
-    label: proxy.t('waitInbound.purchaseArrival'),
-    value: 3,
-  },
-  {
-    label: proxy.t('waitInbound.returnOutbound'),
-    value: 4,
+    label: "未入库",
+    value: "0",
   },
   {
-    label: proxy.t('waitInbound.jdOrder'),
-    value: 5,
+    label: "部分入库",
+    value: "1",
   },
   {
-    label: proxy.t('waitInbound.salesOrderOutbound'),
-    value: 6,
+    label: "入库完成",
+    value: "2",
   },
 ]);
 
 const getList = (type) => {
   loading.value = true;
   proxy
-    .post("/stockWaitDetails/page", req.value)
+    .post("/stockWait/pageByWdly", req.value)
     .then((res) => {
-      console.log(req.value);
+      res.data.rows = res.data.rows.map((x) => ({
+        ...x,
+        ...JSON.parse(x.victoriatouristJson),
+      }));
       listData.value =
         type === "refresh"
           ? res.data.rows
           : listData.value.concat(res.data.rows);
-      listData.value.forEach((x) => {
-        const current = businessType.value.find(
-          (v) => v.value == x.businessType
-        );
-        if (current) {
-          x.businessTypeName = current.label;
-        }
-      });
       if (req.value.pageNum * 10 >= res.data.total) {
         finished.value = true;
       }
@@ -134,10 +164,36 @@ const getList = (type) => {
     });
 };
 getList();
+
+const handleEndInbound = (row) => {
+  showConfirmDialog({
+    title: "提示",
+    message: `您确定结束入库吗?`,
+  })
+    .then(() => {
+      proxy
+        .post("/stockWait/endInStock", {
+          id: row.id,
+        })
+        .then((res) => {
+          showSuccessToast("操作成功");
+          onRefresh();
+        });
+    })
+    .catch(() => {
+      return;
+    });
+};
 </script>
 
 <style lang="scss" scoped>
 .list {
   min-height: 70vh;
 }
+.aa {
+  background: #fa9841;
+  border-radius: 2px;
+  color: #fff;
+  padding: 4px;
+}
 </style>

+ 312 - 0
src/views/purchase-sales/inbound-outbound/waitInbound/manyGoods.vue

@@ -0,0 +1,312 @@
+<template>
+  <div class="form">
+    <van-nav-bar :title="'多货登记'" :left-text="$t('common.back')" left-arrow @click-left="onClickLeft" @click-right="onClickRight">
+      <!-- <template #right> 多货登记 </template> -->
+    </van-nav-bar>
+    <!-- <van-tabs v-model:active="active">
+      <van-tab title="入库明细" :name="0" />
+      <van-tab title="基本信息" :name="1" />
+    </van-tabs> -->
+
+    <van-form @submit="onSubmit" @failed="onFailed" label-align="top" style="margin-top: 20px">
+      <van-cell-group inset>
+        <van-field v-model="formData.businessTypeName" readonly :label="$t('waitInbound.dataSource')" />
+        <van-field v-model="formData.businessCode" readonly label="入库单号" />
+        <van-field v-model="formData.code" readonly label="物流信息" />
+        <div style="padding:0 16px;">
+          <van-button type="primary" round block @click="openSelectGood()">选择物品</van-button>
+        </div>
+        <!-- <van-popup v-model:show="typeModal" round position="bottom">
+          <van-picker :columns="columns" @cancel="typeModal = false" @confirm="onConfirm" />
+        </van-popup> -->
+      </van-cell-group>
+      <!-- overflow-x: auto;width:calc(100% - 20px) -->
+      <van-cell-group inset style="padding:10px;">
+        <table class="table">
+          <thead>
+            <tr>
+              <th style="width:300px">物品信息</th>
+              <!-- <th style="min-width:60px">采购数量</th>
+              <th style="min-width:60px">本次发货</th>
+              <th style="min-width:45px">已入库</th> -->
+              <th style="min-width:85px">本次登记累计</th>
+            </tr>
+          </thead>
+        </table>
+        <div style="height:calc(100vh - 495px);overflow-y:auto">
+          <table class="table">
+            <tbody>
+              <template v-for="(row,index) in formData.stockWaitDetailsList" :key="row.id">
+                <div style="height:10px">
+
+                </div>
+                <tr>
+                  <td style="text-align:left;width:300px">
+                    <div>编码:{{row.productCode}}</div>
+                    <div>名称:{{row.productName}}</div>
+                    <div>规格:{{row.productSpec}}</div>
+                  </td>
+                  <!-- <td style="min-width:60px">
+                    <div>{{row.purchaseQuantity}}</div>
+                  </td>
+                  <td style="min-width:60px">
+                    <div>{{row.arrivalQuantity}}</div>
+                  </td>
+                  <td style="min-width:45px">
+                    <div>{{row.receiptQuantity}}</div>
+                  </td> -->
+                  <td style="min-width:85px">
+                    <div style="color:red">{{row.quantity}}</div>
+                  </td>
+                </tr>
+                <tr style="border-bottom:1px solid #dbd4d4;">
+                  <td colspan="5" style="padding:0 6px">
+                    <div style="text-align:center;color:#b7b0b0;margin-bottom:10px" @click="row.isArrow =!row.isArrow">
+                      <span>在线登记登记</span>
+                      <van-icon :name="!row.isArrow ?'arrow-down':'arrow-up'" style="margin-left:5px" />
+                    </div>
+                    <div v-show="row.isArrow" style="margin-top:5px;margin-bottom:10px">
+                      <div style="display:flex;margin-bottom:8px ;align-items:center">
+                        <van-field v-model="row.addQuantity" type="digit" label="" placeholder="请输入临时登记数量" style="background-color:#f7f7f7;" />
+                        <van-button type="success" size="small" style="width:60px;margin-left:10px" @click="handleStag(row,index)">暂存</van-button>
+                      </div>
+                      <div>
+                        <table class="tableTwo">
+                          <thead>
+                            <tr>
+                              <th>时间</th>
+                              <th style="width:70px">登记数量</th>
+                              <th style="width:70px">提交状态</th>
+                              <th style="width:50px">操作</th>
+                            </tr>
+                          </thead>
+                          <tbody>
+
+                            <tr v-for="(sonRow,sonIndex) in row.stockWaitDetailsCheckList" :key="sonIndex">
+                              <td>
+                                {{sonRow.createTime}}
+                              </td>
+                              <td>
+                                {{sonRow.quantity}}
+                              </td>
+                              <td>
+                                {{sonRow.status==2?'已提交':'未提交'}}
+                              </td>
+                              <td>
+                                <span style="color:#409EFF;cursor:pointer" v-if="sonRow.status !=2" @click="handleDelete(row,index,sonRow)">删除</span>
+                              </td>
+                            </tr>
+                          </tbody>
+                        </table>
+                      </div>
+                    </div>
+                  </td>
+                </tr>
+              </template>
+            </tbody>
+          </table>
+        </div>
+
+      </van-cell-group>
+
+      <div style="margin: 10px">
+        <van-button round block type="primary" native-type="submit">
+          {{$t('common.submit')}}
+        </van-button>
+      </div>
+
+    </van-form>
+  </div>
+</template>
+
+<script setup>
+import { ref, getCurrentInstance, onMounted, watch, computed } from "vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { useRoute } from "vue-router";
+import { parseTime } from "@/utils/ruoyi";
+import useSelectGoodStore from "@/store/manyGood";
+const selectGoodStore = useSelectGoodStore();
+const proxy = getCurrentInstance().proxy;
+const active = ref(0);
+const route = useRoute();
+const typeModal = ref(false);
+const formData = ref({});
+const list = computed(() =>
+  selectGoodStore.selectGood.map((x) => ({ ...x, quantity: 0 }))
+);
+watch(
+  () => list.value,
+  (val) => {
+    console.log(list.value, "sasaw");
+
+    formData.value.stockWaitDetailsList = list.value;
+  }
+);
+const getDict = () => {
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 9999 }).then((res) => {
+    columns.value = res.data.rows.map((item) => {
+      return {
+        text: item.name,
+        value: item.id,
+      };
+    });
+  });
+};
+
+const getDetails = (id) => {
+  proxy.post("/stockWait/detail", { id }).then((res) => {
+    res.data.inQuantity = res.data.quantity;
+    formData.value = res.data;
+  });
+};
+
+const columns = ref([]);
+
+const onConfirm = ({ selectedOptions }) => {
+  formData.value.warehouseId = selectedOptions[0].value;
+  formData.value.warehouseName = selectedOptions[0].text;
+  typeModal.value = false;
+};
+
+const onClickLeft = () => history.back();
+
+const onSubmit = () => {
+  const list = formData.value.stockWaitDetailsList;
+  const total = list.reduce((total, x) => (total += Number(x.quantity)), 0);
+  if (!(total > 0)) {
+    return showFailToast("登记累计不能为0");
+  }
+  proxy.post("/stockWait/addByWdly", formData.value).then(
+    (res) => {
+      setTimeout(() => {
+        showSuccessToast(proxy.$t("manualInbound.warehousingSuccess"));
+        proxy.$router.push("/main/waitInbound");
+      }, 500);
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+
+const onFailed = () => {
+  return showFailToast("数据未填完整");
+};
+const businessType = ref([
+  { label: "线边回仓", value: "1" },
+  { label: "完工入库", value: "2" },
+  { label: "采购到货", value: "3" },
+  { label: "退货出库", value: "4" },
+]);
+
+onMounted(() => {
+  selectGoodStore.clearGood();
+  if (route.query && route.query.id) {
+    formData.value = {
+      ...route.query,
+    };
+  }
+  // getDict();
+});
+
+const getSonList = (query, index) => {
+  proxy.post("/stockWaitDetailsCheck/list", query).then((res) => {
+    formData.value.stockWaitDetailsList[index].stockWaitDetailsCheckList =
+      res.data;
+    formData.value.stockWaitDetailsList[index].quantity = res.data
+      .filter((x) => x.status != 2)
+      .reduce((total, y) => (total += Number(y.quantity)), 0);
+  });
+};
+
+const handleStag = (row, index) => {
+  if (Number(row.addQuantity) > 0) {
+    let obj = {
+      stockWaitId: formData.value.id,
+      stockWaitDetailsId: row.id,
+      createTime: parseTime(new Date()),
+      quantity: Number(row.addQuantity),
+      status: 0,
+    };
+    // row.stockWaitDetailsCheckList.push(obj);
+
+    proxy.post("/stockWaitDetailsCheck/add", obj).then((res) => {
+      row.addQuantity = "";
+      getSonList({ stockWaitDetailsId: row.id }, index);
+      return showSuccessToast("暂存成功");
+    });
+  } else {
+    return showFailToast("数量必须大于0");
+  }
+};
+
+const handleDelete = (row, index, sonRow) => {
+  // formData.value.stockWaitDetailsList[index].stockWaitDetailsCheckList.splice(
+  //   sonIndex,
+  //   1
+  // );
+  proxy.post("/stockWaitDetailsCheck/delete", { id: sonRow.id }).then((res) => {
+    getSonList({ stockWaitDetailsId: row.id }, index);
+    return showSuccessToast("删除成功");
+  });
+};
+
+const openSelectGood = () => {
+  proxy.$router.push({
+    path: "/main/selectGood",
+  });
+};
+</script>
+<style lang="scss" scoped>
+.row {
+  display: flex;
+  padding: 5px 10px 0 10px;
+  justify-content: space-between;
+  align-items: center;
+  .title {
+    flex: 1;
+  }
+  .delete {
+    width: 20px;
+    cursor: pointer;
+    text-align: center;
+  }
+}
+.table {
+  border-collapse: collapse;
+  border-spacing: 0;
+  width: 100%;
+  border-color: #ebeef5;
+  color: #606266;
+  thead tr th {
+    padding: 6px 2px;
+    text-align: left;
+    color: #000;
+  }
+  td {
+    text-align: center;
+    padding: 6px 2px;
+    // height: 40px;
+    height: 30px;
+  }
+}
+
+.tableTwo {
+  border-collapse: collapse;
+  border-spacing: 0;
+  width: 100%;
+  background-color: #f7f7f7;
+  color: #606266;
+  thead tr th {
+    text-align: center;
+    padding: 6px 2px;
+    height: 30px;
+    color: #000;
+  }
+  td {
+    text-align: center;
+    padding: 6px 2px;
+    height: 30px;
+  }
+}
+</style>

+ 146 - 0
src/views/purchase-sales/inbound-outbound/waitInbound/selectGood.vue

@@ -0,0 +1,146 @@
+<template>
+  <van-nav-bar :title="'选择物品'" left-text="" left-arrow @click-left="onClickLeft" @click-right="onClickRight">
+    <!-- <template #right> {{$t('common.add')}} </template> -->
+  </van-nav-bar>
+  <van-search v-model="req.keyword" :placeholder="$t('common.pleaseEnterKeywords')" @search="onRefresh" />
+  <van-pull-refresh v-model="loading" @refresh="onRefresh">
+    <div class="list">
+      <van-list v-model:loading="loading" :finished="finished" :finished-text="$t('common.noMore')" @load="onLoad" style="margin-bottom: 60px">
+        <!-- @onClick="toDtl" -->
+        <commonList :data="listData" :config="listConfig" :showMore="false">
+          <template #btn="{row}">
+            <div style="width:100%;text-align:right">
+              <van-button type="primary" size="small" @click="selectRow(row)">选择</van-button>
+
+            </div>
+          </template>
+        </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";
+import useSelectGoodStore from "@/store/manyGood";
+import { showSuccessToast, showFailToast } from "vant";
+const selectGoodStore = useSelectGoodStore();
+const loading = ref(false);
+const router = useRoute();
+const req = ref({
+  pageNum: 1,
+  keyword: null,
+  definition: "",
+});
+const finished = ref(false);
+const proxy = getCurrentInstance().proxy;
+const listData = ref([]);
+const classification = ref([]);
+const listConfig = ref([
+  {
+    label: proxy.t("productLibrary.productCode"),
+    prop: "customCode",
+  },
+  {
+    label: proxy.t("productLibrary.productName"),
+    prop: "name",
+  },
+  {
+    label: "规格",
+    prop: "spec",
+  },
+  {
+    type: "slot",
+    slotName: "btn",
+    label: "",
+  },
+]);
+const onRefresh = () => {
+  req.value.pageNum = 1;
+  finished.value = false;
+  getList("refresh");
+};
+const onLoad = () => {
+  // getClassification();
+  getList();
+};
+const onClickLeft = () => history.back();
+
+const onClickRight = () => {
+  proxy.$router.push({
+    path: "productLibraryAdd",
+    query: {
+      type: "add",
+    },
+  });
+};
+proxy.uploadDdRightBtn(onClickRight, proxy.t("common.add"));
+const toDtl = (row) => {
+  proxy.$router.push({
+    path: "productLibraryAdd",
+    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: "1",
+      })
+      .then((res) => {
+        classification.value = treeToList(res.data);
+        getList();
+      });
+  }
+};
+const getList = (type) => {
+  loading.value = true;
+  proxy
+    .post("/productInfo/pageByWdly", req.value)
+    .then((res) => {
+      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;
+    });
+};
+
+const selectRow = (row) => {
+  selectGoodStore.pushGood(row);
+  return showSuccessToast("选择成功");
+};
+</script>
+
+<style lang="scss" scoped>
+.list {
+  min-height: 70vh;
+}
+</style>

+ 89 - 55
src/views/purchase-sales/inventory-management/Inventory/add.vue

@@ -1,20 +1,8 @@
 <template>
   <div class="form">
-    <van-nav-bar
-      :title="$t('inventoryCount.name')"
-      :left-text="$t('common.back')"
-      left-arrow
-      @click-left="onClickLeft"
-    >
+    <van-nav-bar :title="'盘点明细'" :left-text="$t('common.back')" left-arrow @click-left="onClickLeft">
     </van-nav-bar>
-    <testForm
-      v-model="formData.data"
-      :formOption="formOption"
-      :formConfig="formConfig"
-      :rules="rules"
-      @onSubmit="onSubmit"
-      ref="formDom"
-    ></testForm>
+    <testForm v-model="formData.data" :formOption="formOption" :formConfig="formConfig" :rules="rules" @onSubmit="onSubmit" ref="formDom"></testForm>
   </div>
 </template>
 
@@ -63,41 +51,69 @@ const formOption = reactive({
     prop: "list",
     plain: true,
     listConfig: [
+      // {
+      //   type: "picker",
+      //   label: proxy.t("inventoryCount.goodsName"),
+      //   prop: "productId",
+      //   itemType: "onePicker",
+      //   showPicker: false,
+      //   readonly: false,
+      //   fieldNames: {
+      //     text: "name",
+      //     value: "id",
+      //   },
+      //   data: [],
+      //   changeFn: function (option, item, index, currentSonIndex) {
+      //     formData.data.list[index][item.prop] = option.selectedOptions[0].id;
+      //     formData.data.list[index][item.prop + "Name"] =
+      //       option.selectedOptions[0].name;
+      //     formDom.value.btnConfigCopy.listConfig[
+      //       currentSonIndex
+      //     ].showPicker = false;
+      //     getStokeQuantity();
+      //   },
+      // },
       {
-        type: "picker",
-        label: proxy.t("inventoryCount.goodsName"),
-        prop: "productId",
-        itemType: "onePicker",
-        showPicker: false,
-        readonly: false,
-        fieldNames: {
-          text: "name",
-          value: "id",
-        },
-        data: [],
-        changeFn: function (option, item, index, currentSonIndex) {
-          formData.data.list[index][item.prop] = option.selectedOptions[0].id;
-          formData.data.list[index][item.prop + "Name"] =
-            option.selectedOptions[0].name;
-          formDom.value.btnConfigCopy.listConfig[
-            currentSonIndex
-          ].showPicker = false;
-          getStokeQuantity();
-        },
+        type: "input",
+        itemType: "text",
+        label: "物品编码",
+        prop: "productCode",
+        readonly: true,
       },
       {
         type: "input",
         itemType: "text",
-        label: proxy.t("inventoryCount.stockNumber"),
+        label: "物品名称",
+        prop: "productName",
+        readonly: true,
+      },
+      {
+        type: "input",
+        itemType: "text",
+        label: "单位",
+        prop: "productUnit",
+        readonly: true,
+      },
+      {
+        type: "input",
+        itemType: "text",
+        label: "库存数量",
         prop: "quantity",
         readonly: true,
       },
       {
         type: "input",
         itemType: "number",
-        label: proxy.t("inventoryCount.inventoryNumber"),
+        label: "盘点数量",
         prop: "checkQuantity",
-        readonly: false,
+        readonly: true,
+      },
+      {
+        type: "input",
+        itemType: "text",
+        label: "盘点结果",
+        prop: "result",
+        readonly: true,
       },
     ],
     clickFn: () => {
@@ -120,24 +136,31 @@ const formOption = reactive({
   },
 });
 const formConfig = reactive([
+  // {
+  //   type: "picker",
+  //   label: proxy.t("inventoryCount.inventoryWarehouse"),
+  //   prop: "warehouseId",
+  //   itemType: "onePicker",
+  //   showPicker: false,
+  //   readonly: false,
+  //   fieldNames: {
+  //     text: "name",
+  //     value: "id",
+  //   },
+  //   data: [],
+  //   changeFn: function (option, item, index) {
+  //     formData.data[item.prop] = option.selectedOptions[0].id;
+  //     formData.data[item.prop + "Name"] = option.selectedOptions[0].name;
+  //     formConfig[index].showPicker = false;
+  //     getStokeQuantity();
+  //   },
+  // },
   {
-    type: "picker",
-    label: proxy.t("inventoryCount.inventoryWarehouse"),
-    prop: "warehouseId",
-    itemType: "onePicker",
-    showPicker: false,
-    readonly: false,
-    fieldNames: {
-      text: "name",
-      value: "id",
-    },
-    data: [],
-    changeFn: function (option, item, index) {
-      formData.data[item.prop] = option.selectedOptions[0].id;
-      formData.data[item.prop + "Name"] = option.selectedOptions[0].name;
-      formConfig[index].showPicker = false;
-      getStokeQuantity();
-    },
+    type: "input",
+    itemType: "text",
+    label: "仓库名称",
+    prop: "warehouseName",
+    readonly: true,
   },
 ]);
 const onClickLeft = () => history.back();
@@ -184,12 +207,23 @@ const getStokeQuantity = () => {
   }
 };
 onMounted(() => {
-  getDict();
+  // getDict();
   if (route.query && route.query.id) {
     formOption.hiddenSubmitBtn = true;
     formOption.btnConfig.isNeed = false;
     proxy.post("/stockCheck/detail", { id: route.query.id }).then((res) => {
       formData.data = res.data;
+      formData.data.list.map((x) => {
+        if (Number(x.checkQuantity) > Number(x.quantity)) {
+          x.result = "盘盈";
+        }
+        if (Number(x.checkQuantity) < Number(x.quantity)) {
+          x.result = "盘亏";
+        }
+        if (Number(x.checkQuantity) == Number(x.quantity)) {
+          x.result = "正常";
+        }
+      });
     });
   }
 });

+ 301 - 38
src/views/purchase-sales/inventory-management/Inventory/index.vue

@@ -1,50 +1,133 @@
 <template>
-  <van-nav-bar
-    :title="$t('inventoryCount.name')"
-    left-text=""
-    left-arrow
-    @click-left="onClickLeft"
-    @click-right="onClickRight"
-  >
-    <template #right> {{ $t("common.add") }} </template>
+  <van-nav-bar :title="$t('inventoryCount.name')" left-text="" left-arrow @click-left="onClickLeft" @click-right="onClickRight">
+    <!-- <template #right> {{ $t("common.add") }} </template> -->
   </van-nav-bar>
-  <van-search
-    v-model="req.keyword"
-    :placeholder="$t('common.pleaseEnterKeywords')"
-    @search="onRefresh"
-  />
-  <van-pull-refresh v-model="loading" @refresh="onRefresh">
-    <div class="list">
-      <van-list
-        v-model:loading="loading"
-        :finished="finished"
-        :finished-text="$t('common.noMore')"
-        @load="getList"
-        style="margin-bottom: 60px"
-      >
-        <commonList :data="listData" @onClick="toDtl" :config="listConfig">
-          <template #inventoryResult="{ row }">
-            <div>
-              <span v-if="row.result == 0">正常</span>
-              <span style="color: #d9001b" v-else>异常</span>
+  <div style="display:flex">
+    <van-dropdown-menu>
+      <van-dropdown-item v-model="req.warehouseId" :options="warehouseList" @change="changeWarehouseId" />
+    </van-dropdown-menu>
+    <van-search v-model="req.keyword" style="flex:1" :placeholder="$t('common.pleaseEnterKeywords')" @search="onRefresh" />
+  </div>
+
+  <van-tabs v-model:active="active" @change="handleChangeTab">
+    <van-tab :title="'物资盘点'" name="first"></van-tab>
+    <van-tab :title="'盘点记录'" name="second"></van-tab>
+    <van-tab :title="'历史记录'" name="three"></van-tab>
+  </van-tabs>
+  <div style="padding:0 16px" v-if="active!='three'">
+    <table class="table">
+      <thead>
+        <tr>
+          <th style="width:70%;text-align: left;">物品信息</th>
+          <th style="width:30%">本次盘点累计</th>
+        </tr>
+      </thead>
+    </table>
+  </div>
+  <div style="overflow-y:auto" :style="{height:active!='three'?'calc(100vh - 300px)':'calc(100vh - 210px)'}">
+    <van-pull-refresh v-model="loading" @refresh="onRefresh">
+      <div class="list">
+        <van-list v-model:loading="loading" :finished="finished" :finished-text="$t('common.noMore')" @load="getList" style="margin-bottom: 60px">
+          <commonList :data="listData" @onClick="toDtl" :config="listConfig" v-if="active=='three'">
+            <template #inventoryResult="{ row }">
+              <div>
+                <span v-if="row.result == 0">正常</span>
+                <span style="color: red" v-else>异常</span>
+              </div>
+            </template>
+          </commonList>
+          <div v-else style="margin-bottom:10px">
+            <div v-for="(row,index) in listData" :key="row.id" class="main-box">
+              <div style="display:flex;align-items:center">
+                <div style="width:70%">
+                  <div>
+                    仓库名称:{{row.warehouseName}}
+                  </div>
+                  <div>
+                    物品编码:{{row.productCustomCode}}
+                  </div>
+                  <div>
+                    物品名称:{{row.productName}}
+                  </div>
+                  <div>
+                    物品规格:{{row.productSpec}}
+                  </div>
+                  <div>
+                    可用库存:{{row.quantity}}
+                  </div>
+                </div>
+                <div style="width:30%;color:red;text-align:center">
+                  {{row.checkQuantity}}
+                </div>
+              </div>
+
+              <!-- style="border-bottom:1px solid #dbd4d4;" -->
+              <div>
+                <div style="padding:0 6px">
+                  <div style="text-align:center;color:#b7b0b0;margin-bottom:10px" @click="row.isArrow =!row.isArrow">
+                    <span>在线盘点登记</span>
+                    <van-icon :name="!row.isArrow ?'arrow-down':'arrow-up'" style="margin-left:5px" />
+                  </div>
+                  <div v-show="row.isArrow" style="margin-top:5px;margin-bottom:10px">
+                    <div style="display:flex;margin-bottom:8px ;align-items:center">
+                      <van-field v-model="row.addQuantity" type="digit" label="" placeholder="请输入临时盘点数量" style="background-color:#f7f7f7;" />
+                      <van-button type="success" size="small" style="width:60px;margin-left:10px" @click="handleStag(row,index)">暂存</van-button>
+                    </div>
+                    <div>
+                      <table class="tableTwo">
+                        <thead>
+                          <tr>
+                            <th>时间</th>
+                            <th style="width:70px">盘点数量</th>
+                            <th style="width:50px">操作</th>
+                          </tr>
+                        </thead>
+                        <tbody>
+                          <tr v-for="(sonRow,sonIndex) in row.stockCheckRegisterList" :key="sonIndex">
+                            <td>
+                              {{sonRow.createTime}}
+                            </td>
+                            <td>
+                              {{sonRow.checkQuantity}}
+                            </td>
+                            <td>
+                              <span style="color:#409EFF;cursor:pointer" v-if="sonRow.status !=2" @click="handleDelete(row,index,sonRow)">删除</span>
+                            </td>
+                          </tr>
+                        </tbody>
+                      </table>
+                    </div>
+                  </div>
+                </div>
+              </div>
             </div>
-          </template>
-        </commonList>
-      </van-list>
-    </div>
-  </van-pull-refresh>
+          </div>
+        </van-list>
+      </div>
+    </van-pull-refresh>
+  </div>
+  <div style="padding:0 16px;margin-top:10px" v-if="active!='three'">
+    <van-button type="primary" round block @click="onSubmit()">提交</van-button>
+  </div>
+
 </template>
 <script setup>
 import { ref, getCurrentInstance } from "vue";
 import commonList from "@/components/common-list.vue";
+import { showSuccessToast, showFailToast } from "vant";
+import { parseTime } from "@/utils/ruoyi";
 
 const proxy = getCurrentInstance().proxy;
 const onClickLeft = () => proxy.$router.push("/main/working");
 const req = ref({
   pageNum: 1,
-  keyword: null,
-  dataType: "1",
+  keyword: "",
+  warehouseId: "",
+  isCheckRegister: "",
 });
+const warehouseId = ref("");
+const warehouseList = ref([{ text: "全部仓库", value: "" }]);
+const active = ref("first");
 const finished = ref(false);
 const onRefresh = () => {
   req.value.pageNum = 1;
@@ -56,8 +139,22 @@ const listData = ref([]);
 const getList = (type) => {
   loading.value = true;
   proxy
-    .post("/stockCheck/page", req.value)
+    .post(requestUrl.value, req.value)
     .then((res) => {
+      if (active.value != "three") {
+        res.data.rows.map((x) => {
+          x.addQuantity = "";
+          if (x.stockCheckRegisterList && x.stockCheckRegisterList.length > 0) {
+            x.checkQuantity = x.stockCheckRegisterList.reduce(
+              (total, x) => (total += Number(x.checkQuantity)),
+              0
+            );
+          } else {
+            x.checkQuantity = 0;
+          }
+        });
+      }
+
       listData.value =
         type === "refresh"
           ? res.data.rows
@@ -88,23 +185,189 @@ const onClickRight = () => {
 };
 const listConfig = ref([
   {
-    label: proxy.t("inventoryCount.inventoryTime"),
+    label: "盘点单号",
+    prop: "code",
+  },
+  {
+    label: "仓库名称",
+    prop: "warehouseName",
+  },
+  {
+    label: "盘点时间",
     prop: "createTime",
   },
   {
-    label: proxy.t("inventoryCount.inventoryPerson"),
+    label: "盘点人",
     prop: "userName",
   },
   {
+    label: "盘点物品数",
+    prop: "totalNum",
+  },
+  {
+    label: "正常物品数",
+    prop: "normalNum",
+  },
+  {
+    label: "异常物品数",
+    prop: "anomalyNum",
+  },
+  {
     type: "slot",
-    label: proxy.t("inventoryCount.inventoryResult"),
+    label: "盘点结论",
     slotName: "inventoryResult",
   },
 ]);
+const requestUrl = ref("/stockCheck/stockProductPage");
+const handleChangeTab = (val) => {
+  if (val == "first") {
+    requestUrl.value = "/stockCheck/stockProductPage";
+    req.value.isCheckRegister = "";
+  } else if (val == "second") {
+    requestUrl.value = "/stockCheck/stockProductPage";
+    req.value.isCheckRegister = "1";
+  } else {
+    requestUrl.value = "/stockCheck/page";
+    req.value.isCheckRegister = "";
+  }
+  req.value.pageNum = 1;
+  listData.value = [];
+  getList();
+};
+
+const changeWarehouseId = (val) => {
+  req.value = {
+    pageNum: 1,
+    keyword: "",
+    warehouseId: val,
+    isCheckRegister: "",
+  };
+  listData.value = [];
+  getList();
+};
+
+const getDict = () => {
+  proxy.post("/warehouse/page", { pageNum: 1, pageSize: 999 }).then((res) => {
+    warehouseList.value = [
+      ...warehouseList.value,
+      ...res.data.rows.map((x) => ({ text: x.name, value: x.id })),
+    ];
+  });
+};
+getDict();
+
+const getSonList = (query, index) => {
+  proxy.post("/stockCheckRegister/list", query).then((res) => {
+    listData.value[index].stockCheckRegisterList = res.data;
+    listData.value[index].checkQuantity = res.data
+      .filter((x) => x.status != 2)
+      .reduce((total, y) => (total += Number(y.checkQuantity)), 0);
+  });
+};
+
+const handleStag = (row, index) => {
+  if (Number(row.addQuantity) > 0) {
+    let obj = {
+      stockId: row.id,
+      warehouseId: row.warehouseId,
+      productId: row.productId,
+      createTime: parseTime(new Date()),
+      // quantity: row.quantity,
+      checkQuantity: Number(row.addQuantity),
+      status: 0,
+    };
+
+    proxy.post("/stockCheckRegister/add", obj).then((res) => {
+      row.addQuantity = "";
+      let query = {
+        stockId: row.id,
+        warehouseId: row.warehouseId,
+        productId: row.productId,
+      };
+      getSonList(query, index);
+      return showSuccessToast("暂存成功");
+    });
+  } else {
+    return showFailToast("数量必须大于0");
+  }
+};
+
+const handleDelete = (row, index, sonRow) => {
+  let query = {
+    stockId: row.id,
+    warehouseId: row.warehouseId,
+    productId: row.productId,
+  };
+  proxy.post("/stockCheckRegister/delete", { id: sonRow.id }).then((res) => {
+    getSonList(query, index);
+    return showSuccessToast("删除成功");
+  });
+};
+
+const onSubmit = () => {
+  proxy.post("/stockCheck/submitAll").then(
+    (res) => {
+      showSuccessToast("操作成功");
+      onRefresh();
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
 </script>
 
 <style lang="scss" scoped>
+* {
+  font-size: 12px;
+}
 .list {
   min-height: 70vh;
 }
+.main-box {
+  padding: 12px 16px 0 16px;
+  background: #fff;
+  border-bottom: 1px solid #f1f1f1;
+}
+.table {
+  border-collapse: collapse;
+  border-spacing: 0;
+  width: 100%;
+  border-color: #ebeef5;
+  color: #606266;
+  thead tr th {
+    padding: 6px 2px;
+    text-align: center;
+    color: #000;
+  }
+  td {
+    text-align: center;
+    padding: 6px 2px;
+    // height: 40px;
+    height: 30px;
+  }
+}
+.tableTwo {
+  border-collapse: collapse;
+  border-spacing: 0;
+  width: 100%;
+  background-color: #f7f7f7;
+  color: #606266;
+  thead tr th {
+    text-align: center;
+    padding: 6px 2px;
+    height: 30px;
+    color: #000;
+  }
+  td {
+    text-align: center;
+    padding: 6px 2px;
+    height: 30px;
+  }
+}
+
+:deep(.van-dropdown-menu__bar) {
+  box-shadow: none !important;
+  height: 54px !important;
+}
 </style>

+ 256 - 71
src/views/purchase-sales/inventory-management/inventoryQuery/index.vue

@@ -1,74 +1,192 @@
 <template>
-  <van-nav-bar
-    :title="$t('inventoryQuery.name')"
-    left-text=""
-    left-arrow
-    @click-left="onClickLeft"
-  >
+  <van-nav-bar :title="$t('inventoryQuery.name')" left-text="" left-arrow @click-left="onClickLeft">
   </van-nav-bar>
-  <van-search
-    v-model="req.keyword"
-    :placeholder="$t('common.pleaseEnterKeywords')"
-    @search="onRefresh"
-  />
+  <van-search v-model="req.keyword" :placeholder="$t('common.pleaseEnterKeywords')" @search="onRefresh" />
   <van-tabs v-model:active="active" @change="handleChangeTab">
-    <van-tab :title="$t('inventoryQuery.all')" name="all"></van-tab>
-    <van-tab
-      v-for="(item, index) in warehouseData"
-      :title="item.name"
-      :name="item.id"
-    >
-    </van-tab>
+    <van-tab :title="'按仓库'" name="first"></van-tab>
+    <van-tab :title="'按产品'" name="second"></van-tab>
+    <van-tab :title="'按SPU'" name="three"></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="$t('common.noMore')"
-        @load="onLoad"
-        style="margin-bottom: 60px"
-      >
-        <commonList
-          :data="listData"
-          @onClick="toDtl"
-          :config="listConfig"
-        ></commonList>
+      <van-list v-model:loading="loading" :finished="finished" :finished-text="$t('common.noMore')" @load="onLoad" style="margin-bottom: 60px">
+        <commonList :data="listData" :config="listConfig" :showMore="false">
+          <template #productUnit="{row}">
+            <div style="width:100%">
+              {{dictValueLabel(row.productUnit,productUnit)}}
+            </div>
+          </template>
+          <template #btn="{row}">
+            <div style="width:100%;text-align:right">
+              <van-button type="primary" size="small" style="margin-right:10px" @click="toDtl(row,true)">良转次</van-button>
+              <van-button type="primary" size="small" @click="toDtl(row,false)">次转良</van-button>
+            </div>
+          </template>
+        </commonList>
+        <!-- @onClick="toDtl" -->
       </van-list>
     </div>
   </van-pull-refresh>
+  <van-popup v-model:show="openPopup" position="bottom" :style="{ height: '370px' }" closeable>
+    <div style="padding:10px">
+      <van-form @submit="onSubmit" label-align="top">
+        <TitleInfo :title="submitType?'良转次':'次转良'"></TitleInfo>
+        <van-field v-model="formData.data.canSum" type="text" label="可转数量" readonly />
+        <van-field v-model="formData.data.quantity" type="digit" label="数量" placeholder="请输入数量" :rules="[{ required: true, message: '请填写数量' }]" />
+        <div style="margin: 16px">
+          <van-button round block type="primary" native-type="submit">
+            提交
+          </van-button>
+        </div>
+      </van-form>
+
+    </div>
+  </van-popup>
 </template>
 <script setup>
-import { ref, getCurrentInstance, onMounted } from "vue";
+import { ref, getCurrentInstance, onMounted, reactive } from "vue";
 import commonList from "@/components/common-list.vue";
 import { useRoute } from "vue-router";
+import { getUserInfo } from "@/utils/auth";
+import { showSuccessToast, showFailToast } from "vant";
+import TitleInfo from "@/components/TitleInfo/index.vue";
+
 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");
-const listConfig = ref([
-  {
-    label: proxy.t('inventoryQuery.itemClassification'),
-    prop: "productClassifyName",
-  },
-  {
-    label: proxy.t('inventoryQuery.itemName'),
-    prop: "productName",
-  },
-  {
-    label: proxy.t('inventoryQuery.inventoryQuantity'),
-    prop: "quantity",
-  },
-]);
+const productUnit = ref([]);
+const active = ref("first");
+let listConfigSet = [
+  [
+    {
+      label: "仓库名称",
+      prop: "warehouseName",
+    },
+    {
+      label: "项目组",
+      prop: "deptName",
+    },
+    {
+      label: "所属分类",
+      prop: "productClassifyName",
+    },
+    {
+      label: "物品编码",
+      prop: "productCustomCode",
+    },
+    {
+      label: "物品名称",
+      prop: "productName",
+    },
+    {
+      label: "规格",
+      prop: "productSpec",
+    },
+    {
+      type: "slot",
+      slotName: "productUnit",
+      label: "单位",
+      prop: "productUnit",
+    },
+    {
+      label: "可用库存",
+      prop: "quantity",
+    },
+    {
+      label: "冻结库存",
+      prop: "frozenQuantity",
+    },
+    {
+      label: "次品库存",
+      prop: "defectiveQuantity",
+    },
+    {
+      label: "最近入库时间",
+      prop: "updateTime",
+    },
+    {
+      type: "slot",
+      slotName: "btn",
+      label: "",
+    },
+  ],
+  [
+    {
+      label: "项目组",
+      prop: "deptName",
+    },
+    {
+      label: "所属分类",
+      prop: "productClassifyName",
+    },
+    {
+      label: "物品编码",
+      prop: "productCustomCode",
+    },
+    {
+      label: "物品名称",
+      prop: "productName",
+    },
+    {
+      label: "规格",
+      prop: "productSpec",
+    },
+    {
+      type: "slot",
+      slotName: "productUnit",
+      label: "单位",
+      prop: "productUnit",
+    },
+    {
+      label: "可用库存",
+      prop: "quantity",
+    },
+    {
+      label: "冻结库存",
+      prop: "frozenQuantity",
+    },
+    {
+      label: "次品库存",
+      prop: "defectiveQuantity",
+    },
+    {
+      label: "最近入库时间",
+      prop: "updateTime",
+    },
+    {
+      type: "slot",
+      slotName: "btn",
+      label: "",
+    },
+  ],
+  [
+    {
+      label: "spu编码",
+      prop: "productSpuCode",
+    },
+    {
+      label: "spu名称",
+      prop: "productSpuName",
+    },
+    {
+      label: "关联产品数",
+      prop: "linkProductQuantity",
+    },
+    {
+      label: "库存数量",
+      prop: "quantity",
+    },
+  ],
+];
+const listConfig = ref([]);
+listConfig.value = listConfigSet[0];
 const onRefresh = () => {
   req.value.pageNum = 1;
   finished.value = false;
@@ -83,25 +201,89 @@ 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 formData = reactive({
+  data: {},
+});
+const openPopup = ref(false);
+const submitType = ref(false);
+const toDtl = (row, flag) => {
+  submitType.value = flag;
+  // proxy.$router.push({
+  //   path: "outInList",
+  //   query: {
+  //     productId: row.productId,
+  //     warehouseId: row.warehouseId,
+  //   },
+  // });
+  let canSum = flag ? row.quantity : row.defectiveQuantity;
+  formData.data = {
+    id: row.id,
+    canSum,
+    quantity: null,
+  };
+  openPopup.value = true;
 };
 
+const onSubmit = () => {
+  let url = submitType.value
+    ? "/stock/qualifiedToDefective"
+    : "/stock/defectiveToQualified";
+  if (!(Number(formData.data.quantity) > 0)) {
+    return showFailToast("数量不能为0");
+  }
+  if (Number(formData.data.quantity) > Number(formData.data.canSum)) {
+    return showFailToast("数量不可大于可转数量");
+  }
+  proxy.post(url, formData.data).then(
+    (res) => {
+      onRefresh();
+      showSuccessToast("操作成功");
+      openPopup.value = false;
+    },
+    (err) => {
+      return showFailToast(err.message);
+    }
+  );
+};
+const getDict = () => {
+  let query = {
+    pageNum: 1,
+    pageSize: 999,
+    tenantId: getUserInfo().tenantId,
+  };
+  // proxy
+  //   .post("/supplierInfo/page", { pageNum: 1, pageSize: 9999 })
+  //   .then((res) => {
+  //     supplierData.value = res.data.rows;
+  //     formConfig[5].data = supplierData.value;
+  //   });
+  proxy
+    .post("/dictTenantData/page", {
+      ...query,
+      dictCode: "unit",
+    })
+    .then((res) => {
+      if (res.data.rows && res.data.rows.length > 0) {
+        productUnit.value = res.data.rows.map((item) => {
+          return {
+            label: item.dictValue,
+            value: item.dictKey,
+          };
+        });
+      }
+    });
+};
+getDict();
 const getList = (type) => {
   loading.value = true;
   proxy
-    .post("/stock/page", req.value)
+    .post(requestUrl.value, req.value)
     .then((res) => {
-      res.data.rows.map((item) => {
-        item.type = item.type === 1 ? "产品" : "物料";
-      });
+      res.data.rows = res.data.rows.map((x) => ({
+        ...x,
+        ...JSON.parse(x.victoriatouristJson),
+        quantity: x.quantity,
+      }));
       listData.value =
         type === "refresh"
           ? res.data.rows
@@ -111,26 +293,29 @@ const getList = (type) => {
       }
       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 = () => {
-  req.value.id = active.value === "all" ? "" : active.value;
+const requestUrl = ref("/stock/pageByWarehouse");
+const handleChangeTab = (val) => {
+  if (val == "first") {
+    requestUrl.value = "/stock/pageByWarehouse";
+    listConfig.value = listConfigSet[0];
+  } else if (val == "second") {
+    requestUrl.value = "/stock/pageByProduct";
+    listConfig.value = listConfigSet[1];
+  } else {
+    requestUrl.value = "/stock/pageByProductSpu";
+    listConfig.value = listConfigSet[2];
+  }
   req.value.pageNum = 1;
   listData.value = [];
   getList();
 };
-getWarehouseData();
+
 getList();
 </script>