Parcourir la source

入库、出库、移库和盘库页面画写和接口联调完成

htc il y a 2 mois
Parent
commit
ed3e6e1030

+ 3 - 5
http/baseApi.js

@@ -1,8 +1,6 @@
-const BaseApi = 'http://gpu.ringzle.com:8082/witcarbon-app/app'
-//严工
-//const BaseApi = 'http://192.168.1.2:9013/witcarbon-app/app'
-
-
+// const BaseApi = 'http://gpu.ringzle.com:8082/witcarbon-app/app'
+//李勇
+const BaseApi = 'http://192.168.2.19:9023/witcarbon-app/app'
 
 export {
 	BaseApi

+ 19 - 0
main.js

@@ -48,6 +48,25 @@ Vue.prototype.$has = btnPermission;
 Vue.prototype.$api = api;
 Vue.prototype.$imgBase = "http://106.54.209.120:8666/image/";
 
+//重载uni.showToast,简化调用
+Vue.prototype.$showToast = function(title, duration = 2000, icon = "none") {
+	return uni.showToast({
+		title,
+		duration,
+		icon
+	})
+}
+//重载uni.showModal,简化调用
+Vue.prototype.$showModal = function(content) {
+	return uni.showModal({
+		title:'温馨提示',
+		content,
+		showCancel:false,
+		confirmText: '确定',
+		confirmColor: '#007A69'
+	})
+}
+
 // 引入全局uView
 import uView from '@/uni_modules/uview-ui'
 Vue.use(uView)

+ 78 - 76
pages.json

@@ -6,8 +6,6 @@
 				"navigationStyle": "custom"
 			}
 		},
-		
-		
 		{
 			"path": "pages/login/login",
 			"style": {
@@ -15,7 +13,6 @@
 				"navigationBarTitleText": "",
 				"enablePullDownRefresh": false
 			}
-
 		},
 		{
 			"path": "pages/login/forget",
@@ -30,7 +27,6 @@
 				"navigationBarTitleText": "",
 				"enablePullDownRefresh": false
 			}
-
 		},
 		{
 			"path": "pages/index/index",
@@ -54,16 +50,14 @@
 				"navigationStyle": "custom" // 隐藏系统导航栏
 			}
 
-		}
-
-		, {
+		}, 
+		{
 			"path": "pages/my/Personalinformation/Personalinformation",
 			"style": {
 				"navigationBarTitleText": "账号中心",
 				"enablePullDownRefresh": false,
 				"navigationBarBackgroundColor": "#FFFFFF"
 			}
-
 		}, {
 			"path": "pages/my/Commentssuggestions/Commentssuggestions",
 			"style": {
@@ -121,7 +115,6 @@
 				"navigationBarTitleText": "账单详情",
 				"enablePullDownRefresh": false
 			}
-
 		},
 		{
 			"path": "pages/index/Workordertodone/Workordertodone",
@@ -129,116 +122,98 @@
 				"navigationBarTitleText": "报修工单",
 				"enablePullDownRefresh": false
 			}
-
 		},
 		{
 			"path": "pages/index/Workordertodone/Workorderdetails/Workorderdetails",
 			"style": {
 				"navigationBarTitleText": "详情",
 				"enablePullDownRefresh": false
-
 			}
-
 		}
-
 		, {
 			"path": "pages/index/Immediatecollection/Immediatecollection",
 			"style": {
 				"navigationBarTitleText": "欠费待收",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/index/Immediatecollection/Chargedetails/Chargedetails",
 			"style": {
 				"navigationBarTitleText": "详情",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/Workorder/pay/pay",
 			"style": {
 				"navigationBarTitleText": "支付",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/index/BillPending/BillPending",
 			"style": {
 				"navigationBarTitleText": "账单详情",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/index/EquipmentException/EquipmentException",
 			"style": {
 				"navigationBarTitleText": "设备异常",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/index/Immediateinspection/Immediateinspection",
 			"style": {
 				"navigationBarTitleText": "巡检打卡",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/my/Myorder/Myorder",
 			"style": {
 				"navigationBarTitleText": "我的订单",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/my/Myorder/Orderdetails/Orderdetails",
 			"style": {
 				"navigationBarTitleText": "订单明细",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/Workorder/Arrearsrecord/Arrearsrecord",
 			"style": {
 				"navigationBarTitleText": "欠费记录",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/Workorder/Videosurveillance/Videosurveillance",
 			"style": {
 				"navigationBarTitleText": "视频监控",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/Workorder/AccessControl/AccessControl",
 			"style": {
 				"navigationBarTitleText": "门禁开关",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/Workorder/Videosurveillance/Videoplayback/Videoplayback",
 			"style": {
 				"navigationBarTitleText": "摄像头直播",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/index/Workordertodone/Toberepaired/Toberepaired",
 			"style": {
 				"navigationBarTitleText": "详情",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/index/Workordertodone/hasrepaired/hasrepaired",
 			"style": {
 				"navigationBarTitleText": "已维修",
 				"enablePullDownRefresh": false
 			}
-
 		},
 		{
 			"path": "pages/Workorder/Intelligentdoorlock/Intelligentdoorlock",
@@ -246,35 +221,30 @@
 				"navigationBarTitleText": "智能门锁",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/Workorder/Intelligentdoorlock/Tenantdetails/Tenantdetails",
 			"style": {
 				"navigationBarTitleText": "租户详情",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/Workorder/Intelligentdoorlock/Dooropeningrecord/Dooropeningrecord",
 			"style": {
 				"navigationBarTitleText": "开门记录",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/login/Privacyagreement",
 			"style": {
 				"navigationBarTitleText": "隐私协议",
 				"enablePullDownRefresh": false
 			}
-
 		}, {
 			"path": "pages/login/useragree",
 			"style": {
 				"navigationBarTitleText": "用户协议",
 				"enablePullDownRefresh": false
 			}
-
 		}
 	],
 	"subPackages": [
@@ -286,6 +256,82 @@
 					"style": {
 						"navigationStyle": "custom"
 					}
+				},
+				{
+					"path": "inStorage/index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "inStorage/add",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "inStorage/goods",
+					"style": {
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": true
+					}
+				},
+				{
+					"path": "outStorage/index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "outStorage/add",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "outStorage/goods",
+					"style": {
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": true
+					}
+				},
+				{
+					"path": "moveStorage/index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "moveStorage/add",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "moveStorage/goods",
+					"style": {
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": true
+					}
+				},
+				{
+					"path": "checkStorage/index",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "checkStorage/add",
+					"style": {
+						"navigationStyle": "custom"
+					}
+				},
+				{
+					"path": "checkStorage/goods",
+					"style": {
+						"navigationStyle": "custom",
+						"enablePullDownRefresh": true
+					}
 				}
 			]
 		}
@@ -295,50 +341,6 @@
 		"navigationBarBackgroundColor": "#FFFFFF",
 		"navigationBarTextStyle": "black"
 	},
-
-	// "tabBar": {
-	// 	"color": "#0C1935",
-	// 	"selectedColor": "#2E69EB",
-	// 	"borderStyle": "black",
-	// 	"backgroundColor": "#ffffff",
-	// 	"height": "55px",
-	// 	"fontSize": "10px",
-	// 	"iconWidth": "24px",
-	// 	"spacing": "3px",
-	// 	"list": [{
-	// 			"pagePath": "pages/index/index",
-	// 			"iconPath": "static/tab/h1.png",
-	// 						"selectedIconPath": "static/tab/h2.png",
-	// 			"text": "首页"
-	// 		},
-	// 		// {
-	// 		// 	"pagePath": "pages/equipment/equipment",
-	// 		// 	"iconPath": "static/tab/s1.png",
-	// 		// 				"selectedIconPath": "static/tab/s2.png",
-	// 		// 	"text": "设备"
-	// 		// },
-	// 		{
-	// 			"pagePath": "pages/Workorder/Workorder",
-	// 			"iconPath": "static/tab/w1.png",
-	// 						"selectedIconPath": "static/tab/w2.png",
-	// 			"text": "工作台"
-	// 		},
-	// 		// {
-	// 		// 	"pagePath": "pages/Energyconsumption/Energyconsumption",
-	// 		// 	"iconPath": "static/tab/e1.png",
-	// 		// 				"selectedIconPath": "static/tab/e2.png",
-	// 		// 	"text": "能耗"
-	// 		// },
-	// 		{
-	// 			"pagePath": "pages/my/my",
-	// 			"iconPath": "static/tab/y1.png",
-	// 						"selectedIconPath": "static/tab/y2.png",
-	// 			"text": "我的"
-	// 		}
-	// 	]
-
-	// },
-
 	"easycom": {
 		"^u-(.*)": "@/uni_modules/uview-ui/components/u-$1/u-$1.vue"
 	},

+ 343 - 0
pagesStorage/checkStorage/add.vue

@@ -0,0 +1,343 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='盘库'></cus-header>
+		<div class="box">
+			<div class="title">盘库单基本信息</div>
+			<div class="form">
+				<div class="item">
+					<div class="left"><span>*</span>盘库单号</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入盘库单号" v-model="checkDto.orderNo" @blur="e=>setReceipt(e,'orderNo')">
+					</div>
+				</div>
+				<div class="item">
+					<div class="left"><span>*</span>仓库</div>
+					<div class="right">
+						<text>{{checkDto.warehouseName}} ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">盈亏数</div>
+					<div class="right">
+						<input type="text" v-model="checkDto.totalQuantity" disabled>
+					</div>
+				</div>
+			</div>
+		</div>
+		<div class="box" :style="{'padding-bottom':checkDto.details.length?'0':'48rpx'}">
+			<div class="title">商品明细</div>
+			<div class="btn" @tap="toAddGoods">+ 新增库存</div>
+			<div class="goods">
+				<template v-if="checkDto.details.length">
+					<div class="good" v-for="(good,idx) in checkDto.details" :key="good.skuId">
+						<div class="title">
+							<text>{{good.item.itemName}}</text>
+							<image :src="imgBase+'storage/icon_remove_grey.png'" @tap="deleteGood(idx)" v-if="!good.id"></image>
+						</div>
+						<div class="info">
+							<div>规格信息:<span>{{good.itemSku.skuName||''}} / {{good.itemSku.grossWeight||0}}kg / {{good.itemSku.width||0}}X{{good.itemSku.height||0}}cm</span></div>
+						</div>
+						<div class="info">
+							<div>账面库存:<span>{{good.quantity||0}}</span></div>
+						</div>
+						<div class="info">
+							<div>盈 亏 数:<span>{{good.profitLoss||0}}</span></div>
+						</div>
+						<div class="num">
+							<text>实际库存:</text>
+							<u-number-box v-model="good.checkQuantity" button-size="48" :integer="true" inputWidth="102rpx"
+							 @change="e=>changeStorageNum(e,idx)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+					</div>
+				</template>
+			</div>
+		</div>
+		<div class="save">
+			<div class="btn" @tap="saveReceipt">完成盘库</div>
+		</div>
+		<u-picker title="仓库" :show="warehouseShow" :columns="warehouseList" keyName="warehouseName" 
+			@cancel="warehouseShow=false" @confirm="warehouseConfirm">
+		</u-picker>
+	</view>
+</template>
+
+<script>
+	import { generateNo } from '@/utils/common.js'
+	export default {
+		data(){
+			return {
+				checkDto:{
+					id: '',
+					orderNo: '',
+					orderStatus: 1,
+					warehouseId: '',
+					warehouseName: '',
+					totalQuantity: 0,
+					details: []
+				},
+				goodsList:[]
+			}
+		},
+		onLoad(option) {
+			this.checkDto.orderNo = generateNo('PK');
+			this.checkDto.warehouseId = option.warehouseId;
+			this.checkDto.warehouseName = option.warehouseName;
+			this.getGoodList();
+		},
+		methods:{
+			getGoodList(){
+				this.$api.get('/wms/inventory/boardList/item/?warehouseId='+this.checkDto.warehouseId).then(res=>{
+					if(res.data.code===0){
+						this.checkDto.details = res.data.data.list;
+						this.checkDto.details.forEach(d=>d.checkQuantity=+d.quantity);
+						this.computeNum();
+					}else this.$showToast(res.data.msg)
+				})
+			},
+			setReceipt(e,name){
+				this.checkDto[name] = e.target.value;
+			},
+			toAddGoods(){
+				let ids = this.goodsList.map(d=>d.skuId);
+				let exitIds = this.checkDto.details.map(d=>d.skuId);
+				uni.navigateTo({
+					url:'/pagesStorage/checkStorage/goods?ids='+ids+'&exitIds='+exitIds,
+					events:{
+						addGoods:list=>{
+							this.goodsList = list;
+							this.goodsList.forEach((d,i)=>{
+								d.quantity = 0;
+								d.checkQuantity = d.checknum;
+							})
+							this.checkDto.details = [...this.checkDto.details,...this.goodsList];
+							this.computeNum();
+						}
+					}
+				})
+			},
+			deleteGood(index){
+				this.checkDto.details.splice(index,1);
+				this.$nextTick(()=>{
+					this.computeNum();
+				})
+			},
+			changeStorageNum(e,index){
+				this.$set(this.checkDto.details[index],'checkQuantity',e.value);
+				this.$set(this.checkDto.details[index],'profitLoss',+e.value-(+this.checkDto.details[index].quantity));
+				this.$nextTick(()=>{
+					this.computeNum();
+				})
+			},
+			computeNum(){
+				this.checkDto.totalQuantity = this.checkDto.details.reduce((cur,pre)=>cur+(pre.checkQuantity-pre.quantity),0);
+			},
+			saveReceipt(){
+				if(!this.checkDto.orderNo) return this.$showToast('请输入盘库单号');
+				if(!this.checkDto.warehouseId) return this.$showToast('请选择仓库');
+				
+				let temp = JSON.parse(JSON.stringify(this.checkDto.details));
+				let details = temp.map(d=>{
+					return {
+						inventoryId: d?.id||'',
+					    skuId: d.itemSku.id,
+					    quantity: d.quantity,
+						checkQuantity:d.checkQuantity,
+					    warehouseId: this.checkDto.warehouseId,
+					}
+				})
+				this.checkDto.details = details;
+				
+				this.$api.post('/wms/checkOrder',this.checkDto).then(res=>{
+					if(res.data.code===0){
+						this.$showToast('盘库单新增成功');
+						setTimeout(()=>{
+							uni.redirectTo({
+								url:'/pagesStorage/checkStorage/index'
+							})
+						},1500)
+					}else this.$showToast(res.data.msg)
+				})
+			},
+		}
+	}
+</script>
+
+<style>
+	.storage-inp-ph{
+		color: #B9C0C8 !important;
+	}
+</style>
+<style scoped lang="less">
+	.page{
+		padding: 0 24rpx 186rpx;
+		background: #F4F8FB;
+		box-sizing: border-box;
+		
+		.box{
+			width: 100%;
+			padding: 36rpx 24rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-top: 20rpx;
+			
+			.title{
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 36rpx;
+				color: #1D2129;
+				line-height: 36rpx;
+				text-align: left;
+			}
+			
+			.form{
+				width: 100%;
+				margin-top: 36rpx;
+				.item{
+					width: 100%;
+					height: 90rpx;
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.left{
+						display: flex;
+						align-items: center;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 42rpx;
+						text-align: left;
+						span{
+							color: #F95050;
+						}
+					}
+					.right{
+						input{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 30rpx;
+							color: #4E5969;
+							line-height: 42rpx;
+							text-align: right;
+						}
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 30rpx;
+							color: #4E5969;
+							line-height: 42rpx;
+							text-align: right;
+							&.tip{
+								color: #B9C0C8;
+							}
+						}
+					}
+				}
+				.zdjs{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #198CFF;
+					line-height: 37rpx;
+					text-align: right;
+					margin-top: 9rpx;
+				}
+			}
+		
+			.btn{
+				width: 100%;
+				height: 64rpx;
+				border-radius: 16rpx;
+				border: 1rpx solid #198CFF;
+				margin-top: 26rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 26rpx;
+				color: #198CFF;
+				line-height: 64rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		
+			.goods{
+				width: 100%;
+				margin-top: 10rpx;
+				.good{
+					width: 100%;
+					padding: 36rpx 0;
+					box-sizing: border-box;
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+					&>div{
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+					}
+					.title{
+						text{
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 30rpx;
+							color: #1D2129;
+							line-height: 30rpx;
+							text-align: left;
+						}
+						image{
+							width: 28rpx;
+							height: 28rpx;
+						}
+					}
+					.info{
+						margin-top: 24rpx;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #86909C;
+						line-height: 24rpx;
+						span{
+							color: #4E5969;
+						}
+					}
+					.num,.money{
+						margin-top: 24rpx;
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+						}
+					}
+				}
+			}
+		}
+		
+		.save{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx 0;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 239 - 0
pagesStorage/checkStorage/goods.vue

@@ -0,0 +1,239 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='新增库存'></cus-header>
+		<div class="goods" v-if="list.length">
+			<div class="good" v-for="(good,index) in list" :key="good.skuId">
+				<div class="check" @click="changeCheck(index)">
+					<image :src="imgBase+'storage/icon_notchecked_grey.png'" v-if="!good.checked"></image>
+					<image :src="imgBase+'storage/icon_checked_blue.png'" v-else></image>
+				</div>
+				<div class="info">
+					<div class="name">{{good.item.itemName}}</div>
+					<div class="ggxx">
+						规格信息:<span>{{good.itemSku.skuName||''}} / {{good.itemSku.grossWeight||0}}kg / {{good.itemSku.width||0}}X{{good.itemSku.height||0}}cm</span>
+					</div>
+					<div class="price">
+						<div class="left">成本价:<span>¥{{good.itemSku.costPrice||0}}</span></div>
+						<div class="right">
+							<u-number-box v-model="good.checknum" button-size="48" :integer="true" inputWidth="102rpx" 
+							@change="e=>changeNum(e,index)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - '+(mt+70)+'px)'"></page-empty>
+		</template>
+		<div class="btn">
+			<div class="left">
+				<image :src="imgBase+'storage/icon_checked_blue.png'"></image>
+				<text>已选:{{selectNum||0}}</text>
+			</div>
+			<div class="confirm" @tap="confirmSelect">确定</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				list:[],
+				isOver:false,
+				params:{
+					page:1,
+					limit:99999
+				},
+				selectNum:0,
+				exitIds:[]
+			}
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			// this.getList();
+		},
+		onPullDownRefresh() {
+			this.params.page = 1;
+			this.isOver = false;
+			this.list = [];
+			this.getList();
+		},
+		watch:{
+			list:{
+				handler(newValue){
+					this.selectNum =  this.list.filter(l=>l.checked).length;
+				},
+				deep:true,
+				immediate:true
+			}
+		},
+		async onLoad(option) {
+			let exitIds = option.exitIds;
+			if(exitIds&&exitIds.indexOf(',')>-1) this.exitIds = exitIds.split(',');
+			else this.exitIds = exitIds;
+			
+			await this.getList();
+			let ids = option.ids;
+			if(ids&&ids.indexOf(',')>-1) ids = ids.split(',');
+			if(ids&&ids.length){
+				ids.forEach(item=>{
+					let fi = this.list.findIndex(l=>l.skuId===item);
+					if(fi>-1) this.$set(this.list[fi],'checked',true);
+				})
+			}
+		},
+		methods:{
+			async getList(){
+				let res = await this.$api.get('/wms/itemSku/page',this.params);
+				if(res.data.code===0){
+					if(this.list.length<res.data.data.total){
+						this.params.page++;
+						this.list = [...this.list,...res.data.data.list];
+						this.list.forEach((d,i)=>{
+							this.$set(this.list[i],'checked',false);
+							this.$set(this.list[i],'checknum',1);
+						})
+						this.exitIds.forEach(id=>{
+							this.list = this.list.filter(l=>l.skuId!==id)
+						})
+					}else this.isOver = true
+				}else this.$showModal(res.msg)
+			},
+			changeCheck(index){
+				this.$set(this.list[index],'checked',!this.list[index].checked);
+			},
+			changeNum(e,index){
+				this.$set(this.list[index],'checknum',e.value);
+			},
+			confirmSelect(){
+				let sn = this.list.filter(l=>l.checked).length;
+				if(sn<1) return this.$showToast('请至少选择一件商品');
+				let list = this.list.filter(l=>l.checked);
+				list.forEach(l=>l.inventoryNum = 0);
+				this.getOpenerEventChannel().emit('addGoods', list);
+				uni.navigateBack();
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		width: 100%;
+		padding-bottom: 160rpx;
+		box-sizing: border-box;
+		background: #F4F8FB;
+		
+		.goods{
+			width: calc(100% - 48rpx);
+			margin: 0 auto;
+			.good{
+				width: 100%;
+				padding: 34rpx 24rpx;
+				box-sizing: border-box;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				margin-top: 20rpx;
+				display: flex;
+				.check{
+					width: 56rpx;
+					image{
+						width: 36rpx;
+						height: 36rpx;
+					}
+				}
+				.info{
+					width: calc(100% - 56rpx);
+					.name{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						text-align: left;
+						overflow: hidden;
+						text-overflow: ellipsis;
+						white-space: nowrap;
+					}
+					.ggxx{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #86909C;
+						line-height: 24rpx;
+						text-align: left;
+						margin-top: 23rpx;
+						span{
+							color: #4E5969;
+						}
+					}
+					.price{
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+						margin-top: 23rpx;
+						.left{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+							span{
+								font-weight: bold;
+								font-size: 26rpx;
+								color: #FF4141;
+								margin-left: 24rpx;
+							}
+						}
+					}
+				}
+			}
+		}
+	
+		.btn{
+			width: 100%;
+			height: 140rpx;
+			padding: 16rpx 20rpx 0 30rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			.left{
+				display: flex;
+				align-items: center;
+				image{
+					width: 36rpx;
+					height: 36rpx;
+				}
+				text{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 30rpx;
+					color: #1D2129;
+					line-height: 42rpx;
+					text-align: left;
+					margin-left: 12rpx;
+				}
+			}
+			.confirm{
+				width: 200rpx;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 441 - 0
pagesStorage/checkStorage/index.vue

@@ -0,0 +1,441 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='盘库'></cus-header>
+		<status-tab :style="{'position':'fixed','top':mt+'px','left':'0','width':'100%'}" :list="typeList" @changeType="changeType"></status-tab>
+		<div class="boxs" v-if="dataList.length">
+			<div class="box" v-for="(item,index) in dataList" :key="item.id">
+				<div class="top">
+					<text>{{ item.orderNo||'' }}</text>
+					<div class="status" 
+						:class="{'wrk':item.orderStatus==0,'yrk':item.orderStatus==1,'zf':item.orderStatus==-1}"
+					>{{ receiptStatus[item.orderStatus]||'' }}</div>
+				</div>
+				<div class="content">
+					<div class="pre">
+						<div class="title">仓库</div>
+						<div class="nr">{{ item.warehouseName||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">盈亏数</div>
+						<div class="nr" :class="{'ks':item.totalQuantity<0}">{{ item.totalQuantity||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">操作时间</div>
+						<div class="nr">{{ item.updateDate||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">操作人</div>
+						<div class="nr">{{ item.updaterName||'' }}</div>
+					</div>
+				</div>
+			</div>
+			<page-loading :loading="isLoading"></page-loading>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - '+(mt+51+74+25)+'px)'" marginTop="51px"></page-empty>
+		</template>
+		<div class="add">
+			<div class="btn" @tap="show=true">盘库</div>
+		</div>
+		<u-popup :show="show" mode="bottom" @close="close">
+			<div class="select">
+				<div class="title">
+					选择仓库
+					<span @tap="close">X</span>
+				</div>
+				<div class="storage">
+					<div class="left">仓库</div>
+					<div class="right" @tap="selectWarehouse">
+						<text v-if="warehouseName">{{warehouseName}} ></text>
+						<text class="tip" v-else>请选择仓库 ></text>
+					</div>
+				</div>
+				<div class="btn" @tap="addCheck">确定</div>
+			</div>
+		</u-popup>
+		<u-picker title="仓库" :show="warehouseShow" :columns="warehouseList" keyName="warehouseName" 
+			@cancel="warehouseShow=false" @confirm="warehouseConfirm">
+		</u-picker>
+	</view>
+</template>
+
+<script>
+	import statusTab from '../components/statusTab/index.vue'
+	import pageLoading from '../components/pageLoading/index.vue'
+	import pageEmpty from '../components/pageEmpty/index.vue'
+	export default {
+		components:{
+			statusTab,
+			pageLoading,
+			pageEmpty
+		},
+		data(){
+			return {
+				typeList:[],
+				receiptStatus:{},
+				receiptType:{},
+				isOver:false,
+				isLoading:false,
+				params:{
+					page:1,
+					limit:10,
+					orderStatus:''
+				},
+				dataList:[],
+				show:false,
+				warehouseId:'',
+				warehouseName:'',
+				warehouseShow:false,
+				warehouseList:[]
+			}
+		},
+		onLoad() {
+			this.getSeceiptStatus();
+			this.getDataList();
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getDataList();
+		},
+		methods:{
+			changeType(status){
+				this.dataList = [];
+				this.params.orderStatus = status;
+				this.params.page = 1;
+				this.isOver = false;
+				this.isLoading = false;
+				this.getDataList();
+			},
+			getSeceiptStatus(){
+				this.$api.get('/sys/dict/data/getListByType/wms_check_status').then(res=>{
+					if(res.data.code===0){
+						this.typeList = res.data.data;
+						res.data.data.forEach(d=>{
+							this.receiptStatus[d.dictValue] = d.dictLabel;
+						})
+						this.typeList.unshift({dictValue:'',dictLabel:'全部'})
+					}else this.$showToast(res.data.msg)
+				});
+			},
+			getDataList(){
+				this.isLoading = true;
+				this.$api.get('/wms/checkOrder/page',this.params).then(res=>{
+					if(res.data.code===0){
+						if(this.dataList.length<res.data.data.total){
+							this.params.page++;
+							this.dataList = [...this.dataList,...res.data.data.list];
+							this.dataList.forEach((d,i)=>{
+								d.totalQuantity = parseInt(d.totalQuantity)||0
+							})
+						}else this.isOver = true
+					}else this.$showModal(res.data.msg)
+					this.isLoading = false;
+				});
+			},
+			addCheck(){
+				uni.navigateTo({
+					url:'/pagesStorage/checkStorage/add?warehouseId='+this.warehouseId+'&warehouseName='+this.warehouseName
+				})
+			},
+			close(){
+				this.warehouseId = '';
+				this.warehouseName = '';
+				this.show = false;
+			},
+			selectWarehouse(e){
+				this.warehouseShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/wms/warehouse/page').then(res=>{
+						if(res.data.code===0){
+							this.warehouseList = [res.data.data.list];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			warehouseConfirm(e){
+				this.warehouseId = e.value[0].id;
+				this.warehouseName = e.value[0].warehouseName;
+				this.warehouseShow = false;
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		padding: 0 0 186rpx;
+		background: #F4F8FB;
+		box-sizing: border-box;
+		
+		.boxs{
+			width: 100%;
+			padding: 20rpx 24rpx 0;
+			margin-top: 102rpx;
+			box-sizing: border-box;
+			.box{
+				width: 100%;
+				margin-top: 20rpx;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				&:first-child{
+					margin-top: 0;
+				}
+				.top{
+					width: 100%;
+					height: 90rpx;
+					padding: 0 24rpx;
+					box-sizing: border-box;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					border-bottom: 1rpx dotted #ECECEC;
+					text{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						text-align: left;
+					}
+					.status{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 26rpx;
+						line-height: 30rpx;
+						text-align: right;
+						&.wrk{
+							color: #FEB000;
+						}
+						&.yrk{
+							color: #14CC8C;
+						}
+						&.zf{
+							color: #FF4141;
+						}
+					}
+				}
+				.content{
+					width: 100%;
+					padding: 0 24rpx 40rpx;
+					box-sizing: border-box;
+					display: flex;
+					flex-wrap: wrap;
+					.pre{
+						width: 50%;
+						margin-top: 36rpx;
+						display: flex;
+						.title{
+							width: 116rpx;
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+						}
+						.nr{
+							width: calc(100% - 116rpx);
+							font-family: PingFangSC, PingFang SC;
+							font-weight: bold;
+							font-size: 26rpx;
+							color: #1D2129;
+							line-height: 24rpx;
+							text-align: left;
+						    white-space: nowrap;
+						    text-overflow: ellipsis;
+						    overflow: hidden;
+							&.money{
+								color: #F95050;
+							}
+							&.ks{
+								color: #FF4141;
+							}
+						}
+						&.bfb{
+							width: 100%;
+						}
+					}
+				}
+				.goods{
+					width: calc(100% - 20rpx);
+					margin: 0 auto 40rpx;
+					.good{
+						width: 100%;
+						padding: 36rpx 16rpx;
+						box-sizing: border-box;
+						background: #F0F8FE;
+						box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+						&>div{
+							display: flex;
+							align-items: center;
+							justify-content: space-between;
+						}
+						.name_price{
+							text{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 28rpx;
+								color: #1D2129;
+								line-height: 30rpx;
+								text-align: left;
+							}
+							span{
+								font-family: PingFang-SC, PingFang-SC;
+								font-weight: bold;
+								font-size: 26rpx;
+								color: #F95050;
+								line-height: 26rpx;
+								text-align: right;
+							}
+						}
+						.info_num{
+							margin-top: 24rpx;
+							.info{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								text-align: left;
+								span{
+									color: #4E5969;
+								}
+							}
+							.num{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								span{
+									font-weight: bold;
+									font-size: 26rpx;
+									color: #4E5969;
+								}
+							}
+						}
+					}
+				}
+				.more{
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					text{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #198CFF;
+						line-height: 28rpx;
+					}
+					image{
+						width: 24rpx;
+						height: 24rpx;
+						margin-left: 10rpx;
+						&.sq{
+							transform: rotate(180deg);
+						}
+					}
+				}
+			}
+		}
+	
+		.add{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx 0;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+		
+		.select{
+			width: 100%;
+			padding: 48rpx 24rpx 40rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			.title{
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 36rpx;
+				color: #1D2129;
+				line-height: 36rpx;
+				text-align: center;
+				position: relative;
+				span{
+					font-size: 36rpx;
+					color: #999999;
+					position: absolute;
+					right: 24rpx;
+				}
+			}
+			.storage{
+				width: 100%;
+				height: 90rpx;
+				background: #FFFFFF;
+				box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				margin-top: 127rpx;
+				.left{
+					font-family: PingFang-SC, PingFang-SC;
+					font-weight: bold;
+					font-size: 30rpx;
+					color: #1D2129;
+					line-height: 42rpx;
+					text-align: left;
+				}
+				.right{
+					input{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #4E5969;
+						line-height: 42rpx;
+						text-align: right;
+					}
+					text{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #4E5969;
+						line-height: 42rpx;
+						text-align: right;
+						&.tip{
+							color: #B9C0C8;
+						}
+					}
+				}
+			}
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+				margin-top: 356rpx;
+			}
+		}
+	}
+</style>

+ 37 - 0
pagesStorage/components/pageEmpty/index.vue

@@ -0,0 +1,37 @@
+<template>
+	<div class="page-empty" :style="{'height':height,'margin-top':marginTop}">
+		<u-empty text="暂无数据" textSize="26rpx" width="332rpx" height="332rpx" mode="order" icon="http://cdn.uviewui.com/uview/empty/order.png"></u-empty>
+	</div>
+</template>
+
+<script>
+	export default {
+		props:{
+			height:{
+				typeof: String,
+				default: '100vh'
+			},
+			marginTop:{
+				typeof: String,
+				default: '0px'
+			}
+		},
+		data(){
+			return {
+				
+			}
+		},
+		methods:{
+			
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page-empty{
+		width: 100%;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+	}
+</style>

+ 43 - 0
pagesStorage/components/pageLoading/index.vue

@@ -0,0 +1,43 @@
+<template>
+	<view class="page">
+		<template v-if="loading">
+			<u-loading-icon text="正在加载中..." textSize="26"></u-loading-icon>
+		</template>
+		<template v-else>
+			<p>已经到底啦~</p>
+		</template>
+	</view>
+</template>
+
+<script>
+	export default {
+		props:{
+			loading:{
+				typeof: Boolean,
+				default: false
+			}
+		},
+		data(){
+			return {
+				
+			}
+		},
+		methods:{
+			
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		width: 100%;
+		display: flex;
+		align-items: center;
+		justify-content: center;
+		margin-top: 30rpx;
+		p{
+			font-size: 26rpx;
+			color: lightgray;
+		}
+	}
+</style>

+ 71 - 0
pagesStorage/components/statusTab/index.vue

@@ -0,0 +1,71 @@
+<template>
+	<view class="page">
+		<template v-if="list.length">
+			<div class="item" :style="{'width':'calc(100% / '+list.length+')'}"
+				:class="{'active':idx===index}"
+				v-for="(item,index) in list" 
+				:key="item.dictValue" 
+				@tap="changeType(index,item.dictValue)">
+				{{item.dictLabel}}
+			</div>
+		</template>
+	</view>
+</template>
+
+<script>
+	export default {
+		props:{
+			list:{
+				typeof:Array,
+				default:[]
+			}
+		},
+		data(){
+			return {
+				idx:0
+			}
+		},
+		methods:{
+			changeType(index,value){
+				this.idx = index;
+				this.$emit('changeType',value)
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		height: 102rpx;
+		display: flex;
+		background: #fff;
+		.item{
+			height: 100%;
+			position: relative;
+			display: flex;
+			align-items: center;
+			justify-content: center;
+			font-family: PingFangSC, PingFang SC;
+			font-weight: 400;
+			font-size: 28rpx;
+			color: #1D2129;
+			line-height: 40rpx;
+			&.active{
+				color: #198CFF;
+				font-size: 32rpx;
+				font-weight: bold;
+				&::after{
+					content: '';
+					width: 36rpx;
+					height: 8rpx;
+					border-radius: 4rpx;
+					background: #198CFF;
+					position: absolute;
+					left: 50%;
+					margin-left: -18rpx;
+					bottom: 8rpx;
+				}
+			}
+		}
+	}
+</style>

+ 9 - 5
pagesStorage/home.vue

@@ -14,7 +14,7 @@
 			</div>
 		</div>
 		<div class="menus">
-			<div class="item" v-for="(item,index) in menuList" :key="index">
+			<div class="item" v-for="(item,index) in menuList" :key="index" @tap="toTurn(item.path)">
 				<image :src="item.icon" :class="index<4?'img1':'img2'"></image>
 				<p :class="index<4?'p1':'p2'">{{item.title}}</p>
 			</div>
@@ -61,22 +61,22 @@
 					{
 						icon:this.$imgBase+'storage/home_icon_rk.png',
 						title:'入库',
-						path:''
+						path:'/pagesStorage/inStorage/index'
 					},
 					{
 						icon:this.$imgBase+'storage/home_icon_ck.png',
 						title:'出库',
-						path:''
+						path:'/pagesStorage/outStorage/index'
 					},
 					{
 						icon:this.$imgBase+'storage/home_icon_pk.png',
 						title:'盘库',
-						path:''
+						path:'/pagesStorage/checkStorage/index'
 					},
 					{
 						icon:this.$imgBase+'storage/home_icon_yk.png',
 						title:'移库',
-						path:''
+						path:'/pagesStorage/moveStorage/index'
 					},
 					{
 						icon:this.$imgBase+'storage/home_icon_kcjl.png',
@@ -104,6 +104,10 @@
 			}
 		},
 		methods:{
+			toTurn(url){
+				if(!url) return;
+				uni.navigateTo({ url })
+			},
 			// 库存数量占比
 			async initKcslzb() {
 				const chart = await this.$refs.kcslzbChartRef.init(echarts);

+ 424 - 0
pagesStorage/inStorage/add.vue

@@ -0,0 +1,424 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='新增'></cus-header>
+		<div class="box">
+			<div class="title">入库单基本信息</div>
+			<div class="form">
+				<div class="item">
+					<div class="left"><span>*</span>入库单号</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入入库单号" v-model="receiptDto.orderNo" @blur="e=>setReceipt(e,'orderNo')">
+					</div>
+				</div>
+				<div class="item">
+					<div class="left"><span>*</span>仓库</div>
+					<div class="right" @tap="selectWarehouse">
+						<text v-if="receiptDto.warehouseName">{{receiptDto.warehouseName}} ></text>
+						<text class="tip" v-else>请选择仓库 ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">入库类型</div>
+					<div class="right" @tap="selectReceiptType">
+						<text v-if="receiptDto.optTypeName">{{receiptDto.optTypeName}} ></text>
+						<text class="tip" v-else>请选择 ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">供应商</div>
+					<div class="right" @tap="selectMerchant">
+						<text v-if="receiptDto.merchantName">{{receiptDto.merchantName}} ></text>
+						<text class="tip" v-else>请选择 ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">业务单号</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入" v-model="receiptDto.bizOrderNo" @blur="e=>setReceipt(e,'bizOrderNo')">
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">总数量</div>
+					<div class="right">
+						<input type="text" v-model="receiptDto.totalQuantity" disabled>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">总金额</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入" v-model="receiptDto.totalAmount"  @blur="e=>setReceipt(e,'totalAmount')">
+					</div>
+				</div>
+				<div class="zdjs" @tap="autoCalculate">自动计算</div>
+			</div>
+		</div>
+		<div class="box" :style="{'padding-bottom':receiptDto.details.length?'0':'48rpx'}">
+			<div class="title">商品明细</div>
+			<div class="btn" @tap="toAddGoods">+ 添加商品</div>
+			<div class="goods">
+				<template v-if="receiptDto.details.length">
+					<div class="good" v-for="(good,idx) in receiptDto.details" :key="good.skuId">
+						<div class="title">
+							<text>{{good.item.itemName}}</text>
+							<image :src="imgBase+'storage/icon_remove_grey.png'" @tap="deleteGood(idx)"></image>
+						</div>
+						<div class="info">
+							<div>规格信息:<span>{{good.itemSku.skuName||''}} / {{good.itemSku.grossWeight||0}}kg / {{good.itemSku.width||0}}X{{good.itemSku.height||0}}cm</span></div>
+						</div>
+						<div class="num">
+							<text>入库数量:</text>
+							<u-number-box v-model="good.quantity" button-size="48" :integer="true" inputWidth="102rpx"
+							 @change="e=>changeRkNum(e,idx)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+						<div class="num">
+							<text>金额:</text>
+							<u-number-box v-model="good.amount" button-size="48" :integer="false" :canSmall="true" inputWidth="102rpx" 
+							@change="e=>changeRkMoney(e,idx)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+					</div>
+				</template>
+			</div>
+		</div>
+		<div class="save">
+			<div class="btn" @tap="saveReceipt">保存</div>
+		</div>
+		<u-picker title="仓库" :show="warehouseShow" :columns="warehouseList" keyName="warehouseName" 
+			@cancel="warehouseShow=false" @confirm="warehouseConfirm">
+		</u-picker>
+		<u-picker title="入库类型" :show="receiptTypeShow" :columns="receiptTypeList" keyName="dictLabel" 
+			@cancel="receiptTypeShow=false" @confirm="receiptTypeConfirm">
+		</u-picker>
+		<u-picker title="供应商" :show="merchantShow" :columns="merchantList" keyName="merchantName" 
+			@cancel="merchantShow=false" @confirm="merchantConfirm">
+		</u-picker>
+	</view>
+</template>
+
+<script>
+	import { generateNo } from '@/utils/common.js'
+	export default {
+		data(){
+			return {
+				receiptDto:{
+					id: '',
+					orderNo: '',
+					optType: '',
+					optTypeName: '',
+					merchantId: '',
+					merchantName: '',
+					bizOrderNo: '',
+					totalAmount: '',
+					orderStatus: 1,
+					warehouseId: '',
+					warehouseName: '',
+					totalQuantity: 0,
+					details: []
+				},
+				warehouseShow:false,
+				warehouseList:[],
+				receiptTypeShow:false,
+				receiptTypeList:[],
+				merchantShow:false,
+				merchantList:[],
+			}
+		},
+		mounted() {
+			this.receiptDto.orderNo = generateNo('RK');
+		},
+		methods:{
+			selectWarehouse(){
+				this.warehouseShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/wms/warehouse/page').then(res=>{
+						if(res.data.code===0){
+							this.warehouseList = [res.data.data.list];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			warehouseConfirm(e){
+				this.receiptDto.warehouseId = e.value[0].id;
+				this.receiptDto.warehouseName = e.value[0].warehouseName;
+				this.warehouseShow = false;
+			},
+			selectReceiptType(){
+				this.receiptTypeShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/sys/dict/data/getListByType/wms_receipt_type').then(res=>{
+						if(res.data.code===0){
+							this.receiptTypeList = [res.data.data];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			receiptTypeConfirm(e){
+				this.receiptDto.optType = e.value[0].dictValue;
+				this.receiptDto.optTypeName = e.value[0].dictLabel;
+				this.receiptTypeShow = false;
+			},
+			selectMerchant(){
+				this.merchantShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/wms/merchant/page').then(res=>{
+						if(res.data.code===0){
+							this.merchantList = [res.data.data.list];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			merchantConfirm(e){
+				this.receiptDto.merchantId = e.value[0].id;
+				this.receiptDto.merchantName = e.value[0].merchantName;
+				this.merchantShow = false;
+			},
+			setReceipt(e,name){
+				this.receiptDto[name] = e.target.value;
+			},
+			autoCalculate(){
+				this.receiptDto.totalAmount = this.receiptDto.details.reduce((cur,pre)=>cur+(+pre.amount||0),0);
+			},
+			toAddGoods(){
+				let ids = this.receiptDto.details.map(d=>d.skuId);
+				uni.navigateTo({
+					url:'/pagesStorage/inStorage/goods?ids='+ids,
+					events:{
+						addGoods:list=>{
+							this.receiptDto.details = list;
+							this.receiptDto.details.forEach((d,i)=>{
+								let amount = d.checknum*d.itemSku.costPrice;
+								this.$set(this.receiptDto.details[i],'amount',amount);
+								this.$set(this.receiptDto.details[i],'quantity',d.checknum);
+							})
+							this.computeNum();
+						}
+					}
+				})
+			},
+			deleteGood(index){
+				this.receiptDto.details.splice(index,1);
+				this.$nextTick(()=>{
+					this.computeNum();
+				})
+			},
+			changeRkNum(e,index){
+				this.$set(this.receiptDto.details[index],'quantity',e.value);
+				this.$nextTick(()=>{
+					this.computeNum();
+				})
+			},
+			changeRkMoney(e,index){
+				this.$set(this.receiptDto.details[index],'amount',e.value);
+			},
+			computeNum(){
+				this.receiptDto.totalQuantity = this.receiptDto.details.reduce((cur,pre)=>cur+pre.quantity,0);
+			},
+			saveReceipt(){
+				if(!this.receiptDto.orderNo) return this.$showToast('请输入入库单号');
+				if(!this.receiptDto.warehouseId) return this.$showToast('请选择仓库');
+				
+				let temp = JSON.parse(JSON.stringify(this.receiptDto.details));
+				let details = temp.map(d=>{
+					return {
+						id: d?.id||'',
+					    skuId: d.itemSku.id,
+					    amount: d.amount,
+					    quantity: d.quantity,
+					    warehouseId: this.receiptDto.warehouseId,
+					}
+				})
+				this.receiptDto.details = details;
+				
+				this.$api.post('/wms/receiptOrder',this.receiptDto).then(res=>{
+					if(res.data.code===0){
+						this.$showToast('入库单新增成功');
+						setTimeout(()=>{
+							uni.redirectTo({
+								url:'/pagesStorage/inStorage/index'
+							})
+						},1500)
+					}else this.$showToast(res.data.msg)
+				})
+			},
+		}
+	}
+</script>
+
+<style>
+	.storage-inp-ph{
+		color: #B9C0C8 !important;
+	}
+</style>
+<style scoped lang="less">
+	.page{
+		padding: 0 24rpx 186rpx;
+		background: #F4F8FB;
+		box-sizing: border-box;
+		
+		.box{
+			width: 100%;
+			padding: 36rpx 24rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-top: 20rpx;
+			
+			.title{
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 36rpx;
+				color: #1D2129;
+				line-height: 36rpx;
+				text-align: left;
+			}
+			
+			.form{
+				width: 100%;
+				margin-top: 36rpx;
+				.item{
+					width: 100%;
+					height: 90rpx;
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.left{
+						display: flex;
+						align-items: center;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 42rpx;
+						text-align: left;
+						span{
+							color: #F95050;
+						}
+					}
+					.right{
+						input{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 30rpx;
+							color: #4E5969;
+							line-height: 42rpx;
+							text-align: right;
+						}
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 30rpx;
+							color: #4E5969;
+							line-height: 42rpx;
+							text-align: right;
+							&.tip{
+								color: #B9C0C8;
+							}
+						}
+					}
+				}
+				.zdjs{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #198CFF;
+					line-height: 37rpx;
+					text-align: right;
+					margin-top: 9rpx;
+				}
+			}
+		
+			.btn{
+				width: 100%;
+				height: 64rpx;
+				border-radius: 16rpx;
+				border: 1rpx solid #198CFF;
+				margin-top: 26rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 26rpx;
+				color: #198CFF;
+				line-height: 64rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		
+			.goods{
+				width: 100%;
+				margin-top: 10rpx;
+				.good{
+					width: 100%;
+					padding: 36rpx 0;
+					box-sizing: border-box;
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+					&>div{
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+					}
+					.title{
+						text{
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 30rpx;
+							color: #1D2129;
+							line-height: 30rpx;
+							text-align: left;
+						}
+						image{
+							width: 28rpx;
+							height: 28rpx;
+						}
+					}
+					.info{
+						margin-top: 24rpx;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #86909C;
+						line-height: 24rpx;
+						span{
+							color: #4E5969;
+						}
+					}
+					.num,.money{
+						margin-top: 24rpx;
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+						}
+					}
+				}
+			}
+		}
+		
+		.save{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx 0;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 230 - 0
pagesStorage/inStorage/goods.vue

@@ -0,0 +1,230 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='添加商品'></cus-header>
+		<div class="goods" v-if="list.length">
+			<div class="good" v-for="(good,index) in list" :key="good.skuId">
+				<div class="check" @click="changeCheck(index)">
+					<image :src="imgBase+'storage/icon_notchecked_grey.png'" v-if="!good.checked"></image>
+					<image :src="imgBase+'storage/icon_checked_blue.png'" v-else></image>
+				</div>
+				<div class="info">
+					<div class="name">{{good.item.itemName}}</div>
+					<div class="ggxx">
+						规格信息:<span>{{good.itemSku.skuName||''}} / {{good.itemSku.grossWeight||0}}kg / {{good.itemSku.width||0}}X{{good.itemSku.height||0}}cm</span>
+					</div>
+					<div class="price">
+						<div class="left">成本价:<span>¥{{good.itemSku.costPrice||0}}</span></div>
+						<div class="right">
+							<u-number-box v-model="good.checknum" button-size="48" :integer="true" inputWidth="102rpx" 
+							@change="e=>changeNum(e,index)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - '+(mt+70)+'px)'"></page-empty>
+		</template>
+		<div class="btn">
+			<div class="left">
+				<image :src="imgBase+'storage/icon_checked_blue.png'"></image>
+				<text>已选:{{selectNum||0}}</text>
+			</div>
+			<div class="confirm" @tap="confirmSelect">确定</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				list:[],
+				isOver:false,
+				params:{
+					page:1,
+					limit:10
+				},
+				selectNum:0
+			}
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getList();
+		},
+		onPullDownRefresh() {
+			this.params.page = 1;
+			this.isOver = false;
+			this.list = [];
+			this.getList();
+		},
+		watch:{
+			list:{
+				handler(newValue){
+					this.selectNum =  this.list.filter(l=>l.checked).length;
+				},
+				deep:true,
+				immediate:true
+			}
+		},
+		async onLoad(option) {
+			let ids = option.ids;
+			if(ids&&ids.indexOf(',')>-1) ids = ids.split(',');
+			await this.getList();
+			if(ids&&ids.length){
+				ids.forEach(item=>{
+					let fi = this.list.findIndex(l=>l.skuId===item);
+					if(fi>-1) this.$set(this.list[fi],'checked',true);
+				})
+			}
+		},
+		methods:{
+			async getList(){
+				let res = await this.$api.get('/wms/itemSku/page',this.params);
+				if(res.data.code===0){
+					if(this.list.length<res.data.data.total){
+						this.params.page++;
+						this.list = [...this.list,...res.data.data.list];
+						this.list.forEach((d,i)=>{
+							this.$set(this.list[i],'checked',false);
+							this.$set(this.list[i],'checknum',1);
+						})
+					}else this.isOver = true
+				}else this.$showModal(res.msg)
+			},
+			changeCheck(index){
+				this.$set(this.list[index],'checked',!this.list[index].checked);
+			},
+			changeNum(e,index){
+				this.$set(this.list[index],'checknum',e.value);
+			},
+			confirmSelect(){
+				let sn = this.list.filter(l=>l.checked).length;
+				if(sn<1) return this.$showToast('请至少选择一件商品');
+				let list = this.list.filter(l=>l.checked);
+				this.getOpenerEventChannel().emit('addGoods', list);
+				uni.navigateBack();
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		width: 100%;
+		padding-bottom: 160rpx;
+		box-sizing: border-box;
+		background: #F4F8FB;
+		
+		.goods{
+			width: calc(100% - 48rpx);
+			margin: 0 auto;
+			.good{
+				width: 100%;
+				padding: 34rpx 24rpx;
+				box-sizing: border-box;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				margin-top: 20rpx;
+				display: flex;
+				.check{
+					width: 56rpx;
+					image{
+						width: 36rpx;
+						height: 36rpx;
+					}
+				}
+				.info{
+					width: calc(100% - 56rpx);
+					.name{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						text-align: left;
+						overflow: hidden;
+						text-overflow: ellipsis;
+						white-space: nowrap;
+					}
+					.ggxx{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #86909C;
+						line-height: 24rpx;
+						text-align: left;
+						margin-top: 23rpx;
+						span{
+							color: #4E5969;
+						}
+					}
+					.price{
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+						margin-top: 23rpx;
+						.left{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+							span{
+								font-weight: bold;
+								font-size: 26rpx;
+								color: #FF4141;
+								margin-left: 24rpx;
+							}
+						}
+					}
+				}
+			}
+		}
+	
+		.btn{
+			width: 100%;
+			height: 140rpx;
+			padding: 16rpx 20rpx 0 30rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			.left{
+				display: flex;
+				align-items: center;
+				image{
+					width: 36rpx;
+					height: 36rpx;
+				}
+				text{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 30rpx;
+					color: #1D2129;
+					line-height: 42rpx;
+					text-align: left;
+					margin-left: 12rpx;
+				}
+			}
+			.confirm{
+				width: 200rpx;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 367 - 0
pagesStorage/inStorage/index.vue

@@ -0,0 +1,367 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='入库'></cus-header>
+		<status-tab :style="{'position':'fixed','top':mt+'px','left':'0','width':'100%'}" :list="typeList" @changeType="changeType"></status-tab>
+		<div class="boxs" v-if="dataList.length">
+			<div class="box" v-for="(item,index) in dataList" :key="item.id">
+				<div class="top">
+					<text>{{ item.orderNo||'' }}</text>
+					<div class="status" 
+						:class="{'wrk':item.orderStatus==0,'yrk':item.orderStatus==1,'zf':item.orderStatus==-1}"
+					>{{ receiptStatus[item.orderStatus]||'' }}</div>
+				</div>
+				<div class="content">
+					<div class="pre">
+						<div class="title">总数量</div>
+						<div class="nr">{{ item.totalQuantity||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">总金额</div>
+						<div class="nr money">¥{{ item.totalAmount||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">仓库</div>
+						<div class="nr">{{ item.warehouseName||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">入库类型</div>
+						<div class="nr">{{ receiptType[item.optType]||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">操作人</div>
+						<div class="nr">{{ item.updaterName||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">操作时间</div>
+						<div class="nr">{{ item.updateDate||'' }}</div>
+					</div>
+					<div class="pre bfb">
+						<div class="title">供应商</div>
+						<div class="nr">{{ item.merchantName||'' }}</div>
+					</div>
+				</div>
+				<div class="goods" v-if="item.goodsList.length&&item.goodsShow">
+					<div class="good" v-for="(good,idx) in item.goodsList" :key="good.id">
+						<div class="name_price">
+							<text>{{ good.item.itemName }}</text>
+							<span>¥{{ good.amount||'' }}</span>
+						</div>
+						<div class="info_num">
+							<div class="info">规格信息:<span>{{ good.itemSku.skuName }}</span></div>
+							<div class="num">数量:<span>{{ good.quantity }}</span></div>
+						</div>
+					</div>
+				</div>
+				<div class="more" @tap="getGoodsListById(item.id,index)">
+					<text>{{ item.goodsShow?'收起':'商品明细' }}</text>
+					<image :src="imgBase+'storage/icon_jtdown_blue.png'" :class="{'sq':item.goodsShow}"></image>
+				</div>
+			</div>
+			<page-loading :loading="isLoading"></page-loading>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - '+(mt+51+74+25)+'px)'" marginTop="51px"></page-empty>
+		</template>
+		<div class="add">
+			<div class="btn" @tap="addReceipt">新增入库单</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	import statusTab from '../components/statusTab/index.vue'
+	import pageLoading from '../components/pageLoading/index.vue'
+	import pageEmpty from '../components/pageEmpty/index.vue'
+	export default {
+		components:{
+			statusTab,
+			pageLoading,
+			pageEmpty
+		},
+		data(){
+			return {
+				typeList:[],
+				receiptStatus:{},
+				receiptType:{},
+				isOver:false,
+				isLoading:false,
+				params:{
+					page:1,
+					limit:10,
+					orderStatus:''
+				},
+				dataList:[],
+			}
+		},
+		onLoad() {
+			this.getSeceiptStatus();
+			this.getSeceiptType();
+			this.getDataList();
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getDataList();
+		},
+		methods:{
+			changeType(status){
+				this.dataList = [];
+				this.params.orderStatus = status;
+				this.params.page = 1;
+				this.isOver = false;
+				this.isLoading = false;
+				this.getDataList();
+			},
+			getSeceiptStatus(){
+				this.$api.get('/sys/dict/data/getListByType/wms_receipt_status').then(res=>{
+					if(res.data.code===0){
+						this.typeList = res.data.data;
+						res.data.data.forEach(d=>{
+							this.receiptStatus[d.dictValue] = d.dictLabel;
+						})
+						this.typeList.unshift({dictValue:'',dictLabel:'全部'})
+					}else this.$showToast(res.data.msg)
+				});
+			},
+			async getSeceiptType(){
+				let res = await this.$api.get('/sys/dict/data/getListByType/wms_receipt_type');
+				if(res.data.code===0){
+					res.data.data.forEach(d=>{
+						this.receiptType[d.dictValue] = d.dictLabel;
+					})
+				}else this.$showToast(res.data.msg)
+			},
+			getDataList(){
+				this.isLoading = true;
+				this.$api.get('/wms/receiptOrder/page',this.params).then(res=>{
+					if(res.data.code===0){
+						if(this.dataList.length<res.data.data.total){
+							this.params.page++;
+							this.dataList = [...this.dataList,...res.data.data.list];
+							this.dataList.forEach((d,i)=>{
+								this.$set(this.dataList[i],'goodsList',[]);
+								this.$set(this.dataList[i],'goodsShow',false);
+							})
+						}else this.isOver = true
+					}else this.$showModal(res.data.msg)
+					this.isLoading = false;
+				});
+			},
+			getGoodsListById(id,index){
+				this.$set(this.dataList[index],'goodsShow',!this.dataList[index].goodsShow);
+				if(!this.dataList[index].goodsShow) return
+				this.$api.get('/wms/receiptOrder/getByReceiptOrderId/'+id).then(res=>{
+					if(res.data.code===0){
+						this.$set(this.dataList[index],'goodsList',res.data.data);
+					}else this.$showModal(res.msg)
+				})
+			},
+			addReceipt(){
+				uni.navigateTo({
+					url:'/pagesStorage/inStorage/add'
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		padding: 0 0 186rpx;
+		background: #F4F8FB;
+		box-sizing: border-box;
+		
+		.boxs{
+			width: 100%;
+			padding: 20rpx 24rpx 0;
+			margin-top: 102rpx;
+			box-sizing: border-box;
+			.box{
+				width: 100%;
+				margin-top: 20rpx;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				padding-bottom: 40rpx;
+				&:first-child{
+					margin-top: 0;
+				}
+				.top{
+					width: 100%;
+					height: 90rpx;
+					padding: 0 24rpx;
+					box-sizing: border-box;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					border-bottom: 1rpx dotted #ECECEC;
+					text{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						text-align: left;
+					}
+					.status{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 26rpx;
+						line-height: 30rpx;
+						text-align: right;
+						&.wrk{
+							color: #FEB000;
+						}
+						&.yrk{
+							color: #14CC8C;
+						}
+						&.zf{
+							color: #FF4141;
+						}
+					}
+				}
+				.content{
+					width: 100%;
+					padding: 0 24rpx 40rpx;
+					box-sizing: border-box;
+					display: flex;
+					flex-wrap: wrap;
+					.pre{
+						width: 50%;
+						margin-top: 36rpx;
+						display: flex;
+						.title{
+							width: 116rpx;
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+						}
+						.nr{
+							width: calc(100% - 116rpx);
+							font-family: PingFangSC, PingFang SC;
+							font-weight: bold;
+							font-size: 26rpx;
+							color: #1D2129;
+							line-height: 24rpx;
+							text-align: left;
+						    white-space: nowrap;
+						    text-overflow: ellipsis;
+						    overflow: hidden;
+							&.money{
+								color: #F95050;
+							}
+						}
+						&.bfb{
+							width: 100%;
+						}
+					}
+				}
+				.goods{
+					width: calc(100% - 20rpx);
+					margin: 0 auto 40rpx;
+					.good{
+						width: 100%;
+						padding: 36rpx 16rpx;
+						box-sizing: border-box;
+						background: #F0F8FE;
+						box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+						&>div{
+							display: flex;
+							align-items: center;
+							justify-content: space-between;
+						}
+						.name_price{
+							text{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 28rpx;
+								color: #1D2129;
+								line-height: 30rpx;
+								text-align: left;
+							}
+							span{
+								font-family: PingFang-SC, PingFang-SC;
+								font-weight: bold;
+								font-size: 26rpx;
+								color: #F95050;
+								line-height: 26rpx;
+								text-align: right;
+							}
+						}
+						.info_num{
+							margin-top: 24rpx;
+							.info{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								text-align: left;
+								span{
+									color: #4E5969;
+								}
+							}
+							.num{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								span{
+									font-weight: bold;
+									font-size: 26rpx;
+									color: #4E5969;
+								}
+							}
+						}
+					}
+				}
+				.more{
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					text{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #198CFF;
+						line-height: 28rpx;
+					}
+					image{
+						width: 24rpx;
+						height: 24rpx;
+						margin-left: 10rpx;
+						&.sq{
+							transform: rotate(180deg);
+						}
+					}
+				}
+			}
+		}
+	
+		.add{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx 0;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 395 - 0
pagesStorage/moveStorage/add.vue

@@ -0,0 +1,395 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='新增'></cus-header>
+		<div class="box">
+			<div class="title">移库单基本信息</div>
+			<div class="form">
+				<div class="item">
+					<div class="left"><span>*</span>移库单号</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入移库单号" v-model="movementDto.orderNo" @blur="e=>setDto(e,'orderNo')">
+					</div>
+				</div>
+				<div class="item">
+					<div class="left"><span>*</span>源仓库</div>
+					<div class="right" @tap="selectSourceWarehouse">
+						<text v-if="movementDto.sourceWarehouseName">{{movementDto.sourceWarehouseName}} ></text>
+						<text class="tip" v-else>请选择仓库 ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left"><span>*</span>目标仓库</div>
+					<div class="right" @tap="selectTargetWarehouse">
+						<text v-if="movementDto.targetWarehouseName">{{movementDto.targetWarehouseName}} ></text>
+						<text class="tip" v-else>请选择仓库 ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">总数量</div>
+					<div class="right">
+						<input type="text" v-model="movementDto.totalQuantity" disabled>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">总金额</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入" v-model="movementDto.totalAmount"  @blur="e=>setDto(e,'totalAmount')">
+					</div>
+				</div>
+				<div class="zdjs" @tap="autoCalculate">自动计算</div>
+			</div>
+		</div>
+		<div class="box" :style="{'padding-bottom':movementDto.details.length?'0':'48rpx'}">
+			<div class="title">商品明细</div>
+			<div class="btn" @tap="toAddGoods">+ 添加商品</div>
+			<div class="goods">
+				<template v-if="movementDto.details.length">
+					<div class="good" v-for="(good,idx) in movementDto.details" :key="good.skuId">
+						<div class="title">
+							<text>{{good.item.itemName}}</text>
+							<image :src="imgBase+'storage/icon_remove_grey.png'" @tap="deleteGood(idx)"></image>
+						</div>
+						<div class="info">
+							<div>规格信息:<span>{{good.itemSku.skuName||''}} / {{good.itemSku.grossWeight||0}}kg / {{good.itemSku.width||0}}X{{good.itemSku.height||0}}cm</span></div>
+						</div>
+						<div class="info">
+							<div>剩余库存:<span>{{good.nextQuantity}}</span></div>
+						</div>
+						<div class="num">
+							<text>移库数量:</text>
+							<u-number-box v-model="good.quantity" button-size="48" :integer="true" inputWidth="102rpx"
+							 @change="e=>changeRkNum(e,idx)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+						<div class="num">
+							<text>金额:</text>
+							<u-number-box v-model="good.amount" button-size="48" :integer="false" :canSmall="true" inputWidth="102rpx" 
+							@change="e=>changeRkMoney(e,idx)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+					</div>
+				</template>
+			</div>
+		</div>
+		<div class="save">
+			<div class="btn" @tap="saveShipment">保存</div>
+		</div>
+		<u-picker title="源仓库" :show="sourceWarehouseShow" :columns="sourceWarehouseList" keyName="warehouseName" 
+			@cancel="sourceWarehouseShow=false" @confirm="sourceWarehouseConfirm">
+		</u-picker>
+		<u-picker title="目标仓库" :show="targetWarehouseShow" :columns="targetWarehouseList" keyName="warehouseName" 
+			@cancel="targetWarehouseShow=false" @confirm="targetWarehouseConfirm">
+		</u-picker>
+	</view>
+</template>
+
+<script>
+	import { generateNo } from '@/utils/common.js'
+	export default {
+		data(){
+			return {
+				movementDto:{
+					id: '',
+					orderNo: '',
+					totalAmount: '',
+					orderStatus: 1,
+					sourceWarehouseId: '',
+					sourceWarehouseName: '',
+					targetWarehouseId: '',
+					targetWarehouseName: '',
+					totalQuantity: 0,
+					details: []
+				},
+				sourceWarehouseShow:false,
+				sourceWarehouseList:[],
+				targetWarehouseShow:false,
+				targetWarehouseList:[],
+			}
+		},
+		mounted() {
+			this.movementDto.orderNo = generateNo('YK');
+		},
+		methods:{
+			selectSourceWarehouse(){
+				this.sourceWarehouseShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/wms/warehouse/page').then(res=>{
+						if(res.data.code===0){
+							this.sourceWarehouseList = [res.data.data.list];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			sourceWarehouseConfirm(e){
+				this.movementDto.sourceWarehouseId = e.value[0].id;
+				this.movementDto.sourceWarehouseName = e.value[0].warehouseName;
+				this.sourceWarehouseShow = false;
+			},
+			selectTargetWarehouse(){
+				this.targetWarehouseShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/wms/warehouse/page').then(res=>{
+						if(res.data.code===0){
+							this.targetWarehouseList = [res.data.data.list];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			targetWarehouseConfirm(e){
+				this.movementDto.targetWarehouseId = e.value[0].id;
+				this.movementDto.targetWarehouseName = e.value[0].warehouseName;
+				this.targetWarehouseShow = false;
+			},
+			
+			setDto(e,name){
+				this.movementDto[name] = e.target.value;
+			},
+			autoCalculate(){
+				this.movementDto.totalAmount = this.movementDto.details.reduce((cur,pre)=>cur+(+pre.amount||0),0);
+			},
+			toAddGoods(){
+				if(!this.movementDto.sourceWarehouseId) return this.$showToast('请选择源仓库')
+				if(!this.movementDto.targetWarehouseId) return this.$showToast('请选择目标仓库')
+				let ids = this.movementDto.details.map(d=>d.skuId);
+				uni.navigateTo({
+					url:'/pagesStorage/moveStorage/goods?ids='+ids+'&warehouseId='+this.movementDto.sourceWarehouseId,
+					events:{
+						addGoods:list=>{
+							this.movementDto.details = list;
+							this.movementDto.details.forEach((d,i)=>{
+								let amount = d.checknum*d.itemSku.costPrice;
+								this.$set(this.movementDto.details[i],'amount',amount);
+								this.$set(this.movementDto.details[i],'quantity',d.checknum);
+							})
+							this.computeNum();
+						}
+					}
+				})
+			},
+			deleteGood(index){
+				this.movementDto.details.splice(index,1);
+				this.$nextTick(()=>{
+					this.computeNum();
+				})
+			},
+			changeRkNum(e,index){
+				this.$set(this.movementDto.details[index],'quantity',e.value);
+				this.$nextTick(()=>{
+					this.computeNum();
+				})
+			},
+			changeRkMoney(e,index){
+				this.$set(this.movementDto.details[index],'amount',e.value);
+			},
+			computeNum(){
+				this.movementDto.totalQuantity = this.movementDto.details.reduce((cur,pre)=>cur+pre.quantity,0);
+			},
+			saveShipment(){
+				if(!this.movementDto.orderNo) return this.$showToast('请输入移库单号');
+				if(!this.movementDto.sourceWarehouseId) return this.$showToast('请选择源仓库')
+				if(!this.movementDto.targetWarehouseId) return this.$showToast('请选择目标仓库')
+				
+				let temp = JSON.parse(JSON.stringify(this.movementDto.details));
+				let details = temp.map(d=>{
+					return {
+					    skuId: d.itemSku.id,
+					    amount: d.amount,
+					    quantity: d.quantity,
+					    sourceWarehouseId: this.movementDto.sourceWarehouseId,
+					    targetWarehouseId: this.movementDto.targetWarehouseId,
+					}
+				})
+				this.movementDto.details = details;
+				
+				this.$api.post('/wms/movementOrder/move',this.movementDto).then(res=>{
+					if(res.data.code===0){
+						this.$showToast('移库单新增成功');
+						setTimeout(()=>{
+							uni.redirectTo({
+								url:'/pagesStorage/moveStorage/index'
+							})
+						},1500)
+					}else this.$showToast(res.data.msg)
+				})
+			},
+		}
+	}
+</script>
+
+<style>
+	.storage-inp-ph{
+		color: #B9C0C8 !important;
+	}
+</style>
+<style scoped lang="less">
+	.page{
+		padding: 0 24rpx 186rpx;
+		background: #F4F8FB;
+		box-sizing: border-box;
+		
+		.box{
+			width: 100%;
+			padding: 36rpx 24rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-top: 20rpx;
+			
+			.title{
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 36rpx;
+				color: #1D2129;
+				line-height: 36rpx;
+				text-align: left;
+			}
+			
+			.form{
+				width: 100%;
+				margin-top: 36rpx;
+				.item{
+					width: 100%;
+					height: 90rpx;
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.left{
+						display: flex;
+						align-items: center;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 42rpx;
+						text-align: left;
+						span{
+							color: #F95050;
+						}
+					}
+					.right{
+						input{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 30rpx;
+							color: #4E5969;
+							line-height: 42rpx;
+							text-align: right;
+						}
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 30rpx;
+							color: #4E5969;
+							line-height: 42rpx;
+							text-align: right;
+							&.tip{
+								color: #B9C0C8;
+							}
+						}
+					}
+				}
+				.zdjs{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #198CFF;
+					line-height: 37rpx;
+					text-align: right;
+					margin-top: 9rpx;
+				}
+			}
+		
+			.btn{
+				width: 100%;
+				height: 64rpx;
+				border-radius: 16rpx;
+				border: 1rpx solid #198CFF;
+				margin-top: 26rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 26rpx;
+				color: #198CFF;
+				line-height: 64rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		
+			.goods{
+				width: 100%;
+				margin-top: 10rpx;
+				.good{
+					width: 100%;
+					padding: 36rpx 0;
+					box-sizing: border-box;
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+					&>div{
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+					}
+					.title{
+						text{
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 30rpx;
+							color: #1D2129;
+							line-height: 30rpx;
+							text-align: left;
+						}
+						image{
+							width: 28rpx;
+							height: 28rpx;
+						}
+					}
+					.info{
+						margin-top: 24rpx;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #86909C;
+						line-height: 24rpx;
+						span{
+							color: #4E5969;
+						}
+					}
+					.num,.money{
+						margin-top: 24rpx;
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+						}
+					}
+				}
+			}
+		}
+		
+		.save{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx 0;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 237 - 0
pagesStorage/moveStorage/goods.vue

@@ -0,0 +1,237 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='添加商品'></cus-header>
+		<div class="goods" v-if="list.length">
+			<div class="good" v-for="(good,index) in list" :key="good.skuId">
+				<div class="check" @click="changeCheck(index)">
+					<image :src="imgBase+'storage/icon_notchecked_grey.png'" v-if="!good.checked"></image>
+					<image :src="imgBase+'storage/icon_checked_blue.png'" v-else></image>
+				</div>
+				<div class="info">
+					<div class="name">{{good.item.itemName}}</div>
+					<div class="ggxx">
+						规格信息:<span>{{good.itemSku.skuName||''}} / {{good.itemSku.grossWeight||0}}kg / {{good.itemSku.width||0}}X{{good.itemSku.height||0}}cm</span>
+					</div>
+					<div class="ggxx">
+						库存:<span>{{good.quantity||''}}</span>
+					</div>
+					<!-- <div class="price">
+						<div class="left">成本价:<span>¥{{good.itemSku.costPrice||0}}</span></div>
+						<div class="right">
+							<u-number-box v-model="good.checknum" button-size="48" :integer="true" inputWidth="102rpx" 
+							@change="e=>changeNum(e,index)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+					</div> -->
+				</div>
+			</div>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - '+(mt+70)+'px)'"></page-empty>
+		</template>
+		<div class="btn">
+			<div class="left">
+				<image :src="imgBase+'storage/icon_checked_blue.png'"></image>
+				<text>已选:{{selectNum||0}}</text>
+			</div>
+			<div class="confirm" @tap="confirmSelect">确定</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				list:[],
+				isOver:false,
+				params:{
+					page:1,
+					limit:10,
+					minQuantity:1,
+					warehouseId:''
+				},
+				selectNum:0
+			}
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getList();
+		},
+		onPullDownRefresh() {
+			this.params.page = 1;
+			this.isOver = false;
+			this.list = [];
+			this.getList();
+		},
+		watch:{
+			list:{
+				handler(newValue){
+					this.selectNum =  this.list.filter(l=>l.checked).length;
+				},
+				deep:true,
+				immediate:true
+			}
+		},
+		async onLoad(option) {
+			let ids = option.ids;
+			if(ids&&ids.indexOf(',')>-1) ids = ids.split(',');
+			this.params.warehouseId = option.warehouseId;
+			await this.getList();
+			if(ids&&ids.length){
+				ids.forEach(item=>{
+					let fi = this.list.findIndex(l=>l.skuId===item);
+					if(fi>-1) this.$set(this.list[fi],'checked',true);
+				})
+			}
+		},
+		methods:{
+			async getList(){
+				let res = await this.$api.get('/wms/inventory/boardList/warehouse',this.params);
+				if(res.data.code===0){
+					if(this.list.length<res.data.data.total){
+						this.params.page++;
+						this.list = [...this.list,...res.data.data.list];
+						this.list.forEach((d,i)=>{
+							this.$set(this.list[i],'checked',false);
+							this.$set(this.list[i],'checknum',1);
+						})
+					}else this.isOver = true
+				}else this.$showModal(res.msg)
+			},
+			changeCheck(index){
+				this.$set(this.list[index],'checked',!this.list[index].checked);
+			},
+			changeNum(e,index){
+				this.$set(this.list[index],'checknum',e.value);
+			},
+			confirmSelect(){
+				let sn = this.list.filter(l=>l.checked).length;
+				if(sn<1) return this.$showToast('请至少选择一件商品');
+				let list = this.list.filter(l=>l.checked);
+				list.forEach(l=>l.nextQuantity=l.quantity);
+				this.getOpenerEventChannel().emit('addGoods', list);
+				uni.navigateBack();
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		width: 100%;
+		padding-bottom: 160rpx;
+		box-sizing: border-box;
+		background: #F4F8FB;
+		
+		.goods{
+			width: calc(100% - 48rpx);
+			margin: 0 auto;
+			.good{
+				width: 100%;
+				padding: 34rpx 24rpx;
+				box-sizing: border-box;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				margin-top: 20rpx;
+				display: flex;
+				.check{
+					width: 56rpx;
+					image{
+						width: 36rpx;
+						height: 36rpx;
+					}
+				}
+				.info{
+					width: calc(100% - 56rpx);
+					.name{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						text-align: left;
+						overflow: hidden;
+						text-overflow: ellipsis;
+						white-space: nowrap;
+					}
+					.ggxx{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #86909C;
+						line-height: 24rpx;
+						text-align: left;
+						margin-top: 23rpx;
+						span{
+							color: #4E5969;
+						}
+					}
+					.price{
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+						margin-top: 23rpx;
+						.left{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+							span{
+								font-weight: bold;
+								font-size: 26rpx;
+								color: #FF4141;
+								margin-left: 24rpx;
+							}
+						}
+					}
+				}
+			}
+		}
+	
+		.btn{
+			width: 100%;
+			height: 140rpx;
+			padding: 16rpx 20rpx 0 30rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			.left{
+				display: flex;
+				align-items: center;
+				image{
+					width: 36rpx;
+					height: 36rpx;
+				}
+				text{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 30rpx;
+					color: #1D2129;
+					line-height: 42rpx;
+					text-align: left;
+					margin-left: 12rpx;
+				}
+			}
+			.confirm{
+				width: 200rpx;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 353 - 0
pagesStorage/moveStorage/index.vue

@@ -0,0 +1,353 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='移库'></cus-header>
+		<status-tab :style="{'position':'fixed','top':mt+'px','left':'0','width':'100%'}" :list="typeList" @changeType="changeType"></status-tab>
+		<div class="boxs" v-if="dataList.length">
+			<div class="box" v-for="(item,index) in dataList" :key="item.id">
+				<div class="top">
+					<text>{{ item.orderNo||'' }}</text>
+					<div class="status" 
+						:class="{'wrk':item.orderStatus==0,'yrk':item.orderStatus==1,'zf':item.orderStatus==-1}"
+					>{{ movementStatus[item.orderStatus]||'' }}</div>
+				</div>
+				<div class="content">
+					<div class="pre">
+						<div class="title">总数量</div>
+						<div class="nr">{{ item.totalQuantity||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">总金额</div>
+						<div class="nr money">¥{{ item.totalAmount||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">操作时间</div>
+						<div class="nr">{{ item.updateDate||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">源仓库</div>
+						<div class="nr">{{ item.sourceWarehouseName||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">操作人</div>
+						<div class="nr">{{ item.updaterName||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">目标仓库</div>
+						<div class="nr">{{ item.targetWarehouseName||'' }}</div>
+					</div>
+				</div>
+				<div class="goods" v-if="item.goodsList.length&&item.goodsShow">
+					<div class="good" v-for="(good,idx) in item.goodsList" :key="good.id">
+						<div class="name_price">
+							<text>{{ good.item.itemName }}</text>
+							<span>¥{{ good.amount||'' }}</span>
+						</div>
+						<div class="info_num">
+							<div class="info">规格信息:<span>{{ good.itemSku.skuName }}</span></div>
+							<div class="num">数量:<span>{{ good.quantity }}</span></div>
+						</div>
+					</div>
+				</div>
+				<div class="more" @tap="getGoodsListById(item.id,index)">
+					<text>{{ item.goodsShow?'收起':'商品明细' }}</text>
+					<image :src="imgBase+'storage/icon_jtdown_blue.png'" :class="{'sq':item.goodsShow}"></image>
+				</div>
+			</div>
+			<page-loading :loading="isLoading"></page-loading>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - '+(mt+51+74+25)+'px)'" marginTop="51px"></page-empty>
+		</template>
+		<div class="add">
+			<div class="btn" @tap="addReceipt">新增移库单</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	import statusTab from '../components/statusTab/index.vue'
+	import pageLoading from '../components/pageLoading/index.vue'
+	import pageEmpty from '../components/pageEmpty/index.vue'
+	export default {
+		components:{
+			statusTab,
+			pageLoading,
+			pageEmpty
+		},
+		data(){
+			return {
+				typeList:[],
+				movementStatus:{},
+				isOver:false,
+				isLoading:false,
+				params:{
+					page:1,
+					limit:10,
+					orderStatus:''
+				},
+				dataList:[],
+			}
+		},
+		onLoad() {
+			this.getMovementStatus();
+			this.getDataList();
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getDataList();
+		},
+		methods:{
+			changeType(status){
+				this.dataList = [];
+				this.params.orderStatus = status;
+				this.params.page = 1;
+				this.isOver = false;
+				this.isLoading = false;
+				this.getDataList();
+			},
+			getMovementStatus(){
+				this.$api.get('/sys/dict/data/getListByType/wms_movement_status').then(res=>{
+					if(res.data.code===0){
+						this.typeList = res.data.data;
+						res.data.data.forEach(d=>{
+							this.movementStatus[d.dictValue] = d.dictLabel;
+						})
+						this.typeList.unshift({dictValue:'',dictLabel:'全部'})
+					}else this.$showToast(res.data.msg)
+				});
+			},
+			getDataList(){
+				this.isLoading = true;
+				this.$api.get('/wms/movementOrder/page',this.params).then(res=>{
+					if(res.data.code===0){
+						if(this.dataList.length<res.data.data.total){
+							this.params.page++;
+							this.dataList = [...this.dataList,...res.data.data.list];
+							this.dataList.forEach((d,i)=>{
+								this.$set(this.dataList[i],'goodsList',[]);
+								this.$set(this.dataList[i],'goodsShow',false);
+							})
+						}else this.isOver = true
+					}else this.$showModal(res.data.msg)
+					this.isLoading = false;
+				});
+			},
+			getGoodsListById(id,index){
+				this.$set(this.dataList[index],'goodsShow',!this.dataList[index].goodsShow);
+				if(!this.dataList[index].goodsShow) return
+				this.$api.get('/wms/movementOrder/getByMovementOrderId/'+id).then(res=>{
+					if(res.data.code===0){
+						this.$set(this.dataList[index],'goodsList',res.data.data);
+					}else this.$showModal(res.msg)
+				})
+			},
+			addReceipt(){
+				uni.navigateTo({
+					url:'/pagesStorage/moveStorage/add'
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		padding: 0 0 186rpx;
+		background: #F4F8FB;
+		box-sizing: border-box;
+		
+		.boxs{
+			width: 100%;
+			padding: 20rpx 24rpx 0;
+			margin-top: 102rpx;
+			box-sizing: border-box;
+			.box{
+				width: 100%;
+				margin-top: 20rpx;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				padding-bottom: 40rpx;
+				&:first-child{
+					margin-top: 0;
+				}
+				.top{
+					width: 100%;
+					height: 90rpx;
+					padding: 0 24rpx;
+					box-sizing: border-box;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					border-bottom: 1rpx dotted #ECECEC;
+					text{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						text-align: left;
+					}
+					.status{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 26rpx;
+						line-height: 30rpx;
+						text-align: right;
+						&.wrk{
+							color: #FEB000;
+						}
+						&.yrk{
+							color: #14CC8C;
+						}
+						&.zf{
+							color: #FF4141;
+						}
+					}
+				}
+				.content{
+					width: 100%;
+					padding: 0 24rpx 40rpx;
+					box-sizing: border-box;
+					display: flex;
+					flex-wrap: wrap;
+					.pre{
+						width: 50%;
+						margin-top: 36rpx;
+						display: flex;
+						.title{
+							width: 116rpx;
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+						}
+						.nr{
+							width: calc(100% - 116rpx);
+							font-family: PingFangSC, PingFang SC;
+							font-weight: bold;
+							font-size: 26rpx;
+							color: #1D2129;
+							line-height: 24rpx;
+							text-align: left;
+						    white-space: nowrap;
+						    text-overflow: ellipsis;
+						    overflow: hidden;
+							&.money{
+								color: #F95050;
+							}
+						}
+						&.bfb{
+							width: 100%;
+						}
+					}
+				}
+				.goods{
+					width: calc(100% - 20rpx);
+					margin: 0 auto 40rpx;
+					.good{
+						width: 100%;
+						padding: 36rpx 16rpx;
+						box-sizing: border-box;
+						background: #F0F8FE;
+						box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+						&>div{
+							display: flex;
+							align-items: center;
+							justify-content: space-between;
+						}
+						.name_price{
+							text{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 28rpx;
+								color: #1D2129;
+								line-height: 30rpx;
+								text-align: left;
+							}
+							span{
+								font-family: PingFang-SC, PingFang-SC;
+								font-weight: bold;
+								font-size: 26rpx;
+								color: #F95050;
+								line-height: 26rpx;
+								text-align: right;
+							}
+						}
+						.info_num{
+							margin-top: 24rpx;
+							.info{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								text-align: left;
+								span{
+									color: #4E5969;
+								}
+							}
+							.num{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								span{
+									font-weight: bold;
+									font-size: 26rpx;
+									color: #4E5969;
+								}
+							}
+						}
+					}
+				}
+				.more{
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					text{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #198CFF;
+						line-height: 28rpx;
+					}
+					image{
+						width: 24rpx;
+						height: 24rpx;
+						margin-left: 10rpx;
+						&.sq{
+							transform: rotate(180deg);
+						}
+					}
+				}
+			}
+		}
+	
+		.add{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx 0;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 425 - 0
pagesStorage/outStorage/add.vue

@@ -0,0 +1,425 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='新增'></cus-header>
+		<div class="box">
+			<div class="title">出库单基本信息</div>
+			<div class="form">
+				<div class="item">
+					<div class="left"><span>*</span>出库单号</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入出库单号" v-model="shipmentDto.orderNo" @blur="e=>setShipment(e,'orderNo')">
+					</div>
+				</div>
+				<div class="item">
+					<div class="left"><span>*</span>仓库</div>
+					<div class="right" @tap="selectWarehouse">
+						<text v-if="shipmentDto.warehouseName">{{shipmentDto.warehouseName}} ></text>
+						<text class="tip" v-else>请选择仓库 ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left"><span>*</span>出库类型</div>
+					<div class="right" @tap="selectShipmentType">
+						<text v-if="shipmentDto.optTypeName">{{shipmentDto.optTypeName}} ></text>
+						<text class="tip" v-else>请选择 ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">客户</div>
+					<div class="right" @tap="selectMerchant">
+						<text v-if="shipmentDto.merchantName">{{shipmentDto.merchantName}} ></text>
+						<text class="tip" v-else>请选择 ></text>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">业务单号</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入" v-model="shipmentDto.bizOrderNo" @blur="e=>setShipment(e,'bizOrderNo')">
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">总数量</div>
+					<div class="right">
+						<input type="text" v-model="shipmentDto.totalQuantity" disabled>
+					</div>
+				</div>
+				<div class="item">
+					<div class="left">总金额</div>
+					<div class="right">
+						<input type="text" placeholder-class="storage-inp-ph" placeholder="请输入" v-model="shipmentDto.totalAmount"  @blur="e=>setShipment(e,'totalAmount')">
+					</div>
+				</div>
+				<div class="zdjs" @tap="autoCalculate">自动计算</div>
+			</div>
+		</div>
+		<div class="box" :style="{'padding-bottom':shipmentDto.details.length?'0':'48rpx'}">
+			<div class="title">商品明细</div>
+			<div class="btn" @tap="toAddGoods">+ 添加商品</div>
+			<div class="goods">
+				<template v-if="shipmentDto.details.length">
+					<div class="good" v-for="(good,idx) in shipmentDto.details" :key="good.skuId">
+						<div class="title">
+							<text>{{good.item.itemName}}</text>
+							<image :src="imgBase+'storage/icon_remove_grey.png'" @tap="deleteGood(idx)"></image>
+						</div>
+						<div class="info">
+							<div>规格信息:<span>{{good.itemSku.skuName||''}} / {{good.itemSku.grossWeight||0}}kg / {{good.itemSku.width||0}}X{{good.itemSku.height||0}}cm</span></div>
+						</div>
+						<div class="num">
+							<text>出库数量:</text>
+							<u-number-box v-model="good.quantity" button-size="48" :integer="true" inputWidth="102rpx"
+							 @change="e=>changeRkNum(e,idx)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+						<div class="num">
+							<text>金额:</text>
+							<u-number-box v-model="good.amount" button-size="48" :integer="false" :canSmall="true" inputWidth="102rpx" 
+							@change="e=>changeRkMoney(e,idx)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+					</div>
+				</template>
+			</div>
+		</div>
+		<div class="save">
+			<div class="btn" @tap="saveShipment">保存</div>
+		</div>
+		<u-picker title="仓库" :show="warehouseShow" :columns="warehouseList" keyName="warehouseName" 
+			@cancel="warehouseShow=false" @confirm="warehouseConfirm">
+		</u-picker>
+		<u-picker title="出库类型" :show="ShipmentTypeShow" :columns="ShipmentTypeList" keyName="dictLabel" 
+			@cancel="ShipmentTypeShow=false" @confirm="ShipmentTypeConfirm">
+		</u-picker>
+		<u-picker title="客户" :show="merchantShow" :columns="merchantList" keyName="merchantName" 
+			@cancel="merchantShow=false" @confirm="merchantConfirm">
+		</u-picker>
+	</view>
+</template>
+
+<script>
+	import { generateNo } from '@/utils/common.js'
+	export default {
+		data(){
+			return {
+				shipmentDto:{
+					id: '',
+					orderNo: '',
+					optType: '',
+					optTypeName: '',
+					merchantId: '',
+					merchantName: '',
+					bizOrderNo: '',
+					totalAmount: '',
+					orderStatus: 1,
+					warehouseId: '',
+					warehouseName: '',
+					totalQuantity: 0,
+					details: []
+				},
+				warehouseShow:false,
+				warehouseList:[],
+				ShipmentTypeShow:false,
+				ShipmentTypeList:[],
+				merchantShow:false,
+				merchantList:[],
+			}
+		},
+		mounted() {
+			this.shipmentDto.orderNo = generateNo('CK');
+		},
+		methods:{
+			selectWarehouse(){
+				this.warehouseShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/wms/warehouse/page').then(res=>{
+						if(res.data.code===0){
+							this.warehouseList = [res.data.data.list];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			warehouseConfirm(e){
+				this.shipmentDto.warehouseId = e.value[0].id;
+				this.shipmentDto.warehouseName = e.value[0].warehouseName;
+				this.warehouseShow = false;
+			},
+			selectShipmentType(){
+				this.ShipmentTypeShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/sys/dict/data/getListByType/wms_shipment_type').then(res=>{
+						if(res.data.code===0){
+							this.ShipmentTypeList = [res.data.data];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			ShipmentTypeConfirm(e){
+				this.shipmentDto.optType = e.value[0].dictValue;
+				this.shipmentDto.optTypeName = e.value[0].dictLabel;
+				this.ShipmentTypeShow = false;
+			},
+			selectMerchant(){
+				this.merchantShow = true;
+				this.$nextTick(()=>{
+					this.$api.get('/wms/merchant/page').then(res=>{
+						if(res.data.code===0){
+							this.merchantList = [res.data.data.list];
+						}else this.$showToast(res.data.msg)
+					})
+				})
+			},
+			merchantConfirm(e){
+				this.shipmentDto.merchantId = e.value[0].id;
+				this.shipmentDto.merchantName = e.value[0].merchantName;
+				this.merchantShow = false;
+			},
+			setShipment(e,name){
+				this.shipmentDto[name] = e.target.value;
+			},
+			autoCalculate(){
+				this.shipmentDto.totalAmount = this.shipmentDto.details.reduce((cur,pre)=>cur+(+pre.amount||0),0);
+			},
+			toAddGoods(){
+				if(!this.shipmentDto.warehouseId) return this.$showToast('请先选择仓库')
+				let ids = this.shipmentDto.details.map(d=>d.skuId);
+				uni.navigateTo({
+					url:'/pagesStorage/outStorage/goods?ids='+ids+'&warehouseId='+this.shipmentDto.warehouseId,
+					events:{
+						addGoods:list=>{
+							this.shipmentDto.details = list;
+							this.shipmentDto.details.forEach((d,i)=>{
+								let amount = d.checknum*d.itemSku.costPrice;
+								this.$set(this.shipmentDto.details[i],'amount',amount);
+								this.$set(this.shipmentDto.details[i],'quantity',d.checknum);
+							})
+							this.computeNum();
+						}
+					}
+				})
+			},
+			deleteGood(index){
+				this.shipmentDto.details.splice(index,1);
+				this.$nextTick(()=>{
+					this.computeNum();
+				})
+			},
+			changeRkNum(e,index){
+				this.$set(this.shipmentDto.details[index],'quantity',e.value);
+				this.$nextTick(()=>{
+					this.computeNum();
+				})
+			},
+			changeRkMoney(e,index){
+				this.$set(this.shipmentDto.details[index],'amount',e.value);
+			},
+			computeNum(){
+				this.shipmentDto.totalQuantity = this.shipmentDto.details.reduce((cur,pre)=>cur+pre.quantity,0);
+			},
+			saveShipment(){
+				if(!this.shipmentDto.orderNo) return this.$showToast('请输入出库单号');
+				if(!this.shipmentDto.warehouseId) return this.$showToast('请选择仓库');
+				if(!this.shipmentDto.optType) return this.$showToast('请选择出库类型');
+				
+				let temp = JSON.parse(JSON.stringify(this.shipmentDto.details));
+				let details = temp.map(d=>{
+					return {
+					    skuId: d.itemSku.id,
+					    amount: d.amount,
+					    quantity: d.quantity,
+					    warehouseId: this.shipmentDto.warehouseId,
+					}
+				})
+				this.shipmentDto.details = details;
+				
+				this.$api.post('/wms/shipmentOrder',this.shipmentDto).then(res=>{
+					if(res.data.code===0){
+						this.$showToast('出库单新增成功');
+						setTimeout(()=>{
+							uni.redirectTo({
+								url:'/pagesStorage/outStorage/index'
+							})
+						},1500)
+					}else this.$showToast(res.data.msg)
+				})
+			},
+		}
+	}
+</script>
+
+<style>
+	.storage-inp-ph{
+		color: #B9C0C8 !important;
+	}
+</style>
+<style scoped lang="less">
+	.page{
+		padding: 0 24rpx 186rpx;
+		background: #F4F8FB;
+		box-sizing: border-box;
+		
+		.box{
+			width: 100%;
+			padding: 36rpx 24rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			border-radius: 16rpx;
+			margin-top: 20rpx;
+			
+			.title{
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 36rpx;
+				color: #1D2129;
+				line-height: 36rpx;
+				text-align: left;
+			}
+			
+			.form{
+				width: 100%;
+				margin-top: 36rpx;
+				.item{
+					width: 100%;
+					height: 90rpx;
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					.left{
+						display: flex;
+						align-items: center;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 42rpx;
+						text-align: left;
+						span{
+							color: #F95050;
+						}
+					}
+					.right{
+						input{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 30rpx;
+							color: #4E5969;
+							line-height: 42rpx;
+							text-align: right;
+						}
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 30rpx;
+							color: #4E5969;
+							line-height: 42rpx;
+							text-align: right;
+							&.tip{
+								color: #B9C0C8;
+							}
+						}
+					}
+				}
+				.zdjs{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 26rpx;
+					color: #198CFF;
+					line-height: 37rpx;
+					text-align: right;
+					margin-top: 9rpx;
+				}
+			}
+		
+			.btn{
+				width: 100%;
+				height: 64rpx;
+				border-radius: 16rpx;
+				border: 1rpx solid #198CFF;
+				margin-top: 26rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 26rpx;
+				color: #198CFF;
+				line-height: 64rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		
+			.goods{
+				width: 100%;
+				margin-top: 10rpx;
+				.good{
+					width: 100%;
+					padding: 36rpx 0;
+					box-sizing: border-box;
+					background: #FFFFFF;
+					box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+					&>div{
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+					}
+					.title{
+						text{
+							font-family: PingFang-SC, PingFang-SC;
+							font-weight: bold;
+							font-size: 30rpx;
+							color: #1D2129;
+							line-height: 30rpx;
+							text-align: left;
+						}
+						image{
+							width: 28rpx;
+							height: 28rpx;
+						}
+					}
+					.info{
+						margin-top: 24rpx;
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #86909C;
+						line-height: 24rpx;
+						span{
+							color: #4E5969;
+						}
+					}
+					.num,.money{
+						margin-top: 24rpx;
+						text{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+						}
+					}
+				}
+			}
+		}
+		
+		.save{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx 0;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 233 - 0
pagesStorage/outStorage/goods.vue

@@ -0,0 +1,233 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='添加商品'></cus-header>
+		<div class="goods" v-if="list.length">
+			<div class="good" v-for="(good,index) in list" :key="good.skuId">
+				<div class="check" @click="changeCheck(index)">
+					<image :src="imgBase+'storage/icon_notchecked_grey.png'" v-if="!good.checked"></image>
+					<image :src="imgBase+'storage/icon_checked_blue.png'" v-else></image>
+				</div>
+				<div class="info">
+					<div class="name">{{good.item.itemName}}</div>
+					<div class="ggxx">
+						规格信息:<span>{{good.itemSku.skuName||''}} / {{good.itemSku.grossWeight||0}}kg / {{good.itemSku.width||0}}X{{good.itemSku.height||0}}cm</span>
+					</div>
+					<div class="price">
+						<div class="left">成本价:<span>¥{{good.itemSku.costPrice||0}}</span></div>
+						<div class="right">
+							<u-number-box v-model="good.checknum" button-size="48" :integer="true" inputWidth="102rpx" 
+							@change="e=>changeNum(e,index)" bgColor="#F5F8FA"></u-number-box>
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - '+(mt+70)+'px)'"></page-empty>
+		</template>
+		<div class="btn">
+			<div class="left">
+				<image :src="imgBase+'storage/icon_checked_blue.png'"></image>
+				<text>已选:{{selectNum||0}}</text>
+			</div>
+			<div class="confirm" @tap="confirmSelect">确定</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	export default {
+		data(){
+			return {
+				list:[],
+				isOver:false,
+				params:{
+					page:1,
+					limit:10,
+					minQuantity:1,
+					warehouseId:''
+				},
+				selectNum:0
+			}
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getList();
+		},
+		onPullDownRefresh() {
+			this.params.page = 1;
+			this.isOver = false;
+			this.list = [];
+			this.getList();
+		},
+		watch:{
+			list:{
+				handler(newValue){
+					this.selectNum =  this.list.filter(l=>l.checked).length;
+				},
+				deep:true,
+				immediate:true
+			}
+		},
+		async onLoad(option) {
+			let ids = option.ids;
+			if(ids&&ids.indexOf(',')>-1) ids = ids.split(',');
+			this.params.warehouseId = option.warehouseId;
+			await this.getList();
+			if(ids&&ids.length){
+				ids.forEach(item=>{
+					let fi = this.list.findIndex(l=>l.skuId===item);
+					if(fi>-1) this.$set(this.list[fi],'checked',true);
+				})
+			}
+		},
+		methods:{
+			async getList(){
+				let res = await this.$api.get('/wms/inventory/boardList/warehouse',this.params);
+				if(res.data.code===0){
+					if(this.list.length<res.data.data.total){
+						this.params.page++;
+						this.list = [...this.list,...res.data.data.list];
+						this.list.forEach((d,i)=>{
+							this.$set(this.list[i],'checked',false);
+							this.$set(this.list[i],'checknum',1);
+						})
+					}else this.isOver = true
+				}else this.$showModal(res.msg)
+			},
+			changeCheck(index){
+				this.$set(this.list[index],'checked',!this.list[index].checked);
+			},
+			changeNum(e,index){
+				this.$set(this.list[index],'checknum',e.value);
+			},
+			confirmSelect(){
+				let sn = this.list.filter(l=>l.checked).length;
+				if(sn<1) return this.$showToast('请至少选择一件商品');
+				let list = this.list.filter(l=>l.checked);
+				this.getOpenerEventChannel().emit('addGoods', list);
+				uni.navigateBack();
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		width: 100%;
+		padding-bottom: 160rpx;
+		box-sizing: border-box;
+		background: #F4F8FB;
+		
+		.goods{
+			width: calc(100% - 48rpx);
+			margin: 0 auto;
+			.good{
+				width: 100%;
+				padding: 34rpx 24rpx;
+				box-sizing: border-box;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				margin-top: 20rpx;
+				display: flex;
+				.check{
+					width: 56rpx;
+					image{
+						width: 36rpx;
+						height: 36rpx;
+					}
+				}
+				.info{
+					width: calc(100% - 56rpx);
+					.name{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						text-align: left;
+						overflow: hidden;
+						text-overflow: ellipsis;
+						white-space: nowrap;
+					}
+					.ggxx{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 24rpx;
+						color: #86909C;
+						line-height: 24rpx;
+						text-align: left;
+						margin-top: 23rpx;
+						span{
+							color: #4E5969;
+						}
+					}
+					.price{
+						display: flex;
+						align-items: center;
+						justify-content: space-between;
+						margin-top: 23rpx;
+						.left{
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+							span{
+								font-weight: bold;
+								font-size: 26rpx;
+								color: #FF4141;
+								margin-left: 24rpx;
+							}
+						}
+					}
+				}
+			}
+		}
+	
+		.btn{
+			width: 100%;
+			height: 140rpx;
+			padding: 16rpx 20rpx 0 30rpx;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			.left{
+				display: flex;
+				align-items: center;
+				image{
+					width: 36rpx;
+					height: 36rpx;
+				}
+				text{
+					font-family: PingFangSC, PingFang SC;
+					font-weight: 400;
+					font-size: 30rpx;
+					color: #1D2129;
+					line-height: 42rpx;
+					text-align: left;
+					margin-left: 12rpx;
+				}
+			}
+			.confirm{
+				width: 200rpx;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 367 - 0
pagesStorage/outStorage/index.vue

@@ -0,0 +1,367 @@
+<template>
+	<view class="page" :style="{'min-height':h+'px', 'padding-top':mt+'px'}">
+		<cus-header title='出库'></cus-header>
+		<status-tab :style="{'position':'fixed','top':mt+'px','left':'0','width':'100%'}" :list="typeList" @changeType="changeType"></status-tab>
+		<div class="boxs" v-if="dataList.length">
+			<div class="box" v-for="(item,index) in dataList" :key="item.id">
+				<div class="top">
+					<text>{{ item.orderNo||'' }}</text>
+					<div class="status" 
+						:class="{'wrk':item.orderStatus==0,'yrk':item.orderStatus==1,'zf':item.orderStatus==-1}"
+					>{{ receiptStatus[item.orderStatus]||'' }}</div>
+				</div>
+				<div class="content">
+					<div class="pre">
+						<div class="title">总数量</div>
+						<div class="nr">{{ item.totalQuantity||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">总金额</div>
+						<div class="nr money">¥{{ item.totalAmount||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">仓库</div>
+						<div class="nr">{{ item.warehouseName||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">出库类型</div>
+						<div class="nr">{{ shipmentType[item.optType]||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">操作人</div>
+						<div class="nr">{{ item.updaterName||'' }}</div>
+					</div>
+					<div class="pre">
+						<div class="title">操作时间</div>
+						<div class="nr">{{ item.updateDate||'' }}</div>
+					</div>
+					<div class="pre bfb">
+						<div class="title">客户</div>
+						<div class="nr">{{ item.merchantName||'' }}</div>
+					</div>
+				</div>
+				<div class="goods" v-if="item.goodsList.length&&item.goodsShow">
+					<div class="good" v-for="(good,idx) in item.goodsList" :key="good.id">
+						<div class="name_price">
+							<text>{{ good.item.itemName }}</text>
+							<span>¥{{ good.amount||'' }}</span>
+						</div>
+						<div class="info_num">
+							<div class="info">规格信息:<span>{{ good.itemSku.skuName }}</span></div>
+							<div class="num">数量:<span>{{ good.quantity }}</span></div>
+						</div>
+					</div>
+				</div>
+				<div class="more" @tap="getGoodsListById(item.id,index)">
+					<text>{{ item.goodsShow?'收起':'商品明细' }}</text>
+					<image :src="imgBase+'storage/icon_jtdown_blue.png'" :class="{'sq':item.goodsShow}"></image>
+				</div>
+			</div>
+			<page-loading :loading="isLoading"></page-loading>
+		</div>
+		<template v-else>
+			<page-empty :height="'calc(100vh - '+(mt+51+74+25)+'px)'" marginTop="51px"></page-empty>
+		</template>
+		<div class="add">
+			<div class="btn" @tap="addReceipt">新增出库单</div>
+		</div>
+	</view>
+</template>
+
+<script>
+	import statusTab from '../components/statusTab/index.vue'
+	import pageLoading from '../components/pageLoading/index.vue'
+	import pageEmpty from '../components/pageEmpty/index.vue'
+	export default {
+		components:{
+			statusTab,
+			pageLoading,
+			pageEmpty
+		},
+		data(){
+			return {
+				typeList:[],
+				receiptStatus:{},
+				shipmentType:{},
+				isOver:false,
+				isLoading:false,
+				params:{
+					page:1,
+					limit:10,
+					orderStatus:''
+				},
+				dataList:[],
+			}
+		},
+		onLoad() {
+			this.getSeceiptStatus();
+			this.getSeceiptType();
+			this.getDataList();
+		},
+		onReachBottom() {
+			if(this.isOver) return
+			this.getDataList();
+		},
+		methods:{
+			changeType(status){
+				this.dataList = [];
+				this.params.orderStatus = status;
+				this.params.page = 1;
+				this.isOver = false;
+				this.isLoading = false;
+				this.getDataList();
+			},
+			getSeceiptStatus(){
+				this.$api.get('/sys/dict/data/getListByType/wms_shipment_status').then(res=>{
+					if(res.data.code===0){
+						this.typeList = res.data.data;
+						res.data.data.forEach(d=>{
+							this.receiptStatus[d.dictValue] = d.dictLabel;
+						})
+						this.typeList.unshift({dictValue:'',dictLabel:'全部'})
+					}else this.$showToast(res.data.msg)
+				});
+			},
+			async getSeceiptType(){
+				let res = await this.$api.get('/sys/dict/data/getListByType/wms_shipment_type');
+				if(res.data.code===0){
+					res.data.data.forEach(d=>{
+						this.shipmentType[d.dictValue] = d.dictLabel;
+					})
+				}else this.$showToast(res.data.msg)
+			},
+			getDataList(){
+				this.isLoading = true;
+				this.$api.get('/wms/shipmentOrder/page',this.params).then(res=>{
+					if(res.data.code===0){
+						if(this.dataList.length<res.data.data.total){
+							this.params.page++;
+							this.dataList = [...this.dataList,...res.data.data.list];
+							this.dataList.forEach((d,i)=>{
+								this.$set(this.dataList[i],'goodsList',[]);
+								this.$set(this.dataList[i],'goodsShow',false);
+							})
+						}else this.isOver = true
+					}else this.$showModal(res.data.msg)
+					this.isLoading = false;
+				});
+			},
+			getGoodsListById(id,index){
+				this.$set(this.dataList[index],'goodsShow',!this.dataList[index].goodsShow);
+				if(!this.dataList[index].goodsShow) return
+				this.$api.get('/wms/shipmentOrder/getByShipmentOrderId/'+id).then(res=>{
+					if(res.data.code===0){
+						this.$set(this.dataList[index],'goodsList',res.data.data);
+					}else this.$showModal(res.msg)
+				})
+			},
+			addReceipt(){
+				uni.navigateTo({
+					url:'/pagesStorage/outStorage/add'
+				})
+			}
+		}
+	}
+</script>
+
+<style scoped lang="less">
+	.page{
+		padding: 0 0 186rpx;
+		background: #F4F8FB;
+		box-sizing: border-box;
+		
+		.boxs{
+			width: 100%;
+			padding: 20rpx 24rpx 0;
+			margin-top: 102rpx;
+			box-sizing: border-box;
+			.box{
+				width: 100%;
+				margin-top: 20rpx;
+				background: #FFFFFF;
+				border-radius: 16rpx;
+				padding-bottom: 40rpx;
+				&:first-child{
+					margin-top: 0;
+				}
+				.top{
+					width: 100%;
+					height: 90rpx;
+					padding: 0 24rpx;
+					box-sizing: border-box;
+					display: flex;
+					align-items: center;
+					justify-content: space-between;
+					border-bottom: 1rpx dotted #ECECEC;
+					text{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 30rpx;
+						color: #1D2129;
+						line-height: 30rpx;
+						text-align: left;
+					}
+					.status{
+						font-family: PingFang-SC, PingFang-SC;
+						font-weight: bold;
+						font-size: 26rpx;
+						line-height: 30rpx;
+						text-align: right;
+						&.wrk{
+							color: #FEB000;
+						}
+						&.yrk{
+							color: #14CC8C;
+						}
+						&.zf{
+							color: #FF4141;
+						}
+					}
+				}
+				.content{
+					width: 100%;
+					padding: 0 24rpx 40rpx;
+					box-sizing: border-box;
+					display: flex;
+					flex-wrap: wrap;
+					.pre{
+						width: 50%;
+						margin-top: 36rpx;
+						display: flex;
+						.title{
+							width: 116rpx;
+							font-family: PingFangSC, PingFang SC;
+							font-weight: 400;
+							font-size: 24rpx;
+							color: #86909C;
+							line-height: 24rpx;
+							text-align: left;
+						}
+						.nr{
+							width: calc(100% - 116rpx);
+							font-family: PingFangSC, PingFang SC;
+							font-weight: bold;
+							font-size: 26rpx;
+							color: #1D2129;
+							line-height: 24rpx;
+							text-align: left;
+						    white-space: nowrap;
+						    text-overflow: ellipsis;
+						    overflow: hidden;
+							&.money{
+								color: #F95050;
+							}
+						}
+						&.bfb{
+							width: 100%;
+						}
+					}
+				}
+				.goods{
+					width: calc(100% - 20rpx);
+					margin: 0 auto 40rpx;
+					.good{
+						width: 100%;
+						padding: 36rpx 16rpx;
+						box-sizing: border-box;
+						background: #F0F8FE;
+						box-shadow: inset 0rpx -1rpx 0rpx 0rpx #ECECEC;
+						&>div{
+							display: flex;
+							align-items: center;
+							justify-content: space-between;
+						}
+						.name_price{
+							text{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 28rpx;
+								color: #1D2129;
+								line-height: 30rpx;
+								text-align: left;
+							}
+							span{
+								font-family: PingFang-SC, PingFang-SC;
+								font-weight: bold;
+								font-size: 26rpx;
+								color: #F95050;
+								line-height: 26rpx;
+								text-align: right;
+							}
+						}
+						.info_num{
+							margin-top: 24rpx;
+							.info{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								text-align: left;
+								span{
+									color: #4E5969;
+								}
+							}
+							.num{
+								font-family: PingFangSC, PingFang SC;
+								font-weight: 400;
+								font-size: 24rpx;
+								color: #86909C;
+								line-height: 24rpx;
+								span{
+									font-weight: bold;
+									font-size: 26rpx;
+									color: #4E5969;
+								}
+							}
+						}
+					}
+				}
+				.more{
+					display: flex;
+					align-items: center;
+					justify-content: center;
+					text{
+						font-family: PingFangSC, PingFang SC;
+						font-weight: 400;
+						font-size: 28rpx;
+						color: #198CFF;
+						line-height: 28rpx;
+					}
+					image{
+						width: 24rpx;
+						height: 24rpx;
+						margin-left: 10rpx;
+						&.sq{
+							transform: rotate(180deg);
+						}
+					}
+				}
+			}
+		}
+	
+		.add{
+			width: 100%;
+			height: 148rpx;
+			padding: 20rpx 48rpx 0;
+			box-sizing: border-box;
+			background: #FFFFFF;
+			position: fixed;
+			left: 0;
+			bottom: 0;
+			.btn{
+				width: 100%;
+				height: 88rpx;
+				background: #198CFF;
+				border-radius: 16rpx;
+				font-family: PingFang-SC, PingFang-SC;
+				font-weight: bold;
+				font-size: 32rpx;
+				color: #FFFFFF;
+				line-height: 88rpx;
+				text-align: center;
+				letter-spacing: 2rpx;
+			}
+		}
+	}
+</style>

+ 5 - 0
uni_modules/uview-ui/components/u-number-box/props.js

@@ -104,6 +104,11 @@ export default {
         iconStyle: {
             type: [Object, String],
             default: uni.$u.props.numberBox.iconStyle
+        },
+        // 是否可输入小数
+        canSmall: {
+            type: Boolean,
+            default: false
         }
     }
 }

+ 11 - 8
uni_modules/uview-ui/components/u-number-box/u-number-box.vue

@@ -188,8 +188,9 @@
 			this.init()
 		},
 		methods: {
-			init() {
-				this.currentValue = this.format(this.value)
+			init() {
+				if(!this.canSmall) this.currentValue = this.format(this.value)
+				else this.currentValue = this.value
 			},
 			// 格式化整理数据,限制范围
 			format(value) {
@@ -264,13 +265,15 @@
 				} = e.detail || {}
 				// 为空返回
 				if (value === '') return
-				let formatted = this.filter(value)
-				// 最大允许的小数长度
-				if (this.decimalLength !== null && formatted.indexOf('.') !== -1) {
-					const pair = formatted.split('.');
-					formatted = `${pair[0]}.${pair[1].slice(0, this.decimalLength)}`
+				let formatted = this.filter(value)
+				if(!this.canSmall){
+					// 最大允许的小数长度
+					if (this.decimalLength !== null && formatted.indexOf('.') !== -1) {
+						const pair = formatted.split('.');
+						formatted = `${pair[0]}.${pair[1].slice(0, this.decimalLength)}`
+					}
+					formatted = this.format(formatted)
 				}
-				formatted = this.format(formatted)
 				this.emitChange(formatted);
 			},
 			// 发出change事件

+ 12 - 0
utils/common.js

@@ -0,0 +1,12 @@
+// 生成单号
+export function generateNo(typename='') {
+  // 获取当前日期
+  const now = new Date();
+  // 获取月和日
+  const month = String(now.getMonth() + 1).padStart(2, '0'); // getMonth() 返回的是0-11,所以需要加1
+  const day = String(now.getDate()).padStart(2, '0'); // getDate() 返回的是1-31
+  // 生成 0 到 9999 之间的随机整数
+  const randomNum = Math.floor(Math.random() * 10000);
+  // 返回
+  return typename + month + '' + day + '' + String(randomNum).padStart(4, '0');
+}