Przeglądaj źródła

Merge branch 'pre-release' of jianguan-web/qpls-md-app into master

李磊 2 lat temu
rodzic
commit
ff28c911ed
100 zmienionych plików z 6678 dodań i 399 usunięć
  1. 1 1
      .hbuilderx/launch.json
  2. 86 0
      App.vue
  3. 1 0
      api/data.js
  4. 124 0
      api/shelf.js
  5. 85 0
      api/shelfCart.js
  6. 17 0
      api/shelfReplenish.js
  7. 129 0
      api/stockCheck.js
  8. 39 0
      api/user.js
  9. 328 0
      components/chunLei-popups/chunLei-popups.vue
  10. 69 29
      components/kk-printer/index.vue
  11. 122 0
      components/kk-printer/printer/cpcl.js
  12. 2 2
      components/kk-printer/utils/bluetoolth.js
  13. 1 1
      config/index.js
  14. 21 15
      libs/axios.js
  15. 300 0
      libs/jgPush.js
  16. 54 20
      libs/printTools.js
  17. 26 1
      libs/tools.js
  18. 2 1
      main.js
  19. 156 7
      manifest.json
  20. BIN
      nativePlugins/JG-JCore/android/libs/arm64-v8a/libjcore332.so
  21. BIN
      nativePlugins/JG-JCore/android/libs/armeabi-v7a/libjcore332.so
  22. BIN
      nativePlugins/JG-JCore/android/libs/armeabi/libjcore332.so
  23. BIN
      nativePlugins/JG-JCore/android/libs/jcore-android-3.3.2.jar
  24. BIN
      nativePlugins/JG-JCore/android/libs/mips/libjcore332.so
  25. BIN
      nativePlugins/JG-JCore/android/libs/mips64/libjcore332.so
  26. BIN
      nativePlugins/JG-JCore/android/libs/x86/libjcore332.so
  27. BIN
      nativePlugins/JG-JCore/android/libs/x86_64/libjcore332.so
  28. BIN
      nativePlugins/JG-JCore/android/uniplugin_jcore-release.aar
  29. 27 0
      nativePlugins/JG-JCore/ios/JGInforCollectionAuth.h
  30. 17 0
      nativePlugins/JG-JCore/ios/UniPluginJCore.framework/Headers/JCoreModule.h
  31. BIN
      nativePlugins/JG-JCore/ios/UniPluginJCore.framework/Info.plist
  32. BIN
      nativePlugins/JG-JCore/ios/UniPluginJCore.framework/UniPluginJCore
  33. BIN
      nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeDirectory
  34. BIN
      nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeRequirements
  35. BIN
      nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeRequirements-1
  36. 117 0
      nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeResources
  37. BIN
      nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeSignature
  38. BIN
      nativePlugins/JG-JCore/ios/jcore-ios-3.2.5.a
  39. 58 0
      nativePlugins/JG-JCore/package.json
  40. BIN
      nativePlugins/JG-JPush/android/com.heytap.msp-push-2.1.0.aar
  41. BIN
      nativePlugins/JG-JPush/android/libs/MiPush_SDK_Client_3_8_5.jar
  42. BIN
      nativePlugins/JG-JPush/android/libs/jpush-android-3.9.1.jar
  43. BIN
      nativePlugins/JG-JPush/android/libs/jpush-android-plugin-meizu-v3.9.1.jar
  44. BIN
      nativePlugins/JG-JPush/android/libs/jpush-android-plugin-oppo-v3.9.1.jar
  45. BIN
      nativePlugins/JG-JPush/android/libs/jpush-android-plugin-vivo-v3.9.1.jar
  46. BIN
      nativePlugins/JG-JPush/android/libs/jpush-android-plugin-xiaomi-v3.9.1.jar
  47. BIN
      nativePlugins/JG-JPush/android/libs/meizu-push-4.0.2.jar
  48. BIN
      nativePlugins/JG-JPush/android/libs/push_sdk_v3.0.0.jar
  49. BIN
      nativePlugins/JG-JPush/android/uniplugin_jpush-release.aar
  50. 838 0
      nativePlugins/JG-JPush/ios/JPUSHService.h
  51. 17 0
      nativePlugins/JG-JPush/ios/UniPluginJPush.framework/Headers/JPushModule.h
  52. BIN
      nativePlugins/JG-JPush/ios/UniPluginJPush.framework/Info.plist
  53. BIN
      nativePlugins/JG-JPush/ios/UniPluginJPush.framework/UniPluginJPush
  54. BIN
      nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeDirectory
  55. BIN
      nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeRequirements
  56. BIN
      nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeRequirements-1
  57. 117 0
      nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeResources
  58. BIN
      nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeSignature
  59. BIN
      nativePlugins/JG-JPush/ios/jpush-ios-4.8.1.a
  60. 138 0
      nativePlugins/JG-JPush/package.json
  61. 338 18
      pages.json
  62. 12 7
      pages/approveStore/authPass.vue
  63. 12 4
      pages/approveStore/detail.vue
  64. 1 1
      pages/approveStore/list.vue
  65. 272 0
      pages/batchShelves/batchPrint/batchPrint.vue
  66. 224 0
      pages/batchShelves/batchPrint/productList.vue
  67. 542 0
      pages/batchShelves/cartList.vue
  68. 118 0
      pages/batchShelves/chooseTypeModal.vue
  69. 294 0
      pages/batchShelves/editShelfHw.vue
  70. 91 0
      pages/batchShelves/index.vue
  71. 154 0
      pages/batchShelves/printStickerModal.vue
  72. 352 0
      pages/batchShelves/scanProduct.vue
  73. 279 0
      pages/batchShelves/searchProduct.vue
  74. 140 0
      pages/batchShelves/setProductCost.vue
  75. 13 10
      pages/common/partList.vue
  76. 77 15
      pages/common/printTag/printTag.vue
  77. 103 46
      pages/index/index.vue
  78. 1 1
      pages/index/printAbc.vue
  79. 34 14
      pages/latePlay/chooseBulk.vue
  80. 272 82
      pages/latePlay/chooseProduct.vue
  81. 163 0
      pages/login/apply-trial.vue
  82. 1 2
      pages/login/login.scss
  83. 40 5
      pages/login/login.vue
  84. 8 8
      pages/replenishmentManage/chooseTypeModal.vue
  85. 8 2
      pages/replenishmentManage/confirm.vue
  86. 3 6
      pages/replenishmentManage/detail.vue
  87. 55 4
      pages/replenishmentManage/manualPrint.vue
  88. 2 1
      pages/replenishmentManage/outWarehousing.vue
  89. 47 13
      pages/replenishmentManage/replenishmentList.vue
  90. 5 1
      pages/replenishmentManage/scanCodePrint.vue
  91. 4 1
      pages/replenishmentManage/sendOutGoods.vue
  92. 9 4
      pages/replenishmentManage/signWarehousing.vue
  93. 4 1
      pages/replenishmentManage/stockModal.vue
  94. 24 51
      pages/sales/addCustomer.vue
  95. 42 7
      pages/sales/chooseCustomer.vue
  96. 2 2
      pages/sales/chooseProduct.vue
  97. 3 3
      pages/sales/edit.vue
  98. 26 9
      pages/sales/index.vue
  99. 4 3
      pages/sales/listComponent.vue
  100. 7 1
      pages/sales/productPricing.vue

+ 1 - 1
.hbuilderx/launch.json

@@ -4,7 +4,7 @@
     "configurations": [{
     "configurations": [{
      	"app-plus" : 
      	"app-plus" : 
      	{
      	{
-     		"launchtype" : "local"
+     		"launchtype" : "remote"
      	},
      	},
      	"default" : 
      	"default" : 
      	{
      	{

+ 86 - 0
App.vue

@@ -1,4 +1,6 @@
 <script>
 <script>
+	import skJGPush from '@/libs/jgPush.js'
+	import {openMessagePage} from '@/libs/tools.js'
 	export default {
 	export default {
 		globalData: {  
 		globalData: {  
 			baseUrl: '',
 			baseUrl: '',
@@ -24,6 +26,76 @@
 		},
 		},
 		onLaunch: function() {
 		onLaunch: function() {
 			console.log('App launch')
 			console.log('App launch')
+			this.$store.state.vuex_tempData = ''
+			let bgAudioManager = uni.getBackgroundAudioManager();
+			if(uni.getSystemInfoSync().platform == "ios"){
+				// 请求定位权限
+				let locationServicesEnabled = skJGPush.locationServicesEnabled()
+				let locationAuthorizationStatus = skJGPush.getLocationAuthorizationStatus()
+				console.log('locationAuthorizationStatus',locationAuthorizationStatus)	
+				if (locationServicesEnabled == true && locationAuthorizationStatus < 3) {
+					skJGPush.requestLocationAuthorization((result)=>{
+						console.log('定位权限',result.status)
+					})
+				}
+				skJGPush.requestNotificationAuthorization((result)=>{
+					let status = result.status
+					if (status < 2) {
+						uni.showModal({
+							title: '提示',
+							content: '您还没有打开通知权限',
+							success: function (res) {
+								if (res.confirm) {
+									skJGPush.openSettingsForNotification()
+								} else if (res.cancel) {
+									console.log('用户点击取消');
+								}
+							}
+						});
+					}
+				})
+				// 清空角标
+				skJGPush.setBadge(0)
+			}else{
+				// 极光推送-init
+				skJGPush.initJPushService()
+			}
+			 
+			// 极光推送-打开debug
+			skJGPush.openDebug()
+			skJGPush.initCrashHandler()
+			 
+			// 极光推送-获取rid
+			skJGPush.getRegistrationID(result => {
+				console.log('【业务getRegistrationID】', result)
+			})
+			
+			// 极光推送-通知事件回调
+			skJGPush.addNotificationListener(result => {
+				console.log('【业务addNotificationListener】', result)
+				// 点击通知
+				if(result.notificationEventType == 'notificationOpened'){
+					this.setRead(result)
+				}else if(result.notificationEventType == 'notificationArrived'){
+					if(bgAudioManager){
+						bgAudioManager.src = '/static/notes.mp3';
+						bgAudioManager.play()
+					}
+				}else{
+					// 清空角标
+					skJGPush.setBadge(0)
+				}
+			})
+			
+			// 极光推送-标签别名事件回调
+			skJGPush.addTagAliasListener(result => {
+				console.log('【业务addTagAliasListener】', result)
+			})	
+			
+			// 连接状态
+			skJGPush.addConnectEventListener(result => {
+				console.log('【连接状态】', result)
+			})
 		},
 		},
 		onShow: function() {
 		onShow: function() {
 			console.log('App Show')
 			console.log('App Show')
@@ -31,6 +103,20 @@
 		onHide: function() {
 		onHide: function() {
 			console.log('App Hide')
 			console.log('App Hide')
 		},
 		},
+		methods:{
+			setRead(item){
+				const api = require("@/api/user.js")
+				const token = getApp().globalData.token
+				if(token){
+					api.setReadNotice({'noticeId': item.extras.noticeId}).then(res => {
+						console.log(res,'setRead')                                                                                     
+						openMessagePage(item)
+					})
+				}else{
+					uni.$emit("openMessage",item)
+				}
+			},
+		}
 	}
 	}
 </script>
 </script>
 
 

+ 1 - 0
api/data.js

@@ -15,6 +15,7 @@ export const listLookUp = (params) => {
   const url = `lookup/queryLike`
   const url = `lookup/queryLike`
   return axios.request({
   return axios.request({
     url: url,
     url: url,
+	data: params||{},
     method: 'POST'
     method: 'POST'
   }).then(res => res)
   }).then(res => res)
 }
 }

+ 124 - 0
api/shelf.js

@@ -11,6 +11,15 @@ export const getShelfList = (params) => {
 		method: 'post'
 		method: 'post'
 	})
 	})
 }
 }
+
+//  货架  保存
+export const shelfSave = (params) => {
+  return axios.request({
+    url: `shelf/save`,
+    data: params,
+    method: 'post'
+  })
+}
 //  货架  货位产品 列表 不分页
 //  货架  货位产品 列表 不分页
 export const shelfProductList = (params) => {
 export const shelfProductList = (params) => {
   return axios.request({
   return axios.request({
@@ -37,4 +46,119 @@ export const getShelfProductList = (params) => {
 		data: params,
 		data: params,
 		method: 'post'
 		method: 'post'
 	})
 	})
+}
+// 货位产品 列表 
+export const queryShelfProductList = (params) => {
+	let url = `shelf/placeProduct/queryShelfProductList`
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 修改完成标识
+export const modifFinishFlag = (params) => {
+  return axios.request({
+    url: `shelf/modifFinishFlag `,
+    data: params,
+    method: 'post'
+  })
+}
+// 新增货位
+export const addPlaceAndProduct = (params) => {
+  return axios.request({
+    url: `shelf/placeAndProduct/save`,
+    data: params,
+    method: 'post'
+  })
+}
+// 删除货位
+export const delShelfPlaceSn = (params) => {
+  return axios.request({
+    url: `shelf/place/deleteBySn/${params.shelfPlaceSn}`,
+    data: params,
+    method: 'post'
+  })
+}
+// 绑定产品
+export const bindProductList = (params) => {
+	let url = `product/queryPageForXPRH/${params.pageNo}/${params.pageSize}`
+	delete params.pageNo
+	delete params.pageSize
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 查询货位
+export const getProductPlace = (params) => {
+  return axios.request({
+    url: `shelf/app/placeProduct/queryList`,
+    data: params,
+    method: 'post'
+  })
+}
+//  货架  货位产品 详情
+export const shelfProductDetail = (params) => {
+  return axios.request({
+    url: `shelf/placeProduct/queryByPlaceSn/${params.shelfPlaceSn}`,
+    data: params,
+    method: 'get'
+  })
+}
+//  货架  货位产品 保存
+export const shelfProductSave = (params) => {
+  return axios.request({
+    url: `shelf/placeProduct/save`,
+    data: params,
+    method: 'post'
+  })
+}
+// 获取价格显示
+export const getShelfPriceShow = (params) => {
+  return axios.request({
+    url: `bizparam/getShelfPriceShow`,
+    data: params,
+    method: 'post'
+  })
+}
+// 更新价格显示
+export const updateShelfPriceShow = (params) => {
+  return axios.request({
+    url: `bizparam/updateShelfPriceShow`,
+    data: params,
+    method: 'post'
+  })
+}
+
+
+// 货架订单-分页列表
+export const orderBillQueryPage = (params) => {
+  const url = `orderBill/queryPage/${params.pageNo}/${params.pageSize}`
+  delete params.pageNo
+  delete params.pageSize
+  return axios.request({
+    url: url,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 货架订单明细-合计
+export const orderBillDetailCount = (params) => {
+  return axios.request({
+    url: `orderBill/queryDetailCount`,
+    data: params,
+    method: 'post'
+  })
+}
+
+// 货架订单-合计
+export const orderBillQueryCount = (params) => {
+  return axios.request({
+    url: `orderBill/queryCount`,
+    data: params,
+    method: 'post'
+  })
 }
 }

+ 85 - 0
api/shelfCart.js

@@ -0,0 +1,85 @@
+import axios from '@/libs/axios.js'
+
+// 查询产品
+export const queryProduct = (params) => {
+	return axios.request({
+		url: `shelfCart/queryProduct`,
+		data: params,
+		method: 'post'
+	})
+}
+// 查询产品 分页
+export const queryProductPage = (params) => {
+	return axios.request({
+		url: `shelfCart/queryProductPage/${params.pageNo}/${params.pageSize}`,
+		data: params,
+		method: 'post'
+	})
+}
+// 查询货架是否有录入的产品
+export const shelfCartNotEmpty = (params) => {
+	return axios.request({
+		url: `shelfCart/shelfCartNotEmpty`,
+		data: params,
+		method: 'post'
+	})
+}
+// 录入保存
+export const shelfCartSave = (params) => {
+	return axios.request({
+		url: `shelfCart/save`,
+		data: params,
+		method: 'post'
+	})
+}
+
+// 已录入的所有产品
+export const queryMapList = (params) => {
+	return axios.request({
+		url: `shelfCart/queryMap`,
+		data: params,
+		method: 'post'
+	})
+}
+// 查询产品统计
+export const queryCountList = (params) => {
+	return axios.request({
+		url: `shelfCart/queryCount`,
+		data: params,
+		method: 'post'
+	})
+}
+// 删除产品
+export const shelfCartDelete = (params) => {
+	return axios.request({
+		url: `shelfCart/delete`,
+		data: params,
+		method: 'post'
+	})
+}
+
+// 上架确认
+export const shelfCartConfirm = (params) => {
+	return axios.request({
+		url: `shelfCart/confirm`,
+		data: params,
+		method: 'post'
+	})
+}
+
+// 查询货架车上结算价为空的产品
+export const queryEmptyCostList = (params) => {
+	return axios.request({
+		url: `shelfCart/queryEmptyCostList/${params.shelfSn}`,
+		method: 'get'
+	})
+}
+
+// 查询货架车上结算价为空的产品
+export const updateBatchById = (params) => {
+	return axios.request({
+		url: `shelfCart/updateBatchById`,
+		data: params,
+		method: 'post'
+	})
+}

+ 17 - 0
api/shelfReplenish.js

@@ -92,4 +92,21 @@ export const shelfReplenishOutStock = (params) => {
     data: params,
     data: params,
     method: 'post'
     method: 'post'
   })
   })
+}
+
+// 可快速补货产品列表
+export const createShelfReplenishBill = (params) => {
+  return axios.request({
+    url: 'shelfReplenish/createShelfReplenishBill',
+    data: params,
+    method: 'post'
+  })
+}
+//生成补货单
+export const saveReplenishBill = (params) => {
+  return axios.request({
+    url: 'shelfReplenish/saveReplenishBill',
+    data: params,
+    method: 'post'
+  })
 }
 }

+ 129 - 0
api/stockCheck.js

@@ -0,0 +1,129 @@
+import axios from '@/libs/axios.js'
+
+// 盘点完成
+export const stockCheckConfirm = (params) => {
+	let url = `shelfStockCheck/confirm`
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 盘点-删除
+export const stockCheckDeleteBySn = (params) => {
+	let url = `shelfStockCheck/deleteBySn/${params.stockCheckSn}`
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 盘点明细-删除
+export const stockCheckDetailDelete = (params) => {
+	let url = `shelfStockCheck/detail/deleteByStockCheckDetailSn/${params.stockCheckDetailSn}`
+	return axios.request({
+		url: url,
+		method: 'post'
+	})
+}
+// 整单删除
+export const deleteByStockCheckSn = (params) => {
+	let url = `shelfStockCheck/detail/deleteByStockCheckSn/${params.stockCheckSn}`
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 盘点明细-详情
+export const stockCheckDetailBySn = (params) => {
+	let url = `shelfStockCheck/detail/queryBySn/${params.stockCheckDetailSn}`
+	return axios.request({
+		url: url,
+		method: 'get'
+	})
+}
+// 盘点明细-分页列表
+export const stockCheckDetailQueryPage = (params) => {
+	let url = `shelfStockCheck/detail/queryPage/${params.pageNo}/${params.pageSize}`
+	delete params.pageNo
+	delete params.pageSize
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 盘点明细-列表
+export const stockCheckDetailQueryList = (params) => {
+	let url = `shelfStockCheck/detail/queryList/${params.stockCheckSn}`
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 盘点明细-保存
+export const stockCheckDetailSave = (params) => {
+	let url = `shelfStockCheck/detail/save`
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 盘点-详情
+export const stockCheckBySn = (params) => {
+	let url = `shelfStockCheck/queryBySn/${params.stockCheckSn}`
+	return axios.request({
+		url: url,
+		method: 'get'
+	})
+}
+// 盘点-分页列表
+export const stockCheckQueryPage = (params) => {
+	let url = `shelfStockCheck/queryPage/${params.pageNo}/${params.pageSize}`
+	delete params.pageNo
+	delete params.pageSize
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+
+// 查询货架待取货状态的订单明细
+export const queryWaitListByShelfSn = (params) => {
+	let url = `shelfStockCheck/queryWaitListByShelfSn`
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+
+// 查看经销商未完结的盘点单数量
+export const queryStockCheckWaitStateNum = (params) => {
+	let url = `shelfStockCheck/queryWaitStateNum`
+	return axios.request({
+		url: url,
+		method: 'get'
+	})
+}
+// 盘点-保存
+export const stockCheckSave = (params) => {
+	let url = `shelfStockCheck/save`
+	return axios.request({
+		url: url,
+		data: params,
+		method: 'post'
+	})
+}
+// 选择货架盘点单
+export const selectShelfStockCheck = (params) => {
+	let url = `shelfStockCheck/selectShelfStockCheck`
+	return axios.request({
+		url: url,
+		method: 'get'
+	})
+}

+ 39 - 0
api/user.js

@@ -10,6 +10,14 @@ export const login = params => {
 	data: params
 	data: params
   },true)
   },true)
 };
 };
+// 注册
+export const register = params => {
+  return axios.request({
+    url: 'register',
+    method: 'post',
+    data: params
+  }, true)
+}
 // 退出
 // 退出
 export const logout = params => {
 export const logout = params => {
   return axios.request({
   return axios.request({
@@ -18,6 +26,14 @@ export const logout = params => {
     method: 'get'
     method: 'get'
   })
   })
 };
 };
+// 注销账号
+export const logoff = params => {
+  return axios.request({
+    url: 'auth/logoff',
+    method: 'post',
+    data: params
+  })
+}
 //  校验手机号是否注册
 //  校验手机号是否注册
 export const validateUser = params => {
 export const validateUser = params => {
   return axios.request({
   return axios.request({
@@ -121,6 +137,14 @@ export const hasRead = params => {
     method: 'get'
     method: 'get'
   })
   })
 }
 }
+// 设置已读消息
+export const setReadNotice = params => {
+  return axios.request({
+    url: `noticeUser/setReadNotice`,
+	data: params,
+    method: 'post'
+  })
+}
 // 查询所有消息
 // 查询所有消息
 export const getMessage = params => {
 export const getMessage = params => {
   let url = `noticeUser/queryLike/${params.pageNo}/${params.pageSize}`
   let url = `noticeUser/queryLike/${params.pageNo}/${params.pageSize}`
@@ -132,6 +156,21 @@ export const getMessage = params => {
     method: 'post'
     method: 'post'
   })
   })
 }
 }
+// 设置所有已读
+export const setReadAllNotice = params => {
+  return axios.request({
+    url: `noticeUser/setReadAllNotice`,
+    method: 'get'
+  })
+}
+//  公告 详情
+export const noticeUserDetail = (params) => {
+  const url = `notice/findById/${params.id}`
+  return axios.request({
+    url: url,
+    method: 'get'
+  })
+}
 // 获取用户信息
 // 获取用户信息
 export const getUserInfo = params => {
 export const getUserInfo = params => {
   return axios.request({
   return axios.request({

+ 328 - 0
components/chunLei-popups/chunLei-popups.vue

@@ -0,0 +1,328 @@
+<template>
+	<view class="mask" :class="!show?'':'mask-show'" :style="{backgroundColor:show?maskBg:'rgba(0,0,0,0)'}" @tap="tapMask">
+		<view class="popups" :class="[theme]"
+			:style="{top: popupsTop ,left: popupsLeft,flexDirection:direction}">
+			<text :class="dynPlace" :style="{width:'0px',height:'0px'}" v-if="triangle"></text>
+			<view v-for="(item,index) in popData" :key="index" @tap.stop="tapItem(item)" 
+				class="itemChild view" :class="[direction=='row'?'solid-right':'solid-bottom',item.disabled?'disabledColor':'']">
+				<image class="image" :src="item.icon" v-if="item.icon"></image>{{item.title}}
+			</view>
+			<slot></slot>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default{
+		props:{
+			maskBg:{
+				type:String,
+				default:'rgba(0,0,0,0)'
+			},
+			placement:{
+				type:String,
+				default:'default' //default top-start top-end bottom-start bottom-end 
+			},
+			direction:{
+				type:String,
+				default:'column' //column row
+			},
+			x:{
+				type:Number,
+				default:0
+			},
+			y:{
+				type:Number,
+				default:0
+			},
+			value:{
+				type:Boolean,
+				default:false
+			},
+			popData:{
+				type:Array,
+				default:()=>[]
+			},
+			theme:{
+				type:String,
+				default:'light' //light dark
+			},
+			dynamic:{
+				type:Boolean,
+				default:false
+			},
+			gap:{
+				type:Number,
+				default:20
+			},
+			triangle:{
+				type:Boolean,
+				default:true
+			}
+		},
+		data(){
+			return{
+				popupsTop:'0px',
+				popupsLeft:'0px',
+				show:false,
+				dynPlace:''
+			}
+		},
+		mounted() {
+			this.popupsPosition()
+		},
+		methods:{
+			tapMask(){
+				this.$emit('input',!this.value)
+			},
+			tapItem(item){
+				if(item.disabled) return
+				this.$emit('tapPopup',item)
+				this.$emit('input',!this.value)
+			},
+			getStatusBar(){
+				let promise = new Promise((resolve,reject)=>{
+					uni.getSystemInfo({
+						success: function(e) {
+							let customBar
+							// #ifdef H5
+							customBar = e.statusBarHeight + e.windowTop;
+							// #endif
+							resolve(customBar)
+						}
+					})
+				})
+				return promise
+			},
+			async popupsPosition(){
+				let statusBar = await this.getStatusBar()
+				let promise = new Promise((resolve,reject)=>{
+					let popupsDom = uni.createSelectorQuery().in(this).select(".popups")
+					popupsDom.fields({
+					    size: true,  
+					}, (data) => {
+						let width = data.width
+						let height = data.height
+						
+						let y = this.dynamic?this.dynamicGetY(this.y,this.gap):this.transformRpx(this.y)
+						
+						let x = this.dynamic?this.dynamicGetX(this.x,this.gap):this.transformRpx(this.x)
+					
+						
+						// #ifdef H5
+						y = this.dynamic?(this.y+statusBar): this.transformRpx(this.y+statusBar)
+						// #endif 
+						
+						this.dynPlace = this.placement=='default'?this.getPlacement(x,y):this.placement
+						
+						switch(this.dynPlace){
+							case 'top-start':
+								this.popupsTop = `${y+9}px`
+								this.popupsLeft = `${x-15}px`
+								break;
+							case 'top-end':
+								this.popupsTop = `${y+9}px`
+								this.popupsLeft = `${x+15-width}px`
+								break;
+							case 'bottom-start':
+								this.popupsTop = `${y-18-height}px`
+								this.popupsLeft = `${x-15}px`
+								break;
+							case 'bottom-end':
+								this.popupsTop = `${y-9-height}px`
+								this.popupsLeft = `${x+15-width}px`
+								break;
+						}
+						resolve()
+					}).exec();
+					
+				})
+				return promise
+				
+			},
+			getPlacement(x,y){
+				let width = uni.getSystemInfoSync().windowWidth
+				let height = uni.getSystemInfoSync().windowHeight
+				if(x>width/2&&y>height/2){
+					return 'bottom-end'
+				}else if(x<width/2&&y<height/2){
+					return 'top-start'
+				}else if(x>width/2&&y<height/2){
+					return 'top-end'
+				}else if(x<width/2&&y>height/2){
+					return 'bottom-start'
+				}else if(x>width/2){
+					return 'top-end'
+				}else{
+					return 'top-start'
+				}
+			},
+			dynamicGetY(y,gap){
+				
+				let height = uni.getSystemInfoSync().windowHeight
+				y = y<gap?gap:y
+				y = height - y <gap? (height - gap) : y
+				
+				return y
+			},
+			dynamicGetX(x,gap){
+				let width = uni.getSystemInfoSync().windowWidth
+				x = x< gap?gap:x
+				x = width - x <gap? (width - gap) : x
+				return x
+			},
+			transformRpx(params){
+				
+				return params*uni.getSystemInfoSync().screenWidth/375
+			}
+		},
+		watch:{
+			value:{
+				immediate:true,
+				handler:async function (newVal,oldVal){
+					if(newVal) await this.popupsPosition()
+					this.show = newVal
+				}
+			},
+			placement:{
+				immediate:true,
+				handler(newVal,oldVal){
+					this.dynPlace = newVal
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.mask{
+		position: fixed;
+		top: 0;
+		right: 0;
+		bottom: 0;
+		left: 0;
+		z-index: 99999;
+		transition: background 0.3s ease-in-out;
+		visibility: hidden;
+		
+		&.mask-show{
+			visibility: visible;
+		}
+	}
+	.popups{
+		position: absolute;
+		padding: 20rpx;
+		border-radius: 5px;
+		display:flex;
+		.view{
+			padding: 10rpx;
+		}
+		.image{
+			display: inline-block;
+			vertical-align: middle;
+			width: 40rpx;
+			height: 40rpx;
+			margin-right: 20rpx;
+		}
+	}
+	.dark{
+		background-color: #4C4C4C;
+		color: #fff;
+		.top-start:after {
+			content: "";
+			position: absolute;
+			top: -18rpx;
+			left: 10rpx;
+			border-width: 0 20rpx 20rpx;
+			border-style: solid;
+			border-color: transparent transparent #4C4C4C;
+		}
+		.top-end:after {
+			content: "";
+			position: absolute;
+			top: -18rpx;
+			right: 10rpx;
+			border-width: 0 20rpx 20rpx;
+			border-style: solid;
+			border-color: transparent transparent #4C4C4C;
+		}
+		.bottom-start:after {
+			content: "";
+			position: absolute;
+			bottom: -18rpx;
+			left: 10rpx;
+			border-width: 20rpx 20rpx 0 ;
+			border-style: solid;
+			border-color: #4C4C4C transparent transparent ;
+			
+		}
+		.bottom-end:after {
+			content: "";
+			position: absolute;
+			bottom: -18rpx;
+			right: 10rpx;
+			border-width: 20rpx 20rpx 0 ;
+			border-style: solid;
+			border-color: #4C4C4C transparent transparent ;
+		}
+		.disabledColor{
+			color: #c5c8ce;
+		}
+	}
+	.light{
+		color: #515a6e;
+		box-shadow: 0upx 0upx 30upx rgba(0,0,0,0.2);
+		background: #fff;
+		.top-start:after {
+			content: "";
+			position: absolute;
+			top: -18rpx;
+			left: 10rpx;
+			border-width: 0 20rpx 20rpx;
+			border-style: solid;
+			border-color: transparent transparent #fff;
+		}
+		.top-end:after {
+			content: "";
+			position: absolute;
+			top: -18rpx;
+			right: 10rpx;
+			border-width: 0 20rpx 20rpx;
+			border-style: solid;
+			border-color: transparent transparent #fff;
+		}
+		.bottom-start:after {
+			content: "";
+			position: absolute;
+			bottom: -18rpx;
+			left: 10rpx;
+			border-width: 20rpx 20rpx 0 ;
+			border-style: solid;
+			border-color: #fff transparent transparent ;
+			
+		}
+		.bottom-end:after {
+			content: "";
+			position: absolute;
+			bottom: -18rpx;
+			right: 10rpx;
+			border-width: 20rpx 20rpx 0 ;
+			border-style: solid;
+			border-color: #fff transparent transparent ;
+		}
+		.disabledColor{
+			color: #c5c8ce;
+		}
+	}
+	.solid-bottom{
+		border-bottom: 1px solid #ccc;
+	}
+	.solid-right{
+		
+		border-right: 1px solid #ccc;
+	}
+	.popups .itemChild:last-child{
+		border: none;
+	}
+	
+</style>

+ 69 - 29
components/kk-printer/index.vue

@@ -1,7 +1,8 @@
 <template>
 <template>
 	<view class="kk-printer">
 	<view class="kk-printer">
 		<view class="kk-printer-btn">
 		<view class="kk-printer-btn">
-			<u-button @tap="handlePrintTap" :loading="isPrinting" shape="circle" :custom-style="{background:$config('primaryColor')}" type="primary">{{isPrinting?printingText:defaultText}}</u-button>
+			<u-button v-if="printBtnStyle=='blue-large'" @tap="handlePrintTap(1)" :loading="isPrinting||isConnecting" shape="circle" :custom-style="{background:$config('primaryColor')}" type="primary">{{isPrinting?printingText:defaultText}}</u-button>
+			<u-button v-if="printBtnStyle=='default-mid'" shape="circle" size="medium" hover-class="none" @tap="handlePrintTap(1)" :loading="isPrinting||isConnecting">{{isPrinting?printingText:defaultText}}</u-button>
 		</view>
 		</view>
 		<view class="kk-shadow" :class="isShowSearch?'show':''" @tap="handleSearchClose">
 		<view class="kk-shadow" :class="isShowSearch?'show':''" @tap="handleSearchClose">
 			<view class="kk-modal" @tap.stop="doNothing">
 			<view class="kk-modal" @tap.stop="doNothing">
@@ -14,10 +15,11 @@
 						<view class="filter-title">根据蓝牙名过滤</view>
 						<view class="filter-title">根据蓝牙名过滤</view>
 						<input type="text"  placeholder-class="kk-placeholder-class" placeholder="请输入蓝牙名字或设备ID搜索" v-model="filterName" />
 						<input type="text"  placeholder-class="kk-placeholder-class" placeholder="请输入蓝牙名字或设备ID搜索" v-model="filterName" />
 					</view> -->
 					</view> -->
-					<view>
+					<view style="text-align: left;">
 						<view>注意事项:</view>
 						<view>注意事项:</view>
 						<view>1、连接打印机之前,先打开手机蓝牙开关</view>
 						<view>1、连接打印机之前,先打开手机蓝牙开关</view>
 						<view>2、请检查打印机是否已被其它手机连接,如果是请关闭其它手机蓝牙,然后再用您的手机连接</view>
 						<view>2、请检查打印机是否已被其它手机连接,如果是请关闭其它手机蓝牙,然后再用您的手机连接</view>
+						<view>3、如果一直处于打印中状态,但打印机没有任何反应,请关闭app应用重新打开再试试</view>
 					</view>
 					</view>
 					<view class="kk-btn-wrap">
 					<view class="kk-btn-wrap">
 						<view class="kk-btn-item confirm-btn" @tap="searchBtnTap" v-if="!isSearching">
 						<view class="kk-btn-item confirm-btn" @tap="searchBtnTap" v-if="!isSearching">
@@ -36,8 +38,8 @@
 							<view class="empty-text">~ 无可搜索到的设备 ~</view>
 							<view class="empty-text">~ 无可搜索到的设备 ~</view>
 						</view>
 						</view>
 						<view class="" v-else>
 						<view class="" v-else>
-							<view class="kk-devices-item flex align_center" v-for="(item,index) in filterDeviceList" :key="index" @tap="handleConnectDevice(item)">
-								<view>
+							<view class="kk-devices-item flex align_center justify_between" v-for="(item,index) in filterDeviceList" :key="index" @tap="handleConnectDevice(item)">
+								<view style="text-align: left;flex-grow: 1;">
 									<view class="name">
 									<view class="name">
 										<text>设备名称:</text>
 										<text>设备名称:</text>
 										<text>{{item.name?item.name:'未命名'}}</text>
 										<text>{{item.name?item.name:'未命名'}}</text>
@@ -51,9 +53,9 @@
 										<text>{{item.deviceId}}</text>
 										<text>{{item.deviceId}}</text>
 									</view>
 									</view>
 								</view>
 								</view>
-								<view>
+								<view style="width: 120rpx;text-align: right;">
 									<!-- <u-icon :size="60" color="#55aaff" name="plus-circle"></u-icon> -->
 									<!-- <u-icon :size="60" color="#55aaff" name="plus-circle"></u-icon> -->
-									<u-button @tap="handleConnectDevice(item)" :loading="isConnecting" shape="circle" size="mini" :custom-style="{background:$config('primaryColor')}" type="primary">{{isConnecting?'连接中':'连接'}}</u-button>
+									<u-button :loading="isConnecting" @tap="handleConnectDevice(item)" shape="circle" size="mini" :custom-style="{background:$config('primaryColor')}" type="primary">{{isConnecting?'连接中':'连接'}}</u-button>
 								</view>
 								</view>
 							</view>
 							</view>
 						</view>
 						</view>
@@ -110,6 +112,11 @@
 				type:String,
 				type:String,
 				default:'打印中...'
 				default:'打印中...'
 			},
 			},
+			// 按钮样式
+			printBtnStyle:{
+				type: String,
+				default: 'blue-large'
+			},
 			roomcode:{
 			roomcode:{
 				type:String, 
 				type:String, 
 				require:true
 				require:true
@@ -121,6 +128,10 @@
 			roomid:{
 			roomid:{
 				type:String,
 				type:String,
 				require:true
 				require:true
+			},
+			autoConnect: {
+				type: Boolean,
+				default: true
 			}
 			}
 		},
 		},
 		computed:{
 		computed:{
@@ -156,7 +167,7 @@
 			}
 			}
 		},
 		},
 		mounted() {
 		mounted() {
-			
+			this.handlePrintTap(0)
 		},
 		},
 		beforeDestroy(){
 		beforeDestroy(){
 			this.stopSearchBtnTap();
 			this.stopSearchBtnTap();
@@ -165,36 +176,44 @@
 			doNothing(){
 			doNothing(){
 				return;
 				return;
 			},
 			},
-			//点击打印按钮
-			handlePrintTap(){
+			//点击打印按钮,flag : true 如果已连接直接执行打印命令,false,不执行
+			handlePrintTap(flag){
 				//打开蓝牙适配器
 				//打开蓝牙适配器
 				blesdk.openBlue().then((res)=>{
 				blesdk.openBlue().then((res)=>{
 					//获取已连接设备
 					//获取已连接设备
 					blesdk.getConnectedBluetoothDevices().then((res)=>{
 					blesdk.getConnectedBluetoothDevices().then((res)=>{
-						//若没有已连接设备,弹框搜索设备
+						const lastDevice = uni.getStorageSync('vuex_lastBuleDevice')
+						console.log(lastDevice)
 						console.log(res,this.deviceId,this.serviceId,this.writeId,this.onPrintSuccess)
 						console.log(res,this.deviceId,this.serviceId,this.writeId,this.onPrintSuccess)
-						if(res.devices.length == 0){
-							this.isShowSearch = true
-							this.devicesList = []
-							if(this.deviceId){
-								this.closeConnect(this.deviceId)
-							}
-						}else{
-							const lastDevice = this.$store.state.vuex_lastBuleDevice
-							if(lastDevice && res.devices[0].deviceId == lastDevice.deviceId){
+						// 如果之前连接过设备
+						if(lastDevice){
+							// 有正在连接的设备,且和上次连接设备一样
+							if(res.devices.length && res.devices[0].deviceId == lastDevice.deviceId){
 								this.deviceId = lastDevice.deviceId
 								this.deviceId = lastDevice.deviceId
 								this.serviceId = lastDevice.serviceId
 								this.serviceId = lastDevice.serviceId
 								this.writeId = lastDevice.writeId
 								this.writeId = lastDevice.writeId
 								this.readId = lastDevice.readId
 								this.readId = lastDevice.readId
+								if(flag){
+									this.isPrinting = true;
+									this.$nextTick(()=>{
+										this.$emit("startPrint",{
+											deviceId: this.deviceId,
+											serviceId: this.serviceId,
+											writeId: this.writeId
+										},tsc,blesdk)
+									})
+								}
+							}else{
+								// 重新直接连接
+								this.handleConnectDevice(lastDevice)
+							}
+						}else{
+							if(this.autoConnect || flag){
+								//若没有已连接设备,弹框搜索设备
+								this.isShowSearch = true
+								this.devicesList = []
+								this.searchBtnTap()
 							}
 							}
-							this.isPrinting = true;
-							this.$nextTick(()=>{
-								this.$emit("startPrint",{
-									deviceId: this.deviceId,
-									serviceId: this.serviceId,
-									writeId: this.writeId
-								},tsc,blesdk)
-							})
 						}
 						}
 					}).catch((err)=>{
 					}).catch((err)=>{
 						blesdk.catchToast(err);
 						blesdk.catchToast(err);
@@ -210,6 +229,7 @@
 			handleSearchClose(){
 			handleSearchClose(){
 				if(!this.isConnecting){
 				if(!this.isConnecting){
 					this.isShowSearch = false
 					this.isShowSearch = false
+					this.stopSearchBtnTap()
 				}
 				}
 			},
 			},
 			handleSRRIChange(e){
 			handleSRRIChange(e){
@@ -242,10 +262,13 @@
 							verticalAlign:'center'
 							verticalAlign:'center'
 						})
 						})
 					}else{
 					}else{
-						_this.closeConnect(deviceId)
+						_this.closeConnect()
 						plus.nativeUI.toast('设备'+ res.deviceId + '已断开连接',{
 						plus.nativeUI.toast('设备'+ res.deviceId + '已断开连接',{
 							verticalAlign:'center'
 							verticalAlign:'center'
 						})
 						})
+						_this.isShowSearch = true
+						_this.devicesList = []
+						_this.searchBtnTap()
 					}
 					}
 					_this.isConnecting = false
 					_this.isConnecting = false
 			    })
 			    })
@@ -260,6 +283,12 @@
 				console.log('链接失败',err)
 				console.log('链接失败',err)
 				this.isConnecting = false
 				this.isConnecting = false
 				blesdk.catchToast(err.res)
 				blesdk.catchToast(err.res)
+				uni.setStorageSync('vuex_lastBuleDevice','')
+				if(err.res.code == 10012){
+					this.isShowSearch = true
+					this.devicesList = []
+					this.searchBtnTap()
+				}
 			},
 			},
 			onGetServicesSuccess(res){
 			onGetServicesSuccess(res){
 				console.log('获取服务',res)
 				console.log('获取服务',res)
@@ -275,10 +304,15 @@
 				this.writeId = res.writeId;
 				this.writeId = res.writeId;
 				this.readId = res.readId;
 				this.readId = res.readId;
 				this.isShowSearch = false;
 				this.isShowSearch = false;
-				this.$store.state.vuex_lastBuleDevice = {deviceId:this.deviceId,serviceId:this.serviceId,writeId:this.writeId,readId:this.readId}
+				try {
+					uni.setStorageSync('vuex_lastBuleDevice', {deviceId:this.deviceId,serviceId:this.serviceId,writeId:this.writeId,readId:this.readId});
+				} catch (e) {
+					// error
+				}
 			},
 			},
 			onGetCharacterFail(err){
 			onGetCharacterFail(err){
 				console.log('特征值获取失败')
 				console.log('特征值获取失败')
+				this.isPrinting = false;
 			},
 			},
 			onPrintSuccess(){
 			onPrintSuccess(){
 				this.isPrinting = false;
 				this.isPrinting = false;
@@ -291,6 +325,9 @@
 			},
 			},
 			closeConnect(){
 			closeConnect(){
 				blesdk.closeBLEConnection(this.deviceId)
 				blesdk.closeBLEConnection(this.deviceId)
+				this.isPrinting = false;
+				uni.hideLoading();
+				this.$emit('closeConnect')
 			},
 			},
 		}
 		}
 	}
 	}
@@ -421,6 +458,9 @@
 										width: 80%;
 										width: 80%;
 									}
 									}
 								}
 								}
+								button{
+									width: auto;
+								}
 							}
 							}
 						}
 						}
 					}
 					}

+ 122 - 0
components/kk-printer/printer/cpcl.js

@@ -0,0 +1,122 @@
+/**
+ * cpcl 命令打印工具类
+ * 2021.04.26 uni-app版本
+ * @auth boolTrue
+ */
+var gbk = require("./printUtil-GBK.js");
+var jpPrinter = {
+	createNew: function() {
+		var jpPrinter = {};
+		var data = "";
+		var command = []
+		var rawCommand = ''
+
+		jpPrinter.name = "标签模式";
+		
+		jpPrinter.addCommand = function(content) { //将指令转成数组装起
+			rawCommand += content
+		}
+		
+		jpPrinter.init = function(width, height, printNum, rotation = 0, offset = 0) {
+			var strCmd = '! ' + offset + ' 200 200 ' + height + ' ' + printNum + '\n';
+			strCmd += "PAGE-WIDTH " + width + '\n';
+			if (rotation == 1)
+				strCmd += "ZPROTATE90\n";
+			else if (rotation == 2)
+				strCmd += "ZPROTATE180\n";
+			else if (rotation == 3)
+				strCmd += "ZPROTATE270\n";
+			else
+				strCmd += "ZPROTATE0\n";
+			jpPrinter.addCommand(strCmd)
+		};
+		
+		jpPrinter.setText = function(x, y, font, xsize, ysize, str) { //横向打印文字
+			data = "T " + "4" + " " + xsize + " " + x + " " + y + " " + str + "\n"
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setGap = function(pageWidth) { //设置标签模式
+			data = "GAP-SENSE" + "\n";
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setSpeed = function(printSpeed) { //设置打印机速度0 - 5
+			data = "SPEED " + printSpeed + "\n";
+			jpPrinter.addCommand(data)
+		};
+
+		jpPrinter.setDensity = function(printDensity) { //设置打印机浓度最亮的打印输出为对比度级别 0。最暗的对比度级别为 3。
+			data = "CONTRAST " + printDensity + "\n";
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setMag = function(w,h) { //字体放大指定的放大倍数。
+			data = "SETMAG " + w + " " + h + "\n"
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setLine = function(x0, y0, x1, y1, width) { //绘制线条
+			data = "LINE " + x0 + " " + y0 + " " + x1 + " " + y1 + " " + width + "\n"
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setBox = function(x_start, y_start, x_end, y_end, thickness) { //绘制方框
+			data = "BOX " + x_start + " " + y_start + " " + x_end + " " + y_end + " " + thickness + "\n";
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setFeed = function(feed) { //将纸向前推出n
+			data = "PREFEED " + feed + "\n";
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setQR = function(x, y, level, ver, scale, content) { //打印二维码
+			var strCmd = 'B QR ' + x + ' ' + y + ' M ' + ver + ' U ' + scale + '\n' + level + 'A,' + content + '\n';
+			strCmd += 'ENDQR\n';
+			jpPrinter.addCommand(strCmd)
+		};
+		
+		jpPrinter.setBar = function(type, width, ratio, height, x, y, content) { //打印条形码
+			data = "BARCODE " + type + " " + width + " " + ratio + " " + height + " " + x + " " + y + " " + content + "\n"
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setSound = function(interval) { //控制蜂鸣器,蜂鸣持续时间
+			data = "BEEP " + interval + "\n";
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setPageForm = function() { //换页
+			data = "FORM "+"\n"
+			jpPrinter.addCommand(data)
+		};
+		
+		jpPrinter.setPagePrint = function() { //打印页面
+			data = "PRINT "+"\n"
+			jpPrinter.addCommand(data)
+		};
+		
+		// 添加命令
+		jpPrinter.RawCommand = function(data) {
+			jpPrinter.addCommand(data)
+		}
+		
+		//获取打印数据
+		jpPrinter.getData = function() {
+			let buffer = gbk.strToGBKByte(rawCommand)
+			return buffer;
+		};
+
+		jpPrinter.getRawData = function() {
+			return rawCommand;
+		};
+		jpPrinter.clearCommand = function() {
+			rawCommand = ''
+		};
+
+		return jpPrinter;
+	}
+};
+
+module.exports.jpPrinter = jpPrinter;

+ 2 - 2
components/kk-printer/utils/bluetoolth.js

@@ -305,7 +305,7 @@ export function senBlData(deviceId, serviceId, characteristicId,uint8Array,laste
 export function catchToast(err) {
 export function catchToast(err) {
 	const errMsg = {
 	const errMsg = {
 		10000: '未初始化蓝牙模块',
 		10000: '未初始化蓝牙模块',
-		10001: '蓝牙未打开',
+		10001: '蓝牙未打开,请打开蓝牙开关',
 		10002: '没有找到指定设备',
 		10002: '没有找到指定设备',
 		10003: '连接失败',
 		10003: '连接失败',
 		10004: '没有找到指定服务',
 		10004: '没有找到指定服务',
@@ -314,7 +314,7 @@ export function catchToast(err) {
 		10007: '当前特征值不支持此操作',
 		10007: '当前特征值不支持此操作',
 		10008: '系统上报异常',
 		10008: '系统上报异常',
 		10009: '系统版本低于 4.3 不支持BLE',
 		10009: '系统版本低于 4.3 不支持BLE',
-		10012: '连接超时,请检查打印机是否被其它手机连接中'
+		10012: '连接超时,请重试'
 	};
 	};
 	let coode = err.errCode ? err.errCode.toString() : '';
 	let coode = err.errCode ? err.errCode.toString() : '';
 	let msg = errMsg[coode];
 	let msg = errMsg[coode];

+ 1 - 1
config/index.js

@@ -6,7 +6,7 @@ const getConfig = (theme) => {
 			themePath: 'default',
 			themePath: 'default',
 			pro_URL: 'https://iscm.360arrow.com/qpls-md/', // 生产地址
 			pro_URL: 'https://iscm.360arrow.com/qpls-md/', // 生产地址
 			uat_URL: 'http://p.iscm.360arrow.com/qpls-md/', // 预发布地址
 			uat_URL: 'http://p.iscm.360arrow.com/qpls-md/', // 预发布地址
-			dev_URL: 'http://192.168.0.102/qpls-md/', // 本地地址
+			dev_URL: 'http://192.168.0.103:8503/qpls-md/', // 本地地址
 			appName: 'iSCM智慧供应链', // app 名称
 			appName: 'iSCM智慧供应链', // app 名称
 			company: '陕西山海高科信息技术有限公司',
 			company: '陕西山海高科信息技术有限公司',
 			loadText:{
 			loadText:{

+ 21 - 15
libs/axios.js

@@ -1,5 +1,6 @@
 import { objToUrl } from '@/libs/tools.js';
 import { objToUrl } from '@/libs/tools.js';
 const baseUrl = getApp().globalData.baseUrl
 const baseUrl = getApp().globalData.baseUrl
+import store from '@/store/index.js'
 //带Token请求
 //带Token请求
 const request = (opts, hasToken) => {
 const request = (opts, hasToken) => {
 	const authorization = getApp().globalData.token
 	const authorization = getApp().globalData.token
@@ -27,9 +28,16 @@ const request = (opts, hasToken) => {
 	let promise = new Promise(function(resolve, reject) {
 	let promise = new Promise(function(resolve, reject) {
 		uni.request(DefaultOpts).then(
 		uni.request(DefaultOpts).then(
 			(res) => {
 			(res) => {
+				console.log(res)
 				// 是否超时已跳转
 				// 是否超时已跳转
 				let loginTimeOut = uni.getStorageSync('loginTimeOut');
 				let loginTimeOut = uni.getStorageSync('loginTimeOut');
 				if(res[0]&&res[0].errMsg.indexOf('request:fail')>=0){
 				if(res[0]&&res[0].errMsg.indexOf('request:fail')>=0){
+					uni.showToast({
+						icon:'none',
+						title: '网络请求失败,请检查网络连接情况',
+						mask: true,
+						duration: 4000 
+					})
 					resolve({
 					resolve({
 						status: 6000,
 						status: 6000,
 						message: "网络请求失败"
 						message: "网络请求失败"
@@ -48,31 +56,29 @@ const request = (opts, hasToken) => {
 					resolve(ret)
 					resolve(ret)
 				}else{
 				}else{
 					if(ret.status == '401' || ret.status == '1099'){  //  未登录或登录过期
 					if(ret.status == '401' || ret.status == '1099'){  //  未登录或登录过期
-					    // 除过查询未完成订单的请求
-						// if(opts.url.indexOf("order/unFinishedOrderRunStatus")<0){
-							uni.showToast({
-								icon:'none',
-								title: '未登录或登录已过期,请重新登录',
-								duration: 5000 
-							})
-							setTimeout(function() {
-								const currentRoute = getRoutePath();
-								const url = `/pages/login/login`
-								uni.redirectTo({ url })
-							}, 1000)
-						// }
+					   uni.showToast({
+					   	icon:'none',
+					   	title: '登录已过期,请重新登录',
+					   	duration: 5000 
+					   })
+					   store.state.vuex_token = ''
+					   setTimeout(function() {
+					   	const url = `/pages/login/login`
+					   	uni.redirectTo({ url })
+					   }, 1000)
 					}
 					}
 					else{
 					else{
 						console.log(opts.url,'opts.url')
 						console.log(opts.url,'opts.url')
 						if(ret.status == 500){
 						if(ret.status == 500){
 							if(
 							if(
 							opts.url.indexOf("shelfReplenish/detail/outScan")<0&&
 							opts.url.indexOf("shelfReplenish/detail/outScan")<0&&
-							opts.url.indexOf("shelfReplenish/detail/queryByProductQrCode")<0){
+							opts.url.indexOf("shelfReplenish/detail/queryByProductQrCode")<0&&
+							opts.url.indexOf("shelfStockCheck/confirm")<0){
 								uni.showToast({
 								uni.showToast({
 									icon:'none',
 									icon:'none',
 									title: ret.message,
 									title: ret.message,
 									mask: true,
 									mask: true,
-									duration: 3000 
+									duration: 4000 
 								})
 								})
 							}
 							}
 						}
 						}

+ 300 - 0
libs/jgPush.js

@@ -0,0 +1,300 @@
+// 引用方式
+var jpushModule = uni.requireNativePlugin("JG-JPush");
+console.log(jpushModule,'【sk】【引用方式】【jpushModule】【requireNativePlugin】')
+ 
+// 开启 debug 模式,默认是关闭
+function openDebug() {
+    jpushModule.setLoggerEnable(true);
+}
+ 
+// 关闭 debug 模式,默认是关闭
+function closeDebug() {
+    jpushModule.setLoggerEnable(false);
+}
+
+function isNotificationEnabled(skBack){
+	jpushModule.isNotificationEnabled(result=>{//number
+		console.log('检查当前应用的通知开关是否开启 =>',result)
+		skBack(result.code)
+	});
+}
+
+function requestLocationAuthorization(skBack){
+	jpushModule.requestLocationAuthorization(result=>{//number
+		console.log('定位权限',result)
+		skBack(result)
+	});
+}
+
+function requestNotificationAuthorization(skBack){
+	jpushModule.requestNotificationAuthorization(result=>{//number
+		console.log('是否打开通知权限',result)
+		skBack(result)
+	});
+}
+ 
+// 获取 RegistrationID,只有当应用程序成功注册到 JPush 的服务器时才返回对应的值,否则返回空字符串
+function getRegistrationID(skBack) {
+    jpushModule.getRegistrationID(result=>{
+        // code number  状态码 0 - 成功, 1011 - iOS模拟器调用会报此错误
+        // registerID   string  返回的 registrationID
+        console.log('【sk】获取 RegistrationID=>',result)
+        skBack(result.registerID)
+    })
+}
+ 
+// 跳转至系统设置页面,0 - 成功 1 - 失败
+function openSettingsForNotification() {
+    jpushModule.openSettingsForNotification((result)=>{
+        // code number  0 - 成功 1 - 失败
+        console.log('【sk】跳转至系统设置页面result=>',result.code)
+    })
+}
+ 
+// 初始化SDK iOS 说明:如果在mainfest.json里 将JPUSH_DEFAULTINITJPUSH_IOS值配置为"true",插件内部将默认初始化JPush,用户则不需要调用该初始化方法。
+function initJPushService() {
+    console.log(jpushModule)
+    jpushModule.initJPushService()
+}
+ 
+// 连接状态回调,true - 已连接, false - 未连接
+function addConnectEventListener(skBack) {
+    jpushModule.addConnectEventListener(result=>{
+        // connectEnable    boolean true - 已连接, false - 未连接
+        console.log('【sk】连接状态回调=>',result.connectEnable)
+        skBack(result.connectEnable);
+    })
+}
+ 
+// 通知事件回调
+function addNotificationListener(skBack) {
+    jpushModule.addNotificationListener(result=>{
+        // messageID    string  唯一标识通知消息的 ID
+        // title    string  对应 Portal 推送通知界面上的“通知标题”字段
+        // content  string  对应 Portal 推送通知界面上的“通知内容”字段
+        // badge    string  对应 Portal 推送通知界面上的可选设置里面的“badge”字段 (ios only)
+        // ring string  推送通知界面上的可选设置里面的“sound”字段 (ios only)
+        // extras   dictionary  对应 Portal 推送消息界面上的“可选设置”里的附加字段
+        // iOS  dictionary  对应原生返回的通知内容,如需要更多字段请查看该字段内容
+        // android  dictionary  对应原生返回的通知内容,如需要更多字段请查看该字段内容
+        // notificationEventType    string  分为notificationArrived和notificationOpened两种
+        console.log('【sk】通知事件回调result=>',result)
+        skBack(result);
+    })
+}
+ 
+// 自定义消息事件回调
+function addCustomMessageListener(skBack) {
+    jpushModule.addCustomMessageListener(result=>{
+        // messageID    string  唯一标识通知消息的 ID
+        // content  string  对应 Portal 推送通知界面上的“通知内容”字段
+        // extras   dictionary  对应 Portal 推送消息界面上的“可选设置”里的附加字段
+        console.log('【sk】自定义消息事件回调result=>',result)
+        skBack(result);
+    })
+}
+ 
+// 应用内消息回调
+function addInMessageListener(skBack) {
+    jpushModule.addInMessageListener(result=>{
+        // eventType    string  show - 应用内消息展示 disappear - 应用内消息已消失 click - 应用内消息点击
+        // messageType  string  消息类型, eventType 不为 disappear时返回, inMessageNoti - 通知类型的inMessage
+        // content  dictionary  应用内消息内容, eventType 不为 disappear 时返回
+        console.log('【sk】应用内消息回调result=>',result)
+        skBack(result);
+    })
+}
+ 
+// 本地通知事件回调
+function addLocalNotificationListener(skBack) {
+    jpushModule.addLocalNotificationListener(result=>{
+        // messageID    string  唯一标识通知消息的ID
+        // title    string  对应“通知标题”字段
+        // content  string  对应“通知内容”字段
+        // extras   dictionary  对应“附加内容”字段
+        console.log('【sk】本地通知事件回调result=>',result)
+        skBack(result);
+    })
+}
+ 
+// 添加一个本地通知
+function addLocalNotification(e) {
+	console.log('添加一个本地通知',e)
+    jpushModule.addLocalNotification({
+        messageID: e.messageID ? e.messageID : '', // 唯一标识通知消息的ID
+        title: e.title ? e.title : '', // 对应“通知标题”字段
+        content: e.content ? e.content : '', // 对应“通知内容”字段
+        extras: e.extras ? e.extras : {name: '', age: ''} // 对应“附加内容”字段
+    })
+}
+ 
+// 移除指定的本地通知
+function removeLocalNotification(e) {
+    jpushModule.removeLocalNotification({
+        messageID: e.messageID ? e.messageID : '' // 唯一标识通知消息的ID
+    })
+}
+ 
+// 移除所有的本地通知
+function clearLocalNotifications() {
+    jpushModule.clearLocalNotifications()
+}
+ 
+// 标签别名事件回调
+function addTagAliasListener(skBack) {
+    jpushModule.addTagAliasListener(result=>{
+        // code number  请求状态码 0 - 成功
+        // sequence number  请求时传入的序列号,会在回调时原样返回
+        // tags StringArray 执行tag数组操作时返回
+        // tag  string  执行查询指定tag(queryTag)操作时会返回
+        // tagEnable    boolean 执行查询指定tag(queryTag)操作时会返回是否可用
+        // alias    string  对alias进行操作时返回
+        console.log('【sk】标签别名事件回调result=>',result)
+        skBack(result);
+    })
+}
+ 
+// 新增标签
+function addTags(e) {
+    jpushModule.addTags({
+        'tags': e.tags ? e.tags : [], // StringArray  string类型的数组
+        'sequence': e.sequence ? e.sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 覆盖标签
+function updateTags(e) {
+    jpushModule.updateTags({
+        'tags': e.tags ? e.tags : [], // StringArray  string类型的数组
+        'sequence': e.sequence ? e.sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 删除指定标签
+function deleteTags(e) {
+    jpushModule.deleteTags({
+        'tags': e.tags ? e.tags : [], // StringArray  string类型的数组
+        'sequence': e.sequence ? e.sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 清除所有标签
+function cleanTags(e) {
+    jpushModule.cleanTags({
+        'sequence': e.sequence ? e.sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 查询指定 tag 与当前用户绑定的状态
+function queryTag(e) {
+    jpushModule.queryTag({
+        'tag': e.tag ? e.tag : '', // string  需要查询的标签
+        'sequence': e.sequence ? sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 查询所有标签
+function getAllTags(e) {
+    jpushModule.getAllTags({
+        'sequence': e.sequence ? e.sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 设置别名
+function setAlias(e) {
+    console.log('设置别名',e)
+    jpushModule.setAlias({
+        'alias': e.alias ? e.alias : '', // string  有效的别名组成:字母(区分大小写)、数字、下划线、汉字、特殊字符@!#$&*+=.|
+        'sequence': e.sequence ? e.sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 删除别名
+function deleteAlias(e) {
+    jpushModule.deleteAlias({
+        'sequence': e.sequence ? e.sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 查询别名
+function queryAlias(e) {
+    jpushModule.queryAlias({
+        'sequence': e.sequence ? e.sequence : 1 // number  请求时传入的序列号,会在回调时原样返回
+    })
+}
+ 
+// 开启 CrashLog 上报
+function initCrashHandler() {
+    jpushModule.initCrashHandler()
+}
+ 
+// 设置地理围栏的最大个数
+function setMaxGeofenceNumber(e) {
+    jpushModule.setMaxGeofenceNumber(e.geofenceNumber ? e.geofenceNumber : 10) // 默认值为 10 ,iOS系统默认地理围栏最大个数为20
+}
+ 
+// 删除指定id的地理围栏
+function deleteGeofence(e) {
+    jpushModule.deleteGeofence(e.geofence ? e.geofence : '') // 删除指定id的地理围栏
+}
+ 
+// 设置 Badge
+function setBadge(e) {
+    jpushModule.setBadge(e.badge ? e.badge : 0) // number
+}
+ 
+// 设置手机号码
+function setMobileNumber(e) {
+    jpushModule.setMobileNumber({
+        sequence: e.sequence ? e.sequence : 1, // number  请求时传入的序列号,会在回调时原样返回
+        mobileNumber: e.mobileNumber ? e.mobileNumber : '' // string  手机号码 会与用户信息一一对应。可为空,为空则清除号码。
+    })
+}
+ 
+// 设置手机号码回调
+function addMobileNumberListener(skBack) {
+    jpushModule.addMobileNumberListener(result=>{
+        // code number  状态码 0 - 成功
+        // sequence number  请求时传入的序列号,会在回调时原样返回
+        console.log('【sk】设置手机号码回调result=>',result)
+        skBack(result);
+    })
+}
+ 
+ 
+module.exports = {
+    openDebug: openDebug,
+    closeDebug: closeDebug,
+    getRegistrationID: getRegistrationID,
+    openSettingsForNotification: openSettingsForNotification,
+    initJPushService: initJPushService,
+	isNotificationEnabled: isNotificationEnabled,
+    addConnectEventListener: addConnectEventListener,
+    addNotificationListener: addNotificationListener,
+    addCustomMessageListener: addCustomMessageListener,
+    addInMessageListener: addInMessageListener,
+    addLocalNotificationListener: addLocalNotificationListener,
+    addLocalNotification: addLocalNotification,
+    removeLocalNotification: removeLocalNotification,
+    clearLocalNotifications: clearLocalNotifications,
+    addTagAliasListener: addTagAliasListener,
+    addTags: addTags,
+    updateTags: updateTags,
+    deleteTags: deleteTags,
+    cleanTags: cleanTags,
+    queryTag: queryTag,
+    getAllTags: getAllTags,
+    setAlias: setAlias,
+    deleteAlias: deleteAlias,
+    queryAlias: queryAlias,
+    initCrashHandler: initCrashHandler,
+    setMaxGeofenceNumber: setMaxGeofenceNumber,
+    deleteGeofence: deleteGeofence,
+    setBadge: setBadge,
+    setMobileNumber: setMobileNumber,
+    addMobileNumberListener: addMobileNumberListener,
+	locationServicesEnabled: ()=> jpushModule.locationServicesEnabled(),
+	getLocationAuthorizationStatus: ()=> jpushModule.getLocationAuthorizationStatus(),
+	requestLocationAuthorization: requestLocationAuthorization,
+	requestNotificationAuthorization: requestNotificationAuthorization
+}

+ 54 - 20
libs/printTools.js

@@ -51,12 +51,12 @@ export const textFormat = function(command,text,maxFontNums,left,top,lightHeight
 		if(align=="center"){
 		if(align=="center"){
 			const ltxt = textArr[i]
 			const ltxt = textArr[i]
 			const ltlen = getBytesCount(ltxt)/2*fontSize
 			const ltlen = getBytesCount(ltxt)/2*fontSize
-			command.setText(left+((maxNums-ltlen)/2)*rowHeight, rowTop, "TSS24.BF2", fontSize, fontSize, ltxt)
+			command.setText(left+((maxNums-ltlen)/2)*rowHeight-2, rowTop, "TSS24.BF2", fontSize, fontSize, ltxt)
 		}
 		}
 		else{
 		else{
 			command.setText(left, rowTop, "TSS24.BF2", fontSize, fontSize, textArr[i])
 			command.setText(left, rowTop, "TSS24.BF2", fontSize, fontSize, textArr[i])
 		}
 		}
-		rowTop = rowTop+rowHeight*fontSize+10
+		rowTop = rowTop+rowHeight*fontSize+5
 	}
 	}
 	return rowTop
 	return rowTop
 }
 }
@@ -72,15 +72,15 @@ export const printText = function(tsc,text){
 }
 }
 // 60 * 40 尺寸模板
 // 60 * 40 尺寸模板
 export const printTempl = function(tsc,data){
 export const printTempl = function(tsc,data){
-	let top = 24 // 距离顶部10点像素
+	let top = 32 // 距离顶部
 	const left = 8 // 距离左边
 	const left = 8 // 距离左边
 	const lightHeight = 24 // 行高3mm,1mm = 8点
 	const lightHeight = 24 // 行高3mm,1mm = 8点
 	const pageW = 60 // 页签宽度mm
 	const pageW = 60 // 页签宽度mm
 	const pageH = 40 // 页签高度mm
 	const pageH = 40 // 页签高度mm
-	const maxFontNums = Math.floor((pageW*8-left*2)/lightHeight) // 每行最多字体数
-	const leftMaxFnums = Math.floor(maxFontNums*0.6)
-	let rightTop = 0
-	let rightLeft = (leftMaxFnums+1.2)*lightHeight
+	const maxFontNums = Math.floor((pageW*8-left*4)/lightHeight) // 每行最多字体数
+	const leftMaxFnums = Math.floor(maxFontNums*0.4)
+	const rightMaxFnums = leftMaxFnums + 1
+	let rightLeft = (leftMaxFnums+2.5)*lightHeight
 	// 初始化打印机
 	// 初始化打印机
 	const command = tsc.jpPrinter.createNew()
 	const command = tsc.jpPrinter.createNew()
 	command.init()
 	command.init()
@@ -91,22 +91,56 @@ export const printTempl = function(tsc,data){
 	top = textFormat(command,data.dealerName,maxFontNums,left,top,lightHeight,"center",1)
 	top = textFormat(command,data.dealerName,maxFontNums,left,top,lightHeight,"center",1)
 	// 数字货架名称文字
 	// 数字货架名称文字
 	top = top+10
 	top = top+10
-	rightTop = top
-	top = textFormat(command,data.shelfName,leftMaxFnums,left,top,lightHeight,"left",1)
+	top = textFormat(command,data.shelfName,maxFontNums,left,top,lightHeight,"center",1)
+	// 二维码
+	top = top+15
+	command.setQR(left*6, top, "M", 5, "A", data.barCode)
+	// 货位号
+	const rightTop = textFormat(command,data.shelfPlaceCode,rightMaxFnums,rightLeft,top,lightHeight,"left",4)
 	// 产品编码
 	// 产品编码
-	top = top+10
-	top = textFormat(command,data.productCode,leftMaxFnums,left,top,lightHeight,"left",1)
-	// 产品名称
-	top = top+6
-	top = textFormat(command,data.productName,leftMaxFnums,left,top,lightHeight,"left",1)
+	top = rightTop + 1
+	top = textFormat(command,data.productCode,rightMaxFnums,rightLeft,top,lightHeight,"left",1)
+	
 	// 打印人打印时间
 	// 打印人打印时间
+	top = top+3
+	top = textFormat(command,data.printDate,rightMaxFnums,rightLeft,top,lightHeight,"left",1)
+	
+	// 打印分数1,每个标签重发打印2次
+	command.setPagePrint(1,data.currentInven) 
+	return command
+}
+
+// 40 * 30 尺寸模板
+export const printMiniTempl = function(tsc,data){
+	let top = 24 // 距离顶部
+	const left = 4 // 距离左边
+	const lightHeight = 24 // 行高3mm,1mm = 8点
+	const pageW = 40 // 页签宽度mm
+	const pageH = 30 // 页签高度mm
+	const maxFontNums = Math.floor((pageW*8-left*2)/lightHeight) // 每行最多字体数
+	const leftMaxFnums = Math.floor(maxFontNums*0.5)
+	const rightMaxFnums = Math.floor(maxFontNums*0.4)
+	let rightLeft = (leftMaxFnums+1)*lightHeight
+	// 初始化打印机
+	const command = tsc.jpPrinter.createNew()
+	command.init()
+	command.setSize(pageW, pageH) // 标签纸张宽高,单位mm
+	command.setGap(3) // 标签上下间距,单位mm
+	command.setCls() // 清除缓冲区数据
+	// 经销商文字高度,是否换行
+	top = textFormat(command,data.dealerName,maxFontNums,left,top,lightHeight,"center",1)
+	// 数字货架名称文字
 	top = top+10
 	top = top+10
-	top = textFormat(command,data.printDate+' '+data.printUser,leftMaxFnums,left,top,lightHeight,"left",1)
-	// 货位号
-	const qrtop = textFormat(command,data.shelfPlaceCode,maxFontNums-leftMaxFnums-1.2,rightLeft,rightTop,lightHeight,"center",2)
+	top = textFormat(command,data.shelfName,maxFontNums,left,top,lightHeight,"center",1)
 	// 二维码
 	// 二维码
-	command.setQR(rightLeft, qrtop, "M", 5, "A", data.barCode)
-	command.setPagePrint(1,data.currentInven) // 打印分数1,每个标签重发打印2次
-	console.log("开始打印了",command.getData())
+	top = top+10
+	command.setQR(left, top, "M", 5, "A", data.barCode)
+	// 货位号
+	const rightTop = textFormat(command,data.shelfPlaceCode,rightMaxFnums,rightLeft,top,lightHeight,"left",3)
+	// 产品编码
+	top = rightTop
+	top = textFormat(command,data.productCode,rightMaxFnums,rightLeft,top,lightHeight,"left",1)
+	// 打印分数1,每个标签重发打印2次
+	command.setPagePrint(1,data.currentInven) 
 	return command
 	return command
 }
 }

+ 26 - 1
libs/tools.js

@@ -1,6 +1,5 @@
 let carmera = uni.requireNativePlugin('ziteng-maskcamera')
 let carmera = uni.requireNativePlugin('ziteng-maskcamera')
 let cameraModule = uni.requireNativePlugin("SMUniPlugin-CameraModule")
 let cameraModule = uni.requireNativePlugin("SMUniPlugin-CameraModule")
-
 // 处理数字千位分隔符  num 数值,decimal要保留的小数位数
 // 处理数字千位分隔符  num 数值,decimal要保留的小数位数
 export const toThousands = (num, decimal) => {
 export const toThousands = (num, decimal) => {
   if (decimal) {
   if (decimal) {
@@ -331,6 +330,11 @@ export const checkVersionToLoadUpdate = function(newVersion,type,callback){
 			cancelText:'稍后进行',
 			cancelText:'稍后进行',
 			success: function (res) {
 			success: function (res) {
 				if (res.confirm) {
 				if (res.confirm) {
+					// 清空缓存token
+					let tmp = uni.getStorageSync('lifeData');
+					tmp = tmp ? tmp : {};
+					tmp['vuex_token'] = '';
+					uni.setStorageSync('lifeData', tmp);
 					if(curVer.platform == 'android'){
 					if(curVer.platform == 'android'){
 						//设置 最新版本apk的下载链接
 						//设置 最新版本apk的下载链接
 						downloadApp(newVersion.attachment);
 						downloadApp(newVersion.attachment);
@@ -423,4 +427,25 @@ export const saveImgToAliOss = function(src,callback){
 			console.log(error)
 			console.log(error)
 		}
 		}
 	});
 	});
+}
+
+// 点击消息打开对应的页面
+export const openMessagePage = function(data){
+	// 急送订单
+	if (data.extras.bizType == 'TEMP_ORDER') {
+		uni.navigateTo({ url: '/pages/sales/edit?pageType=detail&data='+JSON.stringify({ salesBillSn: data.extras.bizSn }) })
+	}
+	// 补货订单
+	if (data.extras.bizType == 'SHELF_REPLENISH') {
+		uni.navigateTo({ url: '/pages/replenishmentManage/replenishmentList?billState=WAIT_CONFIRM' })
+	}
+	// 货架订单
+	if (data.extras.bizType == 'SHELF_ORDER') {
+		uni.navigateTo({ url: '/pages/shelfOrder/orderDetail?pageType=detail&orderBillSn='+data.extras.bizSn })
+	}
+	// 货架异常
+	if (data.extras.bizType == 'SHELF_WARN') {
+		const shelfName = data.content.split('已经超过')[0]
+		uni.navigateTo({ url: '/pages/shelfOrder/shelfOrder?bizType=SHELF_WARN&shelfSn='+data.extras.bizSn+'&shelfName='+shelfName })
+	}
 }
 }

+ 2 - 1
main.js

@@ -48,7 +48,8 @@ Vue.prototype.toashMsg = function (title) {
 	title = title == undefined ? "系统繁忙" : title;
 	title = title == undefined ? "系统繁忙" : title;
 	uni.showToast({
 	uni.showToast({
 		title:title,
 		title:title,
-		icon:'none'
+		icon:'none',
+		duration: 4000
 	})
 	})
 }
 }
 
 

+ 156 - 7
manifest.json

@@ -2,8 +2,8 @@
     "name" : "iSCM智慧供应链",
     "name" : "iSCM智慧供应链",
     "appid" : "__UNI__5B57B68",
     "appid" : "__UNI__5B57B68",
     "description" : "iSCM智慧供应链系统",
     "description" : "iSCM智慧供应链系统",
-    "versionName" : "1.1.5",
-    "versionCode" : 115,
+    "versionName" : "1.1.8",
+    "versionCode" : 118,
     "transformPx" : false,
     "transformPx" : false,
     /* 5+App特有相关 */
     /* 5+App特有相关 */
     "app-plus" : {
     "app-plus" : {
@@ -28,12 +28,12 @@
             "template" : {
             "template" : {
                 //prompt取值为template时有效,用于配置模板提示框上显示的内容  
                 //prompt取值为template时有效,用于配置模板提示框上显示的内容  
                 "title" : "服务协议和隐私政策",
                 "title" : "服务协议和隐私政策",
-                "message" : "为了更好地保障您的个人利益,我们根据相关法规制定了<a href=\"http://static.chelingzhu.com/app/zycgjYsxy.html\">《章鱼车管家隐私保护政策》</a>,请您在点击同意之前仔细阅读并充分理解相关条款。<br/>1. 为了给您提供账号登录、 消息通知等相关基本服务, 我们会根据实际需要收集必要的用户信息; <br/>2. 基于您的授权, 我们会根据不同的功能获取您不同的权限, 涉及位置、 相机、 相册等权限。 您有权拒绝或取消授权; <br/>3. 未经您同意, 我们不会从第三方处获取或向其提供您的信息; <br/>4. 我们会采取业界先进的安全措施保护您的信息安全; <br/>5. 当您点击“ 同意” 时, 视为您已阅读和愿意接受《 章鱼车管家隐私保护政策》的所有内容。 当您点击“ 不同意” 时, 我们将无法为您提供相关产品和服务, 请停止使用并退出本应用。",
+                "message" : "为了更好地保障您的个人利益,我们根据相关法规制定了<a href=\"http://www.zyucgj.com/h-nd-324.html\">《iSCM智慧供应链隐私保护政策》</a>,请您在点击同意之前仔细阅读并充分理解相关条款。<br/>1. 为了给您提供账号登录、 消息通知等相关基本服务, 我们会根据实际需要收集必要的用户信息; <br/>2. 基于您的授权, 我们会根据不同的功能获取您不同的权限, 涉及蓝牙、位置、 相机、 相册等权限。 您有权拒绝或取消授权; <br/>3. 未经您同意, 我们不会从第三方处获取或向其提供您的信息; <br/>4. 我们会采取业界先进的安全措施保护您的信息安全; <br/>5. 当您点击“ 同意” 时, 视为您已阅读和愿意接受《 iSCM智慧供应链隐私保护政策》的所有内容。 当您点击“ 不同意” 时, 我们将无法为您提供相关产品和服务, 请停止使用并退出本应用。",
                 "buttonAccept" : "同意并接受",
                 "buttonAccept" : "同意并接受",
                 "buttonRefuse" : "暂不同意",
                 "buttonRefuse" : "暂不同意",
                 "second" : {
                 "second" : {
                     "title" : "确认提示",
                     "title" : "确认提示",
-                    "message" : "进入应用前,你需先同意<a href=\"http://static.chelingzhu.com/app/zycgjYsxy.html\">《章鱼车管家隐私保护政策》</a>,否则将退出应用。",
+                    "message" : "进入应用前,你需先同意<a href=\"http://www.zyucgj.com/h-nd-324.html\">《iSCM智慧供应链隐私保护政策》</a>,否则将退出应用。",
                     "buttonAccept" : "同意并继续",
                     "buttonAccept" : "同意并继续",
                     "buttonRefuse" : "退出应用"
                     "buttonRefuse" : "退出应用"
                 }
                 }
@@ -73,25 +73,48 @@
                     "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
                     "<uses-permission android:name=\"android.permission.CHANGE_WIFI_STATE\"/>",
                     "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
                     "<uses-permission android:name=\"android.permission.FLASHLIGHT\"/>",
                     "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
                     "<uses-permission android:name=\"android.permission.GET_ACCOUNTS\"/>",
+                    "<uses-permission android:name=\"android.permission.INTERNET\"/>",
                     "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
                     "<uses-permission android:name=\"android.permission.MODIFY_AUDIO_SETTINGS\"/>",
                     "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
                     "<uses-permission android:name=\"android.permission.MOUNT_UNMOUNT_FILESYSTEMS\"/>",
+                    "<uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\"/>",
                     "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
                     "<uses-permission android:name=\"android.permission.READ_LOGS\"/>",
                     "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
                     "<uses-permission android:name=\"android.permission.READ_PHONE_STATE\"/>",
                     "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
                     "<uses-permission android:name=\"android.permission.RECORD_AUDIO\"/>",
                     "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
                     "<uses-permission android:name=\"android.permission.VIBRATE\"/>",
                     "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
                     "<uses-permission android:name=\"android.permission.WAKE_LOCK\"/>",
                     "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
                     "<uses-permission android:name=\"android.permission.WRITE_CONTACTS\"/>",
+                    "<uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\"/>",
                     "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
                     "<uses-permission android:name=\"android.permission.WRITE_SETTINGS\"/>"
-                ]
+                ],
+                "abiFilters" : [ "armeabi-v7a", "arm64-v8a" ]
             },
             },
             /* ios打包配置 */
             /* ios打包配置 */
             "ios" : {
             "ios" : {
                 "idfa" : false,
                 "idfa" : false,
-                "dSYMs" : false
+                "dSYMs" : false,
+                "UIBackgroundModes" : "audio,bluetooth-central,remote-notification",
+                "privacyDescription" : {
+                    //可选,JSON对象,iOS隐私信息访问的许可描述
+                    "NSPhotoLibraryUsageDescription" : "扫描识别产品需要访问设备相册,是否同意?", //可选,字符串类型,系统相册读取权限描述
+                    "NSPhotoLibraryAddUsageDescription" : "扫描识别产品需要访问设备相册,是否同意?", //可选,字符串类型,系统相册写入权限描述
+                    "NSCameraUsageDescription" : "扫描识别产品二维码需要访问相机,是否同意?", //可选,字符串类型,摄像头使用权限描述
+                    "NSLocationWhenInUseUsageDescription" : "连接打印机需要开启位置权限,是否同意?", //可选,字符串类型,运行期访问位置权限描述
+                    "NSBluetoothPeripheralUsageDescription" : "连接打印机需要开启蓝牙权限,是否同意?", //可选,字符串类型,使用蓝牙权限描述
+                    "NSBluetoothAlwaysUsageDescription" : "连接打印机需要开启蓝牙权限,是否同意?" //可选,字符串类型,后台使用蓝牙权限描述
+                }
             },
             },
             /* SDK配置 */
             /* SDK配置 */
             "sdkConfigs" : {
             "sdkConfigs" : {
-                "ad" : {}
+                "ad" : {},
+                "speech" : {},
+                "geolocation" : {
+                    "system" : {
+                        "__platform__" : [ "ios", "android" ]
+                    }
+                },
+                "push" : {
+                    "unipush" : null
+                }
             },
             },
             "icons" : {
             "icons" : {
                 "android" : {
                 "android" : {
@@ -148,6 +171,132 @@
                     "pid" : "2683",
                     "pid" : "2683",
                     "parameters" : {}
                     "parameters" : {}
                 }
                 }
+            },
+            "JG-JCore" : {
+                "JPUSH_APPKEY_IOS" : "a8ad1620a88ff2493a2f8fda",
+                "JPUSH_CHANNEL_IOS" : "developer-default",
+                "JPUSH_APPKEY_ANDROID" : "a8ad1620a88ff2493a2f8fda",
+                "JPUSH_CHANNEL_ANDROID" : "developer-default",
+                "__plugin_info__" : {
+                    "name" : "JG-JCore",
+                    "description" : "极光推送JCore插件",
+                    "platforms" : "Android,iOS",
+                    "url" : "",
+                    "android_package_name" : "",
+                    "ios_bundle_id" : "",
+                    "isCloud" : false,
+                    "bought" : -1,
+                    "pid" : "",
+                    "parameters" : {
+                        "JPUSH_APPKEY_IOS" : {
+                            "des" : "[iOS]极光portal配置应用信息时分配的AppKey",
+                            "key" : "JCore:APP_KEY",
+                            "value" : ""
+                        },
+                        "JPUSH_CHANNEL_IOS" : {
+                            "des" : "[iOS]用于统计分发渠道,不需要可填默认值developer-default",
+                            "key" : "JCore:CHANNEL",
+                            "value" : ""
+                        },
+                        "JPUSH_APPKEY_ANDROID" : {
+                            "des" : "[Android]极光portal配置应用信息时分配的AppKey",
+                            "key" : "JPUSH_APPKEY",
+                            "value" : ""
+                        },
+                        "JPUSH_CHANNEL_ANDROID" : {
+                            "des" : "[Android]用于统计分发渠道,不需要可填默认值developer-default",
+                            "key" : "JPUSH_CHANNEL",
+                            "value" : ""
+                        }
+                    }
+                }
+            },
+            "JG-JPush" : {
+                "JPUSH_ISPRODUCTION_IOS" : "",
+                "JPUSH_ADVERTISINGID_IOS" : "",
+                "JPUSH_DEFAULTINITJPUSH_IOS" : "true",
+                "JPUSH_OPPO_APPKEY" : "",
+                "JPUSH_OPPO_APPID" : "",
+                "JPUSH_OPPO_APPSECRET" : "",
+                "JPUSH_VIVO_APPKEY" : "",
+                "JPUSH_VIVO_APPID" : "",
+                "JPUSH_MEIZU_APPKEY" : "",
+                "JPUSH_MEIZU_APPID" : "",
+                "JPUSH_XIAOMI_APPKEY" : "",
+                "JPUSH_XIAOMI_APPID" : "",
+                "__plugin_info__" : {
+                    "name" : "JG-JPush",
+                    "description" : "极光推送Hbuilder插件",
+                    "platforms" : "Android,iOS",
+                    "url" : "",
+                    "android_package_name" : "",
+                    "ios_bundle_id" : "",
+                    "isCloud" : false,
+                    "bought" : -1,
+                    "pid" : "",
+                    "parameters" : {
+                        "JPUSH_ISPRODUCTION_IOS" : {
+                            "des" : "[iOS]是否是生产环境,是填true,不是填false或者不填",
+                            "key" : "JPush:ISPRODUCTION",
+                            "value" : ""
+                        },
+                        "JPUSH_ADVERTISINGID_IOS" : {
+                            "des" : "[iOS]广告标识符(IDFA)如果不需要使用IDFA,可不填",
+                            "key" : "JPush:ADVERTISINGID",
+                            "value" : ""
+                        },
+                        "JPUSH_DEFAULTINITJPUSH_IOS" : {
+                            "des" : "[iOS]是否默认初始化,是填true,不是填false或者不填",
+                            "key" : "JPush:DEFAULTINITJPUSH",
+                            "value" : ""
+                        },
+                        "JPUSH_OPPO_APPKEY" : {
+                            "des" : "厂商OPPO-appkey,示例:OP-12345678",
+                            "key" : "OPPO_APPKEY",
+                            "value" : ""
+                        },
+                        "JPUSH_OPPO_APPID" : {
+                            "des" : "厂商OPPO-appId,示例:OP-12345678",
+                            "key" : "OPPO_APPID",
+                            "value" : ""
+                        },
+                        "JPUSH_OPPO_APPSECRET" : {
+                            "des" : "厂商OPPO-appSecret,示例:OP-12345678",
+                            "key" : "OPPO_APPSECRET",
+                            "value" : ""
+                        },
+                        "JPUSH_VIVO_APPKEY" : {
+                            "des" : "厂商VIVO-appkey,示例:12345678",
+                            "key" : "com.vivo.push.api_key",
+                            "value" : ""
+                        },
+                        "JPUSH_VIVO_APPID" : {
+                            "des" : "厂商VIVO-appId,示例:12345678",
+                            "key" : "com.vivo.push.app_id",
+                            "value" : ""
+                        },
+                        "JPUSH_MEIZU_APPKEY" : {
+                            "des" : "厂商MEIZU-appKey,示例:MZ-12345678",
+                            "key" : "MEIZU_APPKEY",
+                            "value" : ""
+                        },
+                        "JPUSH_MEIZU_APPID" : {
+                            "des" : "厂商MEIZU-appId,示例:MZ-12345678",
+                            "key" : "MEIZU_APPID",
+                            "value" : ""
+                        },
+                        "JPUSH_XIAOMI_APPKEY" : {
+                            "des" : "厂商XIAOMI-appKey,示例:MI-12345678",
+                            "key" : "XIAOMI_APPKEY",
+                            "value" : ""
+                        },
+                        "JPUSH_XIAOMI_APPID" : {
+                            "des" : "厂商XIAOMI-appId,示例:MI-12345678",
+                            "key" : "XIAOMI_APPID",
+                            "value" : ""
+                        }
+                    }
+                }
             }
             }
         }
         }
     },
     },

BIN
nativePlugins/JG-JCore/android/libs/arm64-v8a/libjcore332.so


BIN
nativePlugins/JG-JCore/android/libs/armeabi-v7a/libjcore332.so


BIN
nativePlugins/JG-JCore/android/libs/armeabi/libjcore332.so


BIN
nativePlugins/JG-JCore/android/libs/jcore-android-3.3.2.jar


BIN
nativePlugins/JG-JCore/android/libs/mips/libjcore332.so


BIN
nativePlugins/JG-JCore/android/libs/mips64/libjcore332.so


BIN
nativePlugins/JG-JCore/android/libs/x86/libjcore332.so


BIN
nativePlugins/JG-JCore/android/libs/x86_64/libjcore332.so


BIN
nativePlugins/JG-JCore/android/uniplugin_jcore-release.aar


+ 27 - 0
nativePlugins/JG-JCore/ios/JGInforCollectionAuth.h

@@ -0,0 +1,27 @@
+//
+//  JGInforCollectionAuth.h
+//  JCore
+//
+//  Created by 豆瓣 on 2021/10/27.
+//  Copyright © 2021 jiguang. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+NS_ASSUME_NONNULL_BEGIN
+
+/// 合规接口,是否授权极光采集一定的设备信息
+@interface JGInforCollectionAuthItems : NSObject
+/// 是否授权,默认YES
+@property(nonatomic,assign)BOOL isAuth;
+@end
+
+@interface JGInforCollectionAuth : NSObject
+
+/// 设备信息采集授权接口(合规接口)
+/// 请务必在调用初始化、功能性接口前调用此接口进行合规授权
+/// @param authBlock auth:YES 则极光认为您同意极光采集一定的设备信息
++(void)JCollectionAuth:(void(^_Nullable)(JGInforCollectionAuthItems *authInfo))authBlock;
+@end
+
+NS_ASSUME_NONNULL_END

+ 17 - 0
nativePlugins/JG-JCore/ios/UniPluginJCore.framework/Headers/JCoreModule.h

@@ -0,0 +1,17 @@
+//
+//  JCoreModule.h
+//  UniPluginJCore
+//
+//  Created by huangshuni on 2021/1/21.
+//
+
+#import <Foundation/Foundation.h>
+#import "DCUniModule.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface JCoreModule : DCUniModule
+
+@end
+
+NS_ASSUME_NONNULL_END

BIN
nativePlugins/JG-JCore/ios/UniPluginJCore.framework/Info.plist


BIN
nativePlugins/JG-JCore/ios/UniPluginJCore.framework/UniPluginJCore


BIN
nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeDirectory


BIN
nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeRequirements


BIN
nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeRequirements-1


+ 117 - 0
nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeResources

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>files</key>
+	<dict>
+		<key>Headers/JCoreModule.h</key>
+		<data>
+		4aMcBALZuuQeh2JQjJqqvSkc2mA=
+		</data>
+		<key>Info.plist</key>
+		<data>
+		3s06cvirbbkxK+4muJ/0lHidXV8=
+		</data>
+	</dict>
+	<key>files2</key>
+	<dict>
+		<key>Headers/JCoreModule.h</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			4aMcBALZuuQeh2JQjJqqvSkc2mA=
+			</data>
+			<key>hash2</key>
+			<data>
+			h/0w2CaU3JBhKI3Pp4EiSWqLf/ZY1Ju+5+tBAdowZ5k=
+			</data>
+		</dict>
+	</dict>
+	<key>rules</key>
+	<dict>
+		<key>^.*</key>
+		<true/>
+		<key>^.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^version.plist$</key>
+		<true/>
+	</dict>
+	<key>rules2</key>
+	<dict>
+		<key>.*\.dSYM($|/)</key>
+		<dict>
+			<key>weight</key>
+			<real>11</real>
+		</dict>
+		<key>^(.*/)?\.DS_Store$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>2000</real>
+		</dict>
+		<key>^.*</key>
+		<true/>
+		<key>^.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^Info\.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^PkgInfo$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^embedded\.provisionprofile$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^version\.plist$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+	</dict>
+</dict>
+</plist>

BIN
nativePlugins/JG-JCore/ios/UniPluginJCore.framework/_CodeSignature/CodeSignature


BIN
nativePlugins/JG-JCore/ios/jcore-ios-3.2.5.a


+ 58 - 0
nativePlugins/JG-JCore/package.json

@@ -0,0 +1,58 @@
+{
+    "name": "JG-JCore",
+    "id": "JG-JCore",
+    "version": "1.0.5",
+    "description": "极光推送JCore插件",
+    "_dp_type":"nativeplugin",
+    "_dp_nativeplugin":{
+        "ios": {
+            "plugins": [
+                {
+                    "type": "module",
+                    "name": "JG-JCore",
+                    "class": "JCoreModule"
+                }
+            ],
+            "integrateType": "framework",
+            "deploymentTarget": "9.0",
+            "parameters": {
+                "JPUSH_APPKEY_IOS": {
+                    "des": "[iOS]极光portal配置应用信息时分配的AppKey",
+                    "key": "JCore:APP_KEY"
+                },
+                "JPUSH_CHANNEL_IOS": {
+                    "des": "[iOS]用于统计分发渠道,不需要可填默认值developer-default",
+                    "key": "JCore:CHANNEL"
+                }
+            }
+        },
+        "android": {
+            "plugins": [
+                {
+                    "type": "module",
+                    "name": "JG-JCore",
+                    "class": "cn.jiguang.uniplugin_jcore.JCoreModule"
+                }
+            ],
+            "integrateType": "aar",
+            "minSdkVersion": "19",
+            "permissions": [
+            ],
+            "abis": [
+                "armeabi-v7a",
+                "arm64-v8a",
+                "x86"
+            ],
+            "parameters": {
+                "JPUSH_APPKEY_ANDROID": {
+                    "des": "[Android]极光portal配置应用信息时分配的AppKey",
+                    "key": "JPUSH_APPKEY"
+                },
+                "JPUSH_CHANNEL_ANDROID":{
+                    "des": "[Android]用于统计分发渠道,不需要可填默认值developer-default",
+                    "key": "JPUSH_CHANNEL"
+                }
+            }
+        }
+    }
+}

BIN
nativePlugins/JG-JPush/android/com.heytap.msp-push-2.1.0.aar


BIN
nativePlugins/JG-JPush/android/libs/MiPush_SDK_Client_3_8_5.jar


BIN
nativePlugins/JG-JPush/android/libs/jpush-android-3.9.1.jar


BIN
nativePlugins/JG-JPush/android/libs/jpush-android-plugin-meizu-v3.9.1.jar


BIN
nativePlugins/JG-JPush/android/libs/jpush-android-plugin-oppo-v3.9.1.jar


BIN
nativePlugins/JG-JPush/android/libs/jpush-android-plugin-vivo-v3.9.1.jar


BIN
nativePlugins/JG-JPush/android/libs/jpush-android-plugin-xiaomi-v3.9.1.jar


BIN
nativePlugins/JG-JPush/android/libs/meizu-push-4.0.2.jar


BIN
nativePlugins/JG-JPush/android/libs/push_sdk_v3.0.0.jar


BIN
nativePlugins/JG-JPush/android/uniplugin_jpush-release.aar


+ 838 - 0
nativePlugins/JG-JPush/ios/JPUSHService.h

@@ -0,0 +1,838 @@
+/*
+ *	| |    | |  \ \  / /  | |    | |   / _______|
+ *	| |____| |   \ \/ /   | |____| |  / /
+ *	| |____| |    \  /    | |____| |  | |   _____
+ * 	| |    | |    /  \    | |    | |  | |  |____ |
+ *  | |    | |   / /\ \   | |    | |  \ \______| |
+ *  | |    | |  /_/  \_\  | |    | |   \_________|
+ *
+ * Copyright (c) 2011 ~ 2017 Shenzhen HXHG. All rights reserved.
+ */
+
+#define JPUSH_VERSION_NUMBER 4.8.1
+
+#import <Foundation/Foundation.h>
+
+@class CLRegion;
+@class UILocalNotification;
+@class CLLocation;
+@class UNNotificationCategory;
+@class UNNotificationSettings;
+@class UNNotificationRequest;
+@class UNNotification;
+@class UIView;
+@protocol JPUSHRegisterDelegate;
+@protocol JPUSHGeofenceDelegate;
+@protocol JPUSHNotiInMessageDelegate;
+
+typedef void (^JPUSHTagsOperationCompletion)(NSInteger iResCode, NSSet *iTags, NSInteger seq);
+typedef void (^JPUSHTagValidOperationCompletion)(NSInteger iResCode, NSSet *iTags, NSInteger seq, BOOL isBind);
+typedef void (^JPUSHAliasOperationCompletion)(NSInteger iResCode, NSString *iAlias, NSInteger seq);
+typedef void (^JPUSHPropertiesOperationCompletion)(NSInteger iResCode, NSDictionary *properties, NSInteger seq);
+
+extern NSString *const kJPFNetworkIsConnectingNotification; // 正在连接中
+extern NSString *const kJPFNetworkDidSetupNotification;     // 建立连接
+extern NSString *const kJPFNetworkDidCloseNotification;     // 关闭连接
+extern NSString *const kJPFNetworkDidRegisterNotification;  // 注册成功
+extern NSString *const kJPFNetworkFailedRegisterNotification; //注册失败
+extern NSString *const kJPFNetworkDidLoginNotification;     // 登录成功
+extern NSString *const kJPFNetworkDidReceiveMessageNotification;         // 收到消息(非APNS)
+extern NSString *const kJPFServiceErrorNotification;  // 错误提示
+
+typedef NS_OPTIONS(NSUInteger, JPAuthorizationOptions) {
+    JPAuthorizationOptionNone    = 0,   // the application may not present any UI upon a notification being received
+    JPAuthorizationOptionBadge   = (1 << 0),    // the application may badge its icon upon a notification being received
+    JPAuthorizationOptionSound   = (1 << 1),    // the application may play a sound upon a notification being received
+    JPAuthorizationOptionAlert   = (1 << 2),    // the application may display an alert upon a notification being received
+    JPAuthorizationOptionCarPlay = (1 << 3),    // The ability to display notifications in a CarPlay environment.
+    JPAuthorizationOptionCriticalAlert NS_AVAILABLE_IOS(12.0) = (1 << 4) ,   //The ability to play sounds for critical alerts.
+    JPAuthorizationOptionProvidesAppNotificationSettings NS_AVAILABLE_IOS(12.0) = (1 << 5) ,      //An option indicating the system should display a button for in-app notification settings.
+    JPAuthorizationOptionProvisional NS_AVAILABLE_IOS(12.0) = (1 << 6) ,     //The ability to post noninterrupting notifications provisionally to the Notification Center.
+    JPAuthorizationOptionAnnouncement NS_AVAILABLE_IOS(13.0) = (1 << 7) , //The ability for Siri to automatically read out messages over AirPods.
+};
+
+typedef NS_ENUM(NSUInteger, JPAuthorizationStatus) {
+    JPAuthorizationNotDetermined    = 0,   // The user has not yet made a choice regarding whether the application may post user notifications.
+    JPAuthorizationStatusDenied,    // The application is not authorized to post user notifications.
+    JPAuthorizationStatusAuthorized,    // The application is authorized to post user notifications.
+    JPAuthorizationStatusProvisional NS_AVAILABLE_IOS(12.0),    // The application is authorized to post non-interruptive user notifications.
+};
+
+/*!
+ * 通知注册实体类
+ */
+@interface JPUSHRegisterEntity : NSObject
+
+/*!
+ * 支持的类型
+ * badge,sound,alert
+ */
+@property (nonatomic, assign) NSInteger types;
+/*!
+ * 注入的类别
+ * iOS10 UNNotificationCategory
+ * iOS8-iOS9 UIUserNotificationCategory
+ */
+@property (nonatomic, strong) NSSet *categories;
+@end
+
+/*!
+ * 进行删除、查找推送实体类
+ */
+@interface JPushNotificationIdentifier : NSObject<NSCopying, NSCoding>
+
+@property (nonatomic, copy) NSArray<NSString *> *identifiers; // 推送的标识数组
+@property (nonatomic, copy) UILocalNotification *notificationObj NS_DEPRECATED_IOS(4_0, 10_0);  // iOS10以下可以传UILocalNotification对象数据,iOS10以上无效
+@property (nonatomic, assign) BOOL delivered NS_AVAILABLE_IOS(10_0); // 在通知中心显示的或待推送的标志,默认为NO,YES表示在通知中心显示的,NO表示待推送的
+@property (nonatomic, copy) void (^findCompletionHandler)(NSArray *results); // 用于查询回调,调用[findNotification:]方法前必须设置,results为返回相应对象数组,iOS10以下返回UILocalNotification对象数组;iOS10以上根据delivered传入值返回UNNotification或UNNotificationRequest对象数组(delivered传入YES,则返回UNNotification对象数组,否则返回UNNotificationRequest对象数组)
+
+@end
+
+/*!
+ * 推送通知声音实体类
+ * iOS10以上有效
+ */
+@interface JPushNotificationSound : NSObject <NSCopying, NSCoding>
+@property (nonatomic, copy) NSString *soundName; //普通通知铃声
+@property (nonatomic, copy) NSString *criticalSoundName NS_AVAILABLE_IOS(12.0); //警告通知铃声
+@property (nonatomic, assign) float criticalSoundVolume NS_AVAILABLE_IOS(12.0); //警告通知铃声音量,有效值在0~1之间,默认为1
+@end
+
+
+/*!
+ * 推送内容实体类
+ */
+@interface JPushNotificationContent : NSObject<NSCopying, NSCoding>
+
+@property (nonatomic, copy) NSString *title;                // 推送标题
+@property (nonatomic, copy) NSString *subtitle;             // 推送副标题
+@property (nonatomic, copy) NSString *body;                 // 推送内容
+@property (nonatomic, copy) NSNumber *badge;                // 角标的数字。如果不需要改变角标传@(-1)
+@property (nonatomic, copy) NSString *action NS_DEPRECATED_IOS(8_0, 10_0); // 弹框的按钮显示的内容(IOS 8默认为"打开", 其他默认为"启动",iOS10以上无效)
+@property (nonatomic, copy) NSString *categoryIdentifier;   // 行为分类标识
+@property (nonatomic, copy) NSDictionary *userInfo;         // 本地推送时可以设置userInfo来增加附加信息,远程推送时设置的payload推送内容作为此userInfo
+@property (nonatomic, copy) NSString *sound;                // 声音名称,不设置则为默认声音
+@property (nonatomic, copy) JPushNotificationSound *soundSetting NS_AVAILABLE_IOS(10.0);   //推送声音实体
+@property (nonatomic, copy) NSArray *attachments NS_AVAILABLE_IOS(10_0);                 // 附件,iOS10以上有效,需要传入UNNotificationAttachment对象数组类型
+@property (nonatomic, copy) NSString *threadIdentifier NS_AVAILABLE_IOS(10_0); // 线程或与推送请求相关对话的标识,iOS10以上有效,可用来对推送进行分组
+@property (nonatomic, copy) NSString *launchImageName NS_AVAILABLE_IOS(10_0);  // 启动图片名,iOS10以上有效,从推送启动时将会用到
+@property (nonatomic, copy) NSString *summaryArgument NS_AVAILABLE_IOS(12.0);  //插入到通知摘要中的部分参数。iOS12以上有效。
+@property (nonatomic, assign) NSUInteger summaryArgumentCount NS_AVAILABLE_IOS(12.0); //插入到通知摘要中的项目数。iOS12以上有效。
+@property (nonatomic, copy) NSString *targetContentIdentifier NS_AVAILABLE_IOS(13.0);  // An identifier for the content of the notification used by the system to customize the scene to be activated when tapping on a notification.
+//iOS15以上的新增属性 interruptionLevel为枚举UNNotificationInterruptionLevel
+// The interruption level determines the degree of interruption associated with the notification
+@property (nonatomic, assign) NSUInteger interruptionLevel NS_AVAILABLE_IOS(15.0);
+// Relevance score determines the sorting for the notification across app notifications. The expected range is between 0.0f and 1.0f.
+@property (nonatomic, assign) double relevanceScore NS_AVAILABLE_IOS(15.0);
+
+@end
+
+
+/*!
+ * 推送触发方式实体类
+ * 注:dateComponents、timeInterval、region在iOS10以上可选择其中一个参数传入有效值,如果同时传入值会根据优先级I、II、III使其中一种触发方式生效,fireDate为iOS10以下根据时间触发时须传入的参数
+ */
+@interface JPushNotificationTrigger : NSObject<NSCopying, NSCoding>
+
+@property (nonatomic, assign) BOOL repeat;                  // 设置是否重复,默认为NO
+@property (nonatomic, copy) NSDate *fireDate NS_DEPRECATED_IOS(2_0, 10_0);           // 用来设置触发推送的时间,iOS10以上无效
+@property (nonatomic, copy) CLRegion *region NS_AVAILABLE_IOS(8_0);                  // 用来设置触发推送的位置,iOS8以上有效,iOS10以上优先级为I,应用需要有允许使用定位的授权
+@property (nonatomic, copy) NSDateComponents *dateComponents NS_AVAILABLE_IOS(10_0); // 用来设置触发推送的日期时间,iOS10以上有效,优先级为II
+@property (nonatomic, assign) NSTimeInterval timeInterval NS_AVAILABLE_IOS(10_0);    // 用来设置触发推送的时间,iOS10以上有效,优先级为III
+
+@end
+
+/*!
+ * 注册或更新推送实体类
+ */
+@interface JPushNotificationRequest : NSObject<NSCopying, NSCoding>
+
+@property (nonatomic, copy) NSString *requestIdentifier;    // 推送请求标识
+@property (nonatomic, copy) JPushNotificationContent *content; // 设置推送的具体内容
+@property (nonatomic, copy) JPushNotificationTrigger *trigger; // 设置推送的触发方式
+@property (nonatomic, copy) void (^completionHandler)(id result); // 注册或更新推送成功回调,iOS10以上成功则result为UNNotificationRequest对象,失败则result为nil;iOS10以下成功result为UILocalNotification对象,失败则result为nil
+
+@end
+
+/*!
+ * JPush 核心头文件
+ */
+@interface JPUSHService : NSObject
+
+
+///----------------------------------------------------
+/// @name Setup 启动相关
+///----------------------------------------------------
+
+
+/*!
+ * @abstract 启动SDK
+ *
+ * @param launchingOption 启动参数.
+ * @param appKey 一个JPush 应用必须的,唯一的标识. 请参考 JPush 相关说明文档来获取这个标识.
+ * @param channel 发布渠道. 可选.
+ * @param isProduction 是否生产环境. 如果为开发状态,设置为 NO; 如果为生产状态,应改为 YES.
+ *                     App 证书环境取决于profile provision的配置,此处建议与证书环境保持一致.
+ *
+ * @discussion 提供SDK启动必须的参数, 来启动 SDK.
+ * 此接口必须在 App 启动时调用, 否则 JPush SDK 将无法正常工作.
+ */
++ (void)setupWithOption:(NSDictionary *)launchingOption
+                 appKey:(NSString *)appKey
+                channel:(NSString *)channel
+       apsForProduction:(BOOL)isProduction;
+
+/*!
+ * @abstract 启动SDK
+ *
+ * @param launchingOption 启动参数.
+ * @param appKey 一个JPush 应用必须的,唯一的标识. 请参考 JPush 相关说明文档来获取这个标识.
+ * @param channel 发布渠道. 可选.
+ * @param isProduction 是否生产环境. 如果为开发状态,设置为 NO; 如果为生产状态,应改为 YES.
+ *                     App 证书环境取决于profile provision的配置,此处建议与证书环境保持一致.
+ * @param advertisingId 广告标识符(IDFA) 如果不需要使用IDFA,传nil.
+ *
+ * @discussion 提供SDK启动必须的参数, 来启动 SDK.
+ * 此接口必须在 App 启动时调用, 否则 JPush SDK 将无法正常工作.
+ */
++ (void)setupWithOption:(NSDictionary *)launchingOption
+                 appKey:(NSString *)appKey
+                channel:(NSString *)channel
+       apsForProduction:(BOOL)isProduction
+  advertisingIdentifier:(NSString *)advertisingId;
+
+
+///----------------------------------------------------
+/// @name APNs about 通知相关
+///----------------------------------------------------
+
+/*!
+ * @abstract 注册要处理的远程通知类型
+ *
+ * @param types 通知类型
+ * @param categories 类别组
+ *
+ */
++ (void)registerForRemoteNotificationTypes:(NSUInteger)types
+                                categories:(NSSet *)categories;
+/*!
+ * @abstract 新版本的注册方法(兼容iOS10)
+ *
+ * @param config 注册通知配置
+ * @param delegate 代理
+ *
+ */
++ (void)registerForRemoteNotificationConfig:(JPUSHRegisterEntity *)config delegate:(id<JPUSHRegisterDelegate>)delegate;
+
+
++ (void)registerDeviceToken:(NSData *)deviceToken;
+
+/*!
+ * @abstract 处理收到的 APNs 消息
+ */
++ (void)handleRemoteNotification:(NSDictionary *)remoteInfo;
+
+/*!
+ * @abstract  向极光服务器提交Token
+ *
+ * @param voipToken 推送使用的Voip Token
+ */
++ (void)registerVoipToken:(NSData *)voipToken;
+
+
+/*!
+ * @abstract  处理收到的 Voip 消息
+ *
+ * @param remoteInfo 下发的 Voip 内容
+ */
++ (void)handleVoipNotification:(NSDictionary *)remoteInfo;
+
+
+/*!
+* @abstract 检测通知授权状态
+* @param completion 授权结果通过status值返回,详见JPAuthorizationStatus
+*/
++ (void)requestNotificationAuthorization:(void (^)(JPAuthorizationStatus status))completion;
+
+/*!
+* @abstract 跳转至系统设置页面,iOS8及以上有效
+*/
++ (void)openSettingsForNotification:(void (^)(BOOL success))completionHandler NS_AVAILABLE_IOS(8_0);
+
+/*!
+ * Tags操作接口
+ * 支持增加/覆盖/删除/清空/查询操作
+ * 详情请参考文档:https://docs.jiguang.cn/jpush/client/iOS/ios_api/)
+ */
+
+/**
+ 增加tags
+
+ @param tags 需要增加的tags集合
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)addTags:(NSSet<NSString *> *)tags
+     completion:(JPUSHTagsOperationCompletion)completion
+            seq:(NSInteger)seq;
+
+/**
+ 覆盖tags
+ 调用该接口会覆盖用户所有的tags
+
+ @param tags 需要设置的tags集合
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)setTags:(NSSet<NSString *> *)tags
+     completion:(JPUSHTagsOperationCompletion)completion
+            seq:(NSInteger)seq;
+
+/**
+ 删除指定tags
+
+ @param tags 需要删除的tags集合
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)deleteTags:(NSSet<NSString *> *)tags
+        completion:(JPUSHTagsOperationCompletion)completion
+               seq:(NSInteger)seq;
+
+/**
+ 清空所有tags
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)cleanTags:(JPUSHTagsOperationCompletion)completion
+              seq:(NSInteger)seq;
+
+/**
+ 查询全部tags
+
+ @param completion 响应回调,请在回调中获取查询结果
+ @param seq 请求序列号
+ */
++ (void)getAllTags:(JPUSHTagsOperationCompletion)completion
+               seq:(NSInteger)seq;
+
+/**
+ 验证tag是否绑定
+ 
+ @param completion 响应回调,回调中查看是否绑定
+ @param seq 请求序列号
+ */
++ (void)validTag:(NSString *)tag
+      completion:(JPUSHTagValidOperationCompletion)completion
+             seq:(NSInteger)seq;
+
+/**
+ 设置Alias
+
+ @param alias 需要设置的alias
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)setAlias:(NSString *)alias
+      completion:(JPUSHAliasOperationCompletion)completion
+             seq:(NSInteger)seq;
+
+/**
+ 删除alias
+
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)deleteAlias:(JPUSHAliasOperationCompletion)completion
+                seq:(NSInteger)seq;
+
+/**
+ 查询当前alias
+
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)getAlias:(JPUSHAliasOperationCompletion)completion
+             seq:(NSInteger)seq;
+
+
+/*!
+ * @abstract 过滤掉无效的 tags
+ *
+ * @discussion 如果 tags 数量超过限制数量, 则返回靠前的有效的 tags.
+ * 建议设置 tags 前用此接口校验. SDK 内部也会基于此接口来做过滤.
+ */
++ (NSSet *)filterValidTags:(NSSet *)tags;
+
+
+/*!
+ * Property操作接口
+ * 支持增加/删除/清空操作
+ * 详情请参考文档:https://docs.jiguang.cn/jpush/client/iOS/ios_api/)
+ */
+
+/**
+ 新增/更新用户属性
+ 
+ 如果某个用户属性之前已经存在了,则会更新;不存在,则会新增
+ 
+ @param properties  需要新增或者更新的的用户属性内容,类型为NSDictionary;
+                   Key 为用户属性名称,类型必须是 NSString 类型;Value为用户属性值,只支持 NSString、NSNumber、NSDate类型,如果属性为BOOL类型,传值时请转成NSNumber类型
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)setProperties:(NSDictionary *)properties
+           completion:(JPUSHPropertiesOperationCompletion)completion
+                  seq:(NSInteger)seq;
+
+
+/**
+ 删除指定属性
+
+ @param keys 需要删除的属性名称集合
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)deleteProperties:(NSSet<NSString *> *)keys
+              completion:(JPUSHPropertiesOperationCompletion)completion
+                     seq:(NSInteger)seq;
+
+
+/**
+ 清空所有属性
+ @param completion 响应回调
+ @param seq 请求序列号
+ */
++ (void)cleanProperties:(JPUSHPropertiesOperationCompletion)completion
+                    seq:(NSInteger)seq;
+
+
+///----------------------------------------------------
+/// @name Stats 统计功能
+///----------------------------------------------------
+
+/*!
+ * @abstract 开始记录页面停留
+ *
+ * @param pageName 页面名称
+ * @discussion JCore 1.1.8 版本后,如需统计页面流,请使用 JAnalytics
+ */
++ (void)startLogPageView:(NSString *)pageName __attribute__((deprecated("JCore 1.1.8 版本已过期")));
+
+/*!
+ * @abstract 停止记录页面停留
+ *
+ * @param pageName 页面
+ * @discussion JCore 1.1.8 版本后,如需统计页面流,请使用 JAnalytics
+ */
++ (void)stopLogPageView:(NSString *)pageName __attribute__((deprecated("JCore 1.1.8 版本已过期")));
+
+/*!
+ * @abstract 直接上报在页面的停留时间
+ *
+ * @param pageName 页面
+ * @param seconds 停留的秒数
+ * @discussion JCore 1.1.8 版本后,如需统计页面流,请使用 JAnalytics
+ */
++ (void)beginLogPageView:(NSString *)pageName duration:(int)seconds __attribute__((deprecated("JCore 1.1.8 版本已过期")));
+
+/*!
+ * @abstract 开启Crash日志收集
+ *
+ * @discussion 默认是关闭状态.
+ */
++ (void)crashLogON;
+
+/*!
+ * @abstract 地理位置上报
+ *
+ * @param latitude 纬度.
+ * @param longitude 经度.
+ *
+ */
++ (void)setLatitude:(double)latitude longitude:(double)longitude;
+
+/*!
+ * @abstract 地理位置上报
+ *
+ * @param location 直接传递 CLLocation * 型的地理信息
+ *
+ * @discussion 需要链接 CoreLocation.framework 并且 #import <CoreLocation/CoreLocation.h>
+ */
++ (void)setLocation:(CLLocation *)location;
+
+/**
+ 设置地理围栏的最大个数
+ 默认值为 10 ,iOS系统默认地理围栏最大个数为20
+ @param count 个数 count
+ */
++ (void)setGeofeneceMaxCount:(NSInteger)count;
+
+/**
+ 设置地理围栏'圈内'类型的检测周期
+ 默认15分钟检测一次
+ */
++ (void)setGeofenecePeriodForInside:(NSInteger)seconds;
+
+/**
+ 注册地理围栏的代理
+
+ @param delegate 代理
+ @param launchOptions app启动完成是收到的字段参数
+ */
++ (void)registerLbsGeofenceDelegate:(id<JPUSHGeofenceDelegate>)delegate withLaunchOptions:(NSDictionary *)launchOptions;
+
+/**
+ 删除地理围栏
+ 
+ @param geofenceId 地理围栏id
+ */
++ (void)removeGeofenceWithIdentifier:(NSString *)geofenceId;
+
+///----------------------------------------------------
+/// @name Local Notification 本地通知
+///----------------------------------------------------
+/*!
+ * @abstract 注册或更新推送 (支持iOS10,并兼容iOS10以下版本)
+ *
+ * JPush 2.1.9新接口
+ * @param request JPushNotificationRequest类型,设置推送的属性,设置已有推送的request.requestIdentifier即更新已有的推送,否则为注册新推送,更新推送仅仅在iOS10以上有效,结果通过request.completionHandler返回
+ * @discussion 旧的注册本地推送接口被废弃,使用此接口可以替换
+ *
+ */
++ (void)addNotification:(JPushNotificationRequest *)request;
+
+/*!
+ * @abstract 移除推送 (支持iOS10,并兼容iOS10以下版本)
+ *
+ * JPush 2.1.9新接口
+ * @param identifier JPushNotificationIdentifier类型,iOS10以上identifier设置为nil,则移除所有在通知中心显示推送和待推送请求,也可以通过设置identifier.delivered和identifier.identifiers来移除相应在通知中心显示推送或待推送请求,identifier.identifiers如果设置为nil或空数组则移除相应标志下所有在通知中心显示推送或待推送请求;iOS10以下identifier设置为nil,则移除所有推送,identifier.delivered属性无效,另外可以通过identifier.notificationObj传入特定推送对象来移除此推送。
+ * @discussion 旧的所有删除推送接口被废弃,使用此接口可以替换
+ *
+ */
++ (void)removeNotification:(JPushNotificationIdentifier *)identifier;
+
+/*!
+ * @abstract 查找推送 (支持iOS10,并兼容iOS10以下版本)
+ *
+ * JPush 2.1.9新接口
+ * @param identifier JPushNotificationIdentifier类型,iOS10以上可以通过设置identifier.delivered和identifier.identifiers来查找相应在通知中心显示推送或待推送请求,identifier.identifiers如果设置为nil或空数组则返回相应标志下所有在通知中心显示推送或待推送请求;iOS10以下identifier.delivered属性无效,identifier.identifiers如果设置nil或空数组则返回所有未触发的推送。须要设置identifier.findCompletionHandler回调才能得到查找结果,通过(NSArray *results)返回相应对象数组。
+ * @discussion 旧的查找推送接口被废弃,使用此接口可以替换
+ *
+ */
++ (void)findNotification:(JPushNotificationIdentifier *)identifier;
+
+/*!
+ * @abstract 本地推送,最多支持64个
+ *
+ * @param fireDate 本地推送触发的时间
+ * @param alertBody 本地推送需要显示的内容
+ * @param badge 角标的数字。如果不需要改变角标传-1
+ * @param alertAction 弹框的按钮显示的内容(IOS 8默认为"打开", 其他默认为"启动")
+ * @param notificationKey 本地推送标示符
+ * @param userInfo 自定义参数,可以用来标识推送和增加附加信息
+ * @param soundName 自定义通知声音,设置为nil为默认声音
+ *
+ * @discussion 最多支持 64 个定义,此方法被[addNotification:]方法取代
+ */
++ (UILocalNotification *)setLocalNotification:(NSDate *)fireDate
+                                    alertBody:(NSString *)alertBody
+                                        badge:(int)badge
+                                  alertAction:(NSString *)alertAction
+                                identifierKey:(NSString *)notificationKey
+                                     userInfo:(NSDictionary *)userInfo
+                                    soundName:(NSString *)soundName __attribute__((deprecated("JPush 2.1.9 版本已过期")));
+
+/*!
+ * @abstract 本地推送 (支持 iOS8 新参数)
+ *
+ * IOS8新参数
+ * @param region 自定义参数
+ * @param regionTriggersOnce 自定义参数
+ * @param category 自定义参数
+ * @discussion 此方法被[addNotification:]方法取代
+ */
++ (UILocalNotification *)setLocalNotification:(NSDate *)fireDate
+                                    alertBody:(NSString *)alertBody
+                                        badge:(int)badge
+                                  alertAction:(NSString *)alertAction
+                                identifierKey:(NSString *)notificationKey
+                                     userInfo:(NSDictionary *)userInfo
+                                    soundName:(NSString *)soundName
+                                       region:(CLRegion *)region
+                           regionTriggersOnce:(BOOL)regionTriggersOnce
+                                     category:(NSString *)category NS_AVAILABLE_IOS(8_0) __attribute__((deprecated("JPush 2.1.9 版本已过期")));
+
+/*!
+ * @abstract 前台展示本地推送
+ *
+ * @param notification 本地推送对象
+ * @param notificationKey 需要前台显示的本地推送通知的标示符
+ *
+ * @discussion 默认App在前台运行时不会进行弹窗,在程序接收通知调用此接口可实现指定的推送弹窗。--iOS10以下还可继续使用,iOS10以上在[UNUserNotificationCenterDelegate willPresentNotification:withCompletionHandler:]方法中调用completionHandler(UNNotificationPresentationOptionSound | UNNotificationPresentationOptionAlert);即可
+ */
++ (void)showLocalNotificationAtFront:(UILocalNotification *)notification
+                       identifierKey:(NSString *)notificationKey __attribute__((deprecated("JPush 2.1.9 版本已过期")));
+/*!
+ * @abstract 删除本地推送定义
+ *
+ * @param notificationKey 本地推送标示符
+ * @discussion 此方法被[removeNotification:]方法取代
+ */
++ (void)deleteLocalNotificationWithIdentifierKey:(NSString *)notificationKey __attribute__((deprecated("JPush 2.1.9 版本已过期")));
+
+/*!
+ * @abstract 删除本地推送定义
+ * @discussion 此方法被[removeNotification:]方法取代
+ */
++ (void)deleteLocalNotification:(UILocalNotification *)localNotification __attribute__((deprecated("JPush 2.1.9 版本已过期")));
+
+/*!
+ * @abstract 获取指定通知
+ *
+ * @param notificationKey 本地推送标示符
+ * @return 本地推送对象数组, [array count]为0时表示没找到
+ * @discussion 此方法被[findNotification:]方法取代
+ */
++ (NSArray *)findLocalNotificationWithIdentifier:(NSString *)notificationKey __attribute__((deprecated("JPush 2.1.9 版本已过期")));
+
+/*!
+ * @abstract 清除所有本地推送对象
+ * @discussion 此方法被[removeNotification:]方法取代
+ */
++ (void)clearAllLocalNotifications __attribute__((deprecated("JPush 2.1.9 版本已过期")));
+
+
+///----------------------------------------------------
+/// @name Server badge 服务器端 badge 功能
+///----------------------------------------------------
+
+/*!
+ * @abstract 设置角标(到服务器)
+ *
+ * @param value 新的值. 会覆盖服务器上保存的值(这个用户)
+ *
+ * @discussion 本接口不会改变应用本地的角标值.
+ * 本地仍须调用 UIApplication:setApplicationIconBadgeNumber 函数来设置脚标.
+ *
+ * 本接口用于配合 JPush 提供的服务器端角标功能.
+ * 该功能解决的问题是, 服务器端推送 APNs 时, 并不知道客户端原来已经存在的角标是多少, 指定一个固定的数字不太合理.
+ *
+ * JPush 服务器端脚标功能提供:
+ *
+ * - 通过本 API 把当前客户端(当前这个用户的) 的实际 badge 设置到服务器端保存起来;
+ * - 调用服务器端 API 发 APNs 时(通常这个调用是批量针对大量用户),
+ *   使用 "+1" 的语义, 来表达需要基于目标用户实际的 badge 值(保存的) +1 来下发通知时带上新的 badge 值;
+ */
++ (BOOL)setBadge:(NSInteger)value;
+
+/*!
+ * @abstract 重置脚标(为0)
+ *
+ * @discussion 相当于 [setBadge:0] 的效果.
+ * 参考 [JPUSHService setBadge:] 说明来理解其作用.
+ */
++ (void)resetBadge;
+
+///----------------------------------------------------
+/// @name Other Feature 其他功能
+///----------------------------------------------------
+
+/*!
+ * @abstract 设置手机号码(到服务器)
+ *
+ * @param mobileNumber 手机号码. 会与用户信息一一对应。可为空,为空则清除号码
+ * @param completion 响应回调。成功则error为空,失败则error带有错误码及错误信息
+ *
+ * @discussion 设置手机号码后,可实现“推送不到短信到”的通知方式,提高推送达到率。结果信息通过completion异步返回,也可将completion设置为nil不处理结果信息。
+ *
+ */
++ (void)setMobileNumber:(NSString *)mobileNumber completion:(void (^)(NSError *error))completion;
+
+///----------------------------------------------------
+/// @name Logs and others 日志与其他
+///----------------------------------------------------
+
+/*!
+ * @abstract JPush标识此设备的 registrationID
+ *
+ * @discussion SDK注册成功后, 调用此接口获取到 registrationID 才能够获取到.
+ *
+ * JPush 支持根据 registrationID 来进行推送.
+ * 如果你需要此功能, 应该通过此接口获取到 registrationID 后, 上报到你自己的服务器端, 并保存下来.
+ * registrationIDCompletionHandler:是新增的获取registrationID的方法,需要在block中获取registrationID,resCode为返回码,模拟器调用此接口resCode返回1011,registrationID返回nil.
+ * 更多的理解请参考 JPush 的文档网站.
+ */
++ (NSString *)registrationID;
+
++ (void)registrationIDCompletionHandler:(void(^)(int resCode,NSString *registrationID))completionHandler;
+
+/*!
+ * @abstract 打开日志级别到 Debug
+ *
+ * @discussion JMessage iOS 的日志系统参考 Android 设计了级别.
+ * 从低到高是: Verbose, Debug, Info, Warning, Error.
+ * 对日志级别的进一步理解, 请参考 Android 相关的说明.
+ *
+ * SDK 默认开启的日志级别为: Info. 只显示必要的信息, 不打印调试日志.
+ *
+ * 请在SDK启动后调用本接口,调用本接口可打开日志级别为: Debug, 打印调试日志.
+ */
++ (void)setDebugMode;
+
+/*!
+ * @abstract 关闭日志
+ *
+ * @discussion 关于日志级别的说明, 参考 [JPUSHService setDebugMode]
+ *
+ * 虽说是关闭日志, 但还是会打印 Warning, Error 日志. 这二种日志级别, 在程序运行正常时, 不应有打印输出.
+ *
+ * 建议在发布的版本里, 调用此接口, 关闭掉日志打印.
+ */
++ (void)setLogOFF;
+
+/*!
+ * @abstract 设置SDK地理位置权限开关
+ *
+ * @discussion 关闭地理位置之后,SDK地理围栏的相关功能将受到影响,默认是开启。
+ *
+ */
++ (void)setLocationEanable:(BOOL)isEanble;
+
+
+/*!
+* @abstract 设置应用内提醒消息的代理
+*
+* @discussion 遵守JPushNotiInMessageDelegate的代理对象
+*
+*/
++ (void)setNotiInMessageDelegate:(id<JPUSHNotiInMessageDelegate>)notiInMessageDelegate;
+
+
+///----------------------------------------------------
+///********************下列方法已过期********************
+///**************请使用新版tag/alias操作接口**************
+///----------------------------------------------------
+/// @name Tag alias setting 设置别名与标签
+///----------------------------------------------------
+
+/*!
+ * 下面的接口是可选的
+ * 设置标签和(或)别名(若参数为nil,则忽略;若是空对象,则清空;详情请参考文档:https://docs.jiguang.cn/jpush/client/iOS/ios_api/)
+ * setTags:alias:fetchCompletionHandle:是新的设置标签别名的方法,不再需要显示声明回调函数,只需要在block里面处理设置结果即可.
+ * WARN: 使用block时需要注意循环引用问题
+ */
++ (void) setTags:(NSSet *)tags
+           alias:(NSString *)alias
+callbackSelector:(SEL)cbSelector
+          target:(id)theTarget __attribute__((deprecated("JPush 2.1.1 版本已过期")));
++ (void) setTags:(NSSet *)tags
+           alias:(NSString *)alias
+callbackSelector:(SEL)cbSelector
+          object:(id)theTarget __attribute__((deprecated("JPush 3.0.6 版本已过期")));
++ (void) setTags:(NSSet *)tags
+callbackSelector:(SEL)cbSelector
+          object:(id)theTarget __attribute__((deprecated("JPush 3.0.6 版本已过期")));
++ (void)setTags:(NSSet *)tags
+          alias:(NSString *)alias
+fetchCompletionHandle:(void (^)(int iResCode, NSSet *iTags, NSString *iAlias))completionHandler __attribute__((deprecated("JPush 3.0.6 版本已过期")));
++ (void)  setTags:(NSSet *)tags
+aliasInbackground:(NSString *)alias __attribute__((deprecated("JPush 3.0.6 版本已过期")));
++ (void)setAlias:(NSString *)alias
+callbackSelector:(SEL)cbSelector
+          object:(id)theTarget __attribute__((deprecated("JPush 3.0.6 版本已过期")));
+
+@end
+
+@class UNUserNotificationCenter;
+@class UNNotificationResponse;
+
+@protocol JPUSHRegisterDelegate <NSObject>
+
+/*
+ * @brief handle UserNotifications.framework [willPresentNotification:withCompletionHandler:]
+ * @param center [UNUserNotificationCenter currentNotificationCenter] 新特性用户通知中心
+ * @param notification 前台得到的的通知对象
+ * @param completionHandler 该callback中的options 请使用UNNotificationPresentationOptions
+ */
+- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger options))completionHandler;
+/*
+ * @brief handle UserNotifications.framework [didReceiveNotificationResponse:withCompletionHandler:]
+ * @param center [UNUserNotificationCenter currentNotificationCenter] 新特性用户通知中心
+ * @param response 通知响应对象
+ * @param completionHandler
+ */
+- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void(^)(void))completionHandler;
+
+/*
+ * @brief handle UserNotifications.framework [openSettingsForNotification:]
+ * @param center [UNUserNotificationCenter currentNotificationCenter] 新特性用户通知中心
+ * @param notification 当前管理的通知对象
+ */
+- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center openSettingsForNotification:(UNNotification *)notification NS_AVAILABLE_IOS(12.0);
+
+/**
+ * 监测通知授权状态返回的结果
+ * @param status 授权通知状态,详见JPAuthorizationStatus
+ * @param info 更多信息,预留参数
+ */
+- (void)jpushNotificationAuthorization:(JPAuthorizationStatus)status withInfo:(NSDictionary *)info;
+
+@end
+
+@protocol JPUSHGeofenceDelegate <NSObject>
+/**
+ 触发地理围栏
+ @param geofence 地理围栏触发时返回的信息
+ @param error 错误信息
+ */
+- (void)jpushGeofenceRegion:(NSDictionary *)geofence
+                      error:(NSError *)error;
+
+/**
+ 拉取地理围栏列表的回调
+ 
+ @param geofenceList 地理围栏列表
+ */
+- (void)jpushCallbackGeofenceReceived:(NSArray<NSDictionary*> *)geofenceList;
+
+/**
+ 进入地理围栏区域
+ 
+ @param geofenceId 地理围栏id
+ @param userInfo 地理围栏触发时返回的信息
+ @param error 错误信息
+ */
+- (void)jpushGeofenceIdentifer:(NSString *)geofenceId didEnterRegion:(NSDictionary *)userInfo error:(NSError *)error __attribute__((deprecated("JPush 3.6.0 版本已过期")));
+
+/**
+ 离开地理围栏区域
+ 
+ @param geofenceId 地理围栏id
+ @param userInfo 地理围栏触发时返回的信息
+ @param error 错误信息
+ */
+- (void)jpushGeofenceIdentifer:(NSString *)geofenceId didExitRegion:(NSDictionary *)userInfo error:(NSError *)error __attribute__((deprecated("JPush 3.6.0 版本已过期")));
+
+@end
+
+
+@protocol JPUSHNotiInMessageDelegate <NSObject>
+
+/**
+ 应用内提醒消息展示的回调
+ 
+ @param content 应用内提醒消息的内容
+
+ */
+- (void)jPushNotiInMessageDidShowWithContent:(NSDictionary *)content;
+
+/**
+ 应用内提醒消息点击的回调
+ 
+ @param content 应用内提醒消息的内容
+
+ */
+- (void)jPushNotiInMessageDidClickWithContent:(NSDictionary *)content;
+
+@end

+ 17 - 0
nativePlugins/JG-JPush/ios/UniPluginJPush.framework/Headers/JPushModule.h

@@ -0,0 +1,17 @@
+//
+//  JPushModule.h
+//  UniPluginJPush
+//
+//  Created by huangshuni on 2021/1/12.
+//
+
+#import <Foundation/Foundation.h>
+#import "DCUniModule.h"
+
+NS_ASSUME_NONNULL_BEGIN
+
+@interface JPushModule : DCUniModule
+
+@end
+
+NS_ASSUME_NONNULL_END

BIN
nativePlugins/JG-JPush/ios/UniPluginJPush.framework/Info.plist


BIN
nativePlugins/JG-JPush/ios/UniPluginJPush.framework/UniPluginJPush


BIN
nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeDirectory


BIN
nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeRequirements


BIN
nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeRequirements-1


+ 117 - 0
nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeResources

@@ -0,0 +1,117 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+	<key>files</key>
+	<dict>
+		<key>Headers/JPushModule.h</key>
+		<data>
+		hAItQbWWuw4mOOySo6FeWH3MYsA=
+		</data>
+		<key>Info.plist</key>
+		<data>
+		pWey0YGB83F7mxgYitvsFA+3a6Y=
+		</data>
+	</dict>
+	<key>files2</key>
+	<dict>
+		<key>Headers/JPushModule.h</key>
+		<dict>
+			<key>hash</key>
+			<data>
+			hAItQbWWuw4mOOySo6FeWH3MYsA=
+			</data>
+			<key>hash2</key>
+			<data>
+			LHaZ7SfsmEBYhVCf3bEBp8fHG5II1obOplOf4kj6EZQ=
+			</data>
+		</dict>
+	</dict>
+	<key>rules</key>
+	<dict>
+		<key>^.*</key>
+		<true/>
+		<key>^.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^version.plist$</key>
+		<true/>
+	</dict>
+	<key>rules2</key>
+	<dict>
+		<key>.*\.dSYM($|/)</key>
+		<dict>
+			<key>weight</key>
+			<real>11</real>
+		</dict>
+		<key>^(.*/)?\.DS_Store$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>2000</real>
+		</dict>
+		<key>^.*</key>
+		<true/>
+		<key>^.*\.lproj/</key>
+		<dict>
+			<key>optional</key>
+			<true/>
+			<key>weight</key>
+			<real>1000</real>
+		</dict>
+		<key>^.*\.lproj/locversion.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>1100</real>
+		</dict>
+		<key>^Base\.lproj/</key>
+		<dict>
+			<key>weight</key>
+			<real>1010</real>
+		</dict>
+		<key>^Info\.plist$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^PkgInfo$</key>
+		<dict>
+			<key>omit</key>
+			<true/>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^embedded\.provisionprofile$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+		<key>^version\.plist$</key>
+		<dict>
+			<key>weight</key>
+			<real>20</real>
+		</dict>
+	</dict>
+</dict>
+</plist>

BIN
nativePlugins/JG-JPush/ios/UniPluginJPush.framework/_CodeSignature/CodeSignature


BIN
nativePlugins/JG-JPush/ios/jpush-ios-4.8.1.a


+ 138 - 0
nativePlugins/JG-JPush/package.json

@@ -0,0 +1,138 @@
+{
+    "name": "JG-JPush",
+    "id": "JG-JPush",
+    "version": "1.1.1",
+    "description": "极光推送Hbuilder插件",
+    "_dp_type":"nativeplugin",
+    "_dp_nativeplugin":{
+        "ios": {
+            "plugins": [{
+                "type": "module",
+                "name": "JG-JPush",
+                "class": "JPushModule"
+            }],
+            "hooksClass": "JPushProxy",
+            "integrateType": "framework",
+            "deploymentTarget": "9.0",
+            "frameworks": [
+                "CFNetwork.framework",
+                "CoreFoundation.framework",
+                "CoreTelephony.framework",
+                "SystemConfiguration.framework",
+                "CoreGraphics.framework",
+                "Foundation.framework",
+                "UIKit.framework",
+                "Security.framework",
+                "libz.tbd",
+                "AdSupport.framework",
+                "UserNotifications.framework",
+                "libresolv.tbd",
+                "WebKit.framework",
+                "AppTrackingTransparency.framework",
+                "StoreKit.framework"
+            ],
+            "resources": [
+                
+            ],
+            "capabilities": {
+                "entitlements": {
+                    "aps-environment":"development"
+                }
+            },
+            "privacies": [
+                            "NSLocationAlwaysAndWhenInUseUsageDescription",
+                            "NSLocationAlwaysUsageDescription",
+                            "NSLocationWhenInUseUsageDescription"
+                        ],
+            "parameters": {
+                "JPUSH_ISPRODUCTION_IOS": {
+                    "des": "[iOS]是否是生产环境,是填true,不是填false或者不填",
+                    "key": "JPush:ISPRODUCTION"
+                },
+                "JPUSH_ADVERTISINGID_IOS": {
+                    "des": "[iOS]广告标识符(IDFA)如果不需要使用IDFA,可不填",
+                    "key": "JPush:ADVERTISINGID"
+                },
+                "JPUSH_DEFAULTINITJPUSH_IOS": {
+                    "des": "[iOS]是否默认初始化,是填true,不是填false或者不填",
+                    "key": "JPush:DEFAULTINITJPUSH"
+                }
+            }
+        },
+		 "android": {
+			 "plugins": [
+				 {
+					 "type": "module",
+					 "name": "JG-JPush",
+					 "class": "cn.jiguang.uniplugin_jpush.JPushModule"
+				 }
+			 ],
+			 "integrateType": "aar",
+			 "minSdkVersion": "19",
+			 "permissions": [
+				 "${applicationId}.permission.JPUSH_MESSAGE",
+				 "android.permission.RECEIVE_USER_PRESENT",
+				 "android.permission.INTERNET",
+				 "android.permission.READ_PHONE_STATE",
+				 "android.permission.WRITE_EXTERNAL_STORAGE",
+				 "android.permission.READ_EXTERNAL_STORAGE",
+				 "android.permission.WRITE_SETTINGS",
+				 "android.permission.MOUNT_UNMOUNT_FILESYSTEMS",
+				 "android.permission.ACCESS_NETWORK_STATE",
+				 "android.permission.ACCESS_WIFI_STATE",
+				 "com.huawei.android.launcher.permission.CHANGE_BADGE",
+				 "android.permission.VIBRATE",
+				 "android.permission.SYSTEM_ALERT_WINDOW",
+				 "android.permission.ACCESS_COARSE_LOCATION",
+				 "android.permission.CHANGE_WIFI_STATE",
+				 "android.permission.ACCESS_FINE_LOCATION",
+				 "android.permission.ACCESS_BACKGROUND_LOCATION",
+				 "android.permission.ACCESS_LOCATION_EXTRA_COMMANDS",
+				 "android.permission.CHANGE_NETWORK_STATE",
+				 "android.permission.GET_TASKS",
+				 "android.permission.QUERY_ALL_PACKAGES",
+				 "${applicationId}.permission.MIPUSH_RECEIVE",
+				 "com.coloros.mcs.permission.RECIEVE_MCS_MESSAGE",
+				 "com.heytap.mcs.permission.RECIEVE_MCS_MESSAGE"
+			 ],
+			 "parameters": {
+				 "JPUSH_OPPO_APPKEY": {
+					 "des": "厂商OPPO-appkey,示例:OP-12345678",
+					 "key": "OPPO_APPKEY"
+				 },
+				 "JPUSH_OPPO_APPID":{
+					 "des": "厂商OPPO-appId,示例:OP-12345678",
+					 "key": "OPPO_APPID"
+				 },
+				 "JPUSH_OPPO_APPSECRET":{
+					 "des": "厂商OPPO-appSecret,示例:OP-12345678",
+					 "key": "OPPO_APPSECRET"
+				 },
+				 "JPUSH_VIVO_APPKEY":{
+					 "des": "厂商VIVO-appkey,示例:12345678",
+					 "key": "com.vivo.push.api_key"
+				 },
+				 "JPUSH_VIVO_APPID":{
+					 "des": "厂商VIVO-appId,示例:12345678",
+					 "key": "com.vivo.push.app_id"
+				 },
+				 "JPUSH_MEIZU_APPKEY":{
+					 "des": "厂商MEIZU-appKey,示例:MZ-12345678",
+					 "key": "MEIZU_APPKEY"
+				 },
+				 "JPUSH_MEIZU_APPID":{
+					 "des": "厂商MEIZU-appId,示例:MZ-12345678",
+					 "key": "MEIZU_APPID"
+				 },
+				 "JPUSH_XIAOMI_APPKEY":{
+					 "des": "厂商XIAOMI-appKey,示例:MI-12345678",
+					 "key": "XIAOMI_APPKEY"
+				 },
+				 "JPUSH_XIAOMI_APPID":{
+					 "des": "厂商XIAOMI-appId,示例:MI-12345678",
+					 "key": "XIAOMI_APPID"
+				 }
+			 }
+		 }
+    }
+}

+ 338 - 18
pages.json

@@ -9,6 +9,13 @@
 				"navigationBarTitleText": ""
 				"navigationBarTitleText": ""
 			}
 			}
 		},
 		},
+		{
+			"path": "pages/login/apply-trial",  //  申请试用
+			"style": {
+				"navigationStyle": "default",  //  是否显示导航栏  default显示,custom不显示
+				"navigationBarTitleText": "申请注册"
+			}
+		},
 		{
 		{
 			"path": "pages/index/index", // 货架
 			"path": "pages/index/index", // 货架
 			"style": {
 			"style": {
@@ -42,21 +49,60 @@
 			"style": {
 			"style": {
 				"navigationBarTitleText": "修改密码"
 				"navigationBarTitleText": "修改密码"
 			}
 			}
-		}
-        ,{
+		},
+		{
+			"path": "pages/xtNotice/xtNotice",		//  我的>消息
+			"style": {
+				"navigationBarTitleText": "消息",
+				"navigationStyle":"custom",
+				"app-plus":{
+					"titleNView": {
+						"titleAlign": "left",
+						"buttons": [ //原生标题栏按钮配置,
+							{
+								"text": "设置全部已读" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
+								"fontSize": "14",
+								"color": "#00aaff",
+								"width":"100px"
+							}
+						]
+					}
+				}
+			}
+		},
+		{
+			"path": "pages/xtNotice/xtNoticeDetail/xtNoticeDetail",		//  我的>消息详情
+			"style": {
+				"navigationBarTitleText": "消息详情"
+			}
+		},
+        {
             "path" : "pages/latePlay/chooseBulk",
             "path" : "pages/latePlay/chooseBulk",
             "style" :                                                                                    
             "style" :                                                                                    
             {
             {
-                "navigationBarTitleText": "选择货柜",
+                "navigationBarTitleText": "选择货",
                 "enablePullDownRefresh": false
                 "enablePullDownRefresh": false
             }
             }
         }
         }
         ,{
         ,{
             "path" : "pages/latePlay/chooseProduct",
             "path" : "pages/latePlay/chooseProduct",
-            "style" :                                                                                    
-            {
-                "navigationBarTitleText": "补打贴签",
-                "enablePullDownRefresh": false
+            "style": {
+            	"navigationBarTitleText": "打印贴签",
+            	"navigationStyle":"custom",
+            	"app-plus":{
+            		"titleNView": {
+            			"titleAlign": "left",
+            			"buttons": [ //原生标题栏按钮配置,
+							{
+								"text": "\ue65a 批量打印" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
+								"fontSrc": "/static/iconfont/iconfont.ttf",
+								"fontSize": "14",
+								"color": "#00aaff",
+								"width":"110px"
+							}
+            			]
+            		}
+            	}
             }
             }
         },
         },
 		{
 		{
@@ -215,12 +261,12 @@
 				"navigationStyle":"custom",
 				"navigationStyle":"custom",
 				"app-plus":{
 				"app-plus":{
 					"titleNView": {
 					"titleNView": {
-						"titleAlign": "auto",
+						"titleAlign": "left",
 						"buttons": [ //原生标题栏按钮配置,
 						"buttons": [ //原生标题栏按钮配置,
 							{
 							{
 								"text": "\ue694 查询" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
 								"text": "\ue694 查询" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
 								"fontSrc": "/static/iconfont/iconfont.ttf",
 								"fontSrc": "/static/iconfont/iconfont.ttf",
-								"fontSize": "16",
+								"fontSize": "14",
 								"width":"90px"
 								"width":"90px"
 							}
 							}
 						]
 						]
@@ -249,12 +295,12 @@
 				"navigationStyle":"custom",
 				"navigationStyle":"custom",
 				"app-plus":{
 				"app-plus":{
 					"titleNView": {
 					"titleNView": {
-						"titleAlign": "auto",
+						"titleAlign": "left",
 						"buttons": [ //原生标题栏按钮配置,
 						"buttons": [ //原生标题栏按钮配置,
 							{
 							{
 								"text": "\ue694 查询" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
 								"text": "\ue694 查询" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
 								"fontSrc": "/static/iconfont/iconfont.ttf",
 								"fontSrc": "/static/iconfont/iconfont.ttf",
-								"fontSize": "16",
+								"fontSize": "14",
 								"width":"90px"
 								"width":"90px"
 							}
 							}
 						]
 						]
@@ -283,12 +329,12 @@
 				"navigationStyle":"custom",
 				"navigationStyle":"custom",
 				"app-plus":{
 				"app-plus":{
 					"titleNView": {
 					"titleNView": {
-						"titleAlign": "auto",
+						"titleAlign": "left",
 						"buttons": [ //原生标题栏按钮配置,
 						"buttons": [ //原生标题栏按钮配置,
 							{
 							{
 								"text": "\ue694 查询" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
 								"text": "\ue694 查询" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
 								"fontSrc": "/static/iconfont/iconfont.ttf",
 								"fontSrc": "/static/iconfont/iconfont.ttf",
-								"fontSize": "16",
+								"fontSize": "14",
 								"width":"90px"
 								"width":"90px"
 							}
 							}
 						]
 						]
@@ -340,6 +386,273 @@
             }
             }
             
             
         }
         }
+        ,{
+            "path" : "pages/shelfSetting/shelfList",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "选择货架",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfSetting/shelfSet",
+            "style": {
+            			"navigationStyle": "custom" ,// 隐藏系统导航栏
+            			"navigationBarTextStyle": "black" // 状态栏字体为白色,只能为 white-白色,black-黑色 二选一
+            		}
+        }
+        ,{
+            "path" : "pages/shelfSetting/editShelf",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "修改货架名称",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfSetting/searchShelfHw",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "按产品搜索",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfSetting/editShelfHw",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "编辑货位",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfSetting/addShelfHw",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "新增货位",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfSetting/bindProduct",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "绑定产品",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfSetting/batchPrint",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "批量打印",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfSetting/quickReplenish",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "快速补货",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/stockCheck/shelfList",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "选择货架",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/stockCheck/startCheck",
+            "style": {
+            	"navigationBarTitleText": "库存盘点",
+            	"navigationStyle":"custom",
+            	"app-plus":{
+            		"titleNView": {
+            			"titleAlign": "left",
+            			"buttons": [ //原生标题栏按钮配置,
+            				{
+            					"text": "\ue694 盘点历史" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
+            					"fontSrc": "/static/iconfont/iconfont.ttf",
+            					"fontSize": "14",
+								"color": "#00aaff",
+            					"width":"120px"
+            				}
+            			]
+            		}
+            	}
+            }
+        }
+        ,{
+            "path" : "pages/stockCheck/submitStockCheck",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "提交盘点单",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/stockCheck/checkRecord",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "盘点历史",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/batchShelves/index",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "批量上架—选层",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/batchShelves/scanProduct",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "扫描条形码",
+                "enablePullDownRefresh": false,
+				"app-plus":{
+					"titleNView": {
+						"titleAlign": "left",
+						"buttons": [ //原生标题栏按钮配置,
+							{
+								"text": "\ue694 搜索" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
+								"fontSrc": "/static/iconfont/iconfont.ttf",
+								"fontSize": "16",
+								"color": "#00aaff",
+								"width":"80px"
+							}
+						]
+					}
+				}
+            }
+            
+        }
+        ,{
+            "path" : "pages/batchShelves/searchProduct",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "产品编码搜索",
+                "enablePullDownRefresh": false,
+				"app-plus":{
+					"titleNView": {
+						"titleAlign": "left",
+						"buttons": [ //原生标题栏按钮配置,
+							{
+								"text": "\ue617 扫码" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
+								"fontSrc": "/static/iconfont/iconfont.ttf",
+								"fontSize": "16",
+								"color": "#00aaff",
+								"width":"80px"
+							}
+						]
+					}
+				}
+            }
+            
+        }
+        ,{
+            "path" : "pages/batchShelves/cartList",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "批量上架",
+                "enablePullDownRefresh": false,
+				"app-plus":{
+					"titleNView": {
+						"titleAlign": "left",
+						"buttons": [ //原生标题栏按钮配置,
+							{
+								"text": "\ue67a 上架" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
+								"fontSrc": "/static/iconfont/iconfont.ttf",
+								"fontSize": "14",
+								"color": "#00aaff",
+								"width":"80px"
+							},
+							{
+								"text": "\ue65a 打印" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
+								"fontSrc": "/static/iconfont/iconfont.ttf",
+								"fontSize": "14",
+								"color": "#00aaff",
+								"width":"auto"
+							}
+						]
+					}
+				}
+            }
+        },{
+            "path" : "pages/batchShelves/editShelfHw",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "编辑上架信息",
+                "enablePullDownRefresh": false
+            }
+        }
+        ,{
+            "path" : "pages/batchShelves/setProductCost",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "结算价设置",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/batchShelves/batchPrint/batchPrint",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "批量打印",
+                "enablePullDownRefresh": false
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfOrder/shelfOrder",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "货架订单",
+                "enablePullDownRefresh": false,
+				"app-plus":{
+					"titleNView": {
+						"titleAlign": "left",
+						"buttons": [ //原生标题栏按钮配置,
+							{
+								"text": "\ue694 查询" ,//原生标题栏增加分享按钮,点击事件可通过页面的 onNavigationBarButtonTap 函数进行监听u
+								"fontSrc": "/static/iconfont/iconfont.ttf",
+								"fontSize": "14",
+								"width":"80px"
+							}
+						]
+					}
+				}
+            }
+            
+        }
+        ,{
+            "path" : "pages/shelfOrder/orderDetail",
+            "style" :                                                                                    
+            {
+                "navigationBarTitleText": "货架订单详情",
+                "enablePullDownRefresh": false
+            }
+            
+        }
     ],
     ],
 	"globalStyle": {
 	"globalStyle": {
 		"navigationBarTextStyle": "black",
 		"navigationBarTextStyle": "black",
@@ -349,7 +662,10 @@
 		"app-plus": {
 		"app-plus": {
 			// 将回弹属性关掉
 			// 将回弹属性关掉
 			"bounce": "none",
 			"bounce": "none",
-			"scrollIndicator": "none"
+			"scrollIndicator": "none",
+			"titleAlign": "left",
+			"disableSwipeBack": true,
+			"softinputMode":"adjustResize"
 		}
 		}
 	},
 	},
 	"tabBar": {
 	"tabBar": {
@@ -357,19 +673,23 @@
 		"list": [
 		"list": [
 			{
 			{
 				"pagePath": "pages/sales/index",
 				"pagePath": "pages/sales/index",
-				"text": "销售"
+				"text": "销售",
+				"visible": true
 			},
 			},
 			{
 			{
 				"pagePath": "pages/stock/index",
 				"pagePath": "pages/stock/index",
-				"text": "库存"
+				"text": "库存",
+				"visible": true
 			},
 			},
 			{
 			{
 				"pagePath": "pages/index/index",
 				"pagePath": "pages/index/index",
-				"text": "货架"
+				"text": "货架",
+				"visible": true
 			},
 			},
 			{
 			{
 				"pagePath": "pages/userCenter/index",
 				"pagePath": "pages/userCenter/index",
-				"text": "我的"
+				"text": "我的",
+				"visible": true
 			}
 			}
 		]
 		]
 	}
 	}

+ 12 - 7
pages/approveStore/authPass.vue

@@ -50,7 +50,7 @@
 					<u-picker v-model="settleStyleModal" @confirm="settleStyleChange" :range="settleStyleList" range-key="dispName" mode="selector"></u-picker>
 					<u-picker v-model="settleStyleModal" @confirm="settleStyleChange" :range="settleStyleList" range-key="dispName" mode="selector"></u-picker>
 				</u-form-item>
 				</u-form-item>
 				<u-form-item label="授信金额" v-if="form.settleType == 'CREDIT'" required prop="creditLimit">
 				<u-form-item label="授信金额" v-if="form.settleType == 'CREDIT'" required prop="creditLimit">
-					<u-input :clearable="false" type="digit" :min="100" :maxlength="8" @input="numberToFixed('creditLimit',2,999999)" v-model.trim="form.creditLimit" placeholder="请输入大于100的数字,最多两位小数"/>
+					<u-input :clearable="false" type="digit" :min="100" :maxlength="8" @blur="numberToFixed('creditLimit',2,999999)" v-model.trim="form.creditLimit" placeholder="请输入大于100的数字,最多两位小数"/>
 				</u-form-item>
 				</u-form-item>
 			</u-form>
 			</u-form>
 		</view>
 		</view>
@@ -100,9 +100,7 @@
 					storeImage:[{ required: true, message: '请选择门头照片', trigger: 'change' }],
 					storeImage:[{ required: true, message: '请选择门头照片', trigger: 'change' }],
 					storeName: [{ required: true, message: '请输入门店名称', trigger: 'change' }],
 					storeName: [{ required: true, message: '请输入门店名称', trigger: 'change' }],
 					contactMobile: [{ required: false, pattern: /^\d{30}$/, message: '请输入正确的手机号', trigger: 'change' }],
 					contactMobile: [{ required: false, pattern: /^\d{30}$/, message: '请输入正确的手机号', trigger: 'change' }],
-					addrProvince: [{ required: true, message: '请选择省', trigger: 'change' }],
-					addrCity: [{ required: true, message: '请选择市', trigger: 'change' }],
-					addrDistrict: [{ required: true, message: '请选择区/县', trigger: 'change' }],
+					label: [{ required: true, message: '请选择地区', trigger: 'change' }],
 					addrDetail: [{ required: true, message: '请输入详细地址', trigger: 'change' }],
 					addrDetail: [{ required: true, message: '请输入详细地址', trigger: 'change' }],
 					contactName: [{ required: true, message: '请输入联系人姓名', trigger: 'change' }],
 					contactName: [{ required: true, message: '请输入联系人姓名', trigger: 'change' }],
 					settleType: [{ required: true, message: '请选择收结算方式', trigger: 'change' }],
 					settleType: [{ required: true, message: '请选择收结算方式', trigger: 'change' }],
@@ -153,9 +151,16 @@
 			      this.form = Object.assign(this.form, res.data)
 			      this.form = Object.assign(this.form, res.data)
 			      this.storePhotoList = this.form.storeImage ? [{url:this.form.storeImage}] : []
 			      this.storePhotoList = this.form.storeImage ? [{url:this.form.storeImage}] : []
 			      this.yyzzPhotoList = this.form.licenseImage ? [{url:this.form.licenseImage}] : [],
 			      this.yyzzPhotoList = this.form.licenseImage ? [{url:this.form.licenseImage}] : [],
-			      this.labelArr = [this.form.addrProvinceName,this.form.addrCityName,this.form.addrDistrictName]
-			      this.areaIdArr = [this.form.addrProvince,this.form.addrCity,this.form.addrDistrict]
-			      this.form.label = this.labelArr.join('-')
+				  this.form.addrDetail = this.form.addrDetail || ''
+				  if(this.form.addrProvinceName&&this.form.addrCityName&&this.form.addrDistrictName){
+					  this.labelArr = [this.form.addrProvinceName,this.form.addrCityName,this.form.addrDistrictName]
+					  this.areaIdArr = [this.form.addrProvince,this.form.addrCity,this.form.addrDistrict]
+					  this.form.label = this.labelArr.join('-')
+				  }else{
+					  this.labelArr = []
+					  this.areaIdArr = []
+					  this.form.label = ''
+				  }
 			      this.form.auditStatus = 'PASS' // 通过
 			      this.form.auditStatus = 'PASS' // 通过
 			    } else {
 			    } else {
 			      this.$refs.ruleForm.resetFields()
 			      this.$refs.ruleForm.resetFields()

+ 12 - 4
pages/approveStore/detail.vue

@@ -7,7 +7,8 @@
 		<view class="login-form">
 		<view class="login-form">
 			<u-form :model="form" label-width="180rpx" :error-type="['toast']" ref="uForm">
 			<u-form :model="form" label-width="180rpx" :error-type="['toast']" ref="uForm">
 				<u-form-item label="门头照片">
 				<u-form-item label="门头照片">
-					<u-image :src="form.storeImage" width="200" height="150"></u-image>
+					<u-image v-if="form.storeImage" :src="form.storeImage" width="200" height="150"></u-image>
+					<text v-else>未上传</text>
 				</u-form-item>
 				</u-form-item>
 				<u-form-item label="营业执照">
 				<u-form-item label="营业执照">
 					<u-image v-if="form.licenseImage" :src="form.licenseImage" width="200" height="150"></u-image>
 					<u-image v-if="form.licenseImage" :src="form.licenseImage" width="200" height="150"></u-image>
@@ -96,9 +97,16 @@
 				  console.log(res)
 				  console.log(res)
 			    if (res.status == 200) {
 			    if (res.status == 200) {
 			      this.form = Object.assign(this.form, res.data)
 			      this.form = Object.assign(this.form, res.data)
-			      this.labelArr = [this.form.addrProvinceName,this.form.addrCityName,this.form.addrDistrictName]
-			      this.areaIdArr = [this.form.addrProvince,this.form.addrCity,this.form.addrDistrict]
-			      this.form.label = this.labelArr.join('-')
+				  this.form.addrDetail = this.form.addrDetail || '--'
+				  if(this.form.addrProvinceName&&this.form.addrCityName&&this.form.addrDistrictName){
+				  	this.labelArr = [this.form.addrProvinceName,this.form.addrCityName,this.form.addrDistrictName]
+				  	this.areaIdArr = [this.form.addrProvince,this.form.addrCity,this.form.addrDistrict]
+				  	this.form.label = this.labelArr.join('-')
+				  }else{
+					this.labelArr = []
+					this.areaIdArr = []
+					this.form.label = '--'
+				  }
 			    }  
 			    }  
 			  })
 			  })
 			},
 			},

+ 1 - 1
pages/approveStore/list.vue

@@ -27,7 +27,7 @@
 								<view class="info">
 								<view class="info">
 									<view class="btext">{{item.contactPhone}} {{item.contactName}}</view>
 									<view class="btext">{{item.contactPhone}} {{item.contactName}}</view>
 									<view>{{item.storeName}}</view>
 									<view>{{item.storeName}}</view>
-									<view class="addr">{{item.addrProvinceName +'-'+ item.addrCityName +'-'+ item.addrDistrictName +'-'+ item.addrDetail}}</view>
+									<view class="addr" v-if="item.addrProvinceName||item.addrDetail">{{item.addrProvinceName +'-'+ item.addrCityName +'-'+ item.addrDistrictName +' '+ item.addrDetail}}</view>
 								</view>
 								</view>
 							</view>
 							</view>
 							<view style="width: 100%;text-align: right;" v-if="item.auditStatus == 'WAIT'">
 							<view style="width: 100%;text-align: right;" v-if="item.auditStatus == 'WAIT'">

+ 272 - 0
pages/batchShelves/batchPrint/batchPrint.vue

@@ -0,0 +1,272 @@
+<template>
+	<view class="batchPrint-manualPrint-wrap" :style="{'padding-top':type=='search'?'100rpx':'0'}">
+		<view v-if="type=='search'" class="productList-search">
+			<view class="search flex align_center">
+				<view class="input">
+					<u-search 
+					v-model="queryWord" 
+					@input="$u.debounce(searchList, 800)"
+					@custom="$u.debounce(searchList, 500)" 
+					@search="$u.debounce(searchList, 500)" 
+					@clear="clearSearch" 
+					bg-color="#fff" 
+					:show-action="false"
+					placeholder="请输入产品编码查询"></u-search>
+				</view>
+			</view>
+		</view>
+		<view class="batchPrint-manualPrint-body">
+			<view class="part-list">
+				<!-- 产品 -->
+				<productList :list="partList" title="产品列表" ref="productList" noDataText="暂无产品" @allChecked="allCheckedCallback"></productList>
+			</view>
+		</view>
+		<view class="batchPrint-manualPrint-footer">
+			<view>
+				<u-checkbox size="40" @change="allCheckeChange" v-model="allChecked" shape="circle">{{allChecked?'取消全选':'全选'}}</u-checkbox>
+			</view>
+			<view>
+			</view>
+			<view>
+				<kk-printer ref="kkprinter" defaultText="开始打印" @closeConnect="closeConnect" @startPrint="startPrint"></kk-printer>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { clzConfirm, numberToFixed } from '@/libs/tools';
+	import kkPrinter from '@/components/kk-printer/index.vue';
+	import productList from './productList.vue'
+	import {printTempl} from '@/libs/printTools.js'
+	export default {
+		components: { productList, kkPrinter },
+		data() {
+			return {
+				show: false,
+				basicInfoData:null,
+				partList: [],
+				allList:[],
+				allChecked: false,
+				printIndex: 0,
+				isParinting: false,
+				type: '',
+				queryWord: ''
+			}
+		},
+		onReady() {
+			if(this.type == 'manual'){
+				uni.showLoading({
+					title: '正在加载...'
+				})
+				this.$refs.productList.setData(this.partList)
+				setTimeout(()=>{
+					uni.hideLoading()
+					this.allCheckeChange({value:true})
+					this.allChecked = true
+				},3000)
+			}
+		},
+		onLoad(option) {
+			this.basicInfoData = JSON.parse(decodeURIComponent(option.data));
+			this.type = option.type
+			// 批量打印
+			if(this.type == 'manual'){
+				this.partList = this.$store.state.vuex_tempPrintList
+			}else{
+				this.allList = this.$store.state.vuex_tempPrintList
+			}
+			// 保持屏幕常亮
+			uni.setKeepScreenOn({
+				keepScreenOn: true
+			});
+			uni.setNavigationBarColor({
+				frontColor: '#ffffff',
+				backgroundColor: this.$config('primaryColor')
+			})
+			uni.setNavigationBarTitle({
+				title: this.type == 'search' ? '按编码搜索打印' : '批量打印—'+this.basicInfoData.layer+'层'
+			})
+		},
+		onUnload() {
+			this.partList = []
+			// 保持屏幕常亮
+			uni.setKeepScreenOn({
+				keepScreenOn: false
+			});
+			this.$store.state.vuex_tempPrintList = []
+		},
+		onBackPress(event){
+			if(event.from == 'backbutton'){
+				if(this.isParinting){
+					uni.showToast({
+						icon:'none',
+						title: '正在打印中...'
+					})
+				}else{
+					uni.navigateBack({delta: 1})
+				}
+				return true  // 阻止默认返回行为(会导致无限循环)
+			}
+		},
+		methods: {
+			searchList(e){
+				if(this.queryWord == ''){
+					this.clearSearch()
+					return
+				}
+				
+				uni.showLoading({
+					mask: true,
+					title: "正在搜索..."
+				})
+				this.partList = []
+				// 搜索
+				for(let key in this.allList){
+					const item = this.allList[key]
+					const ret = item.filter(a => a.productCode.indexOf(this.queryWord)>=0)
+					this.partList = this.partList.concat(ret)
+				}
+				this.$refs.productList.setData(this.partList)
+				
+				setTimeout(()=>{
+					uni.hideLoading()
+				},1000)
+			},
+			clearSearch(){
+				this.partList = []
+				this.$refs.productList.setData(this.partList)
+			},
+			// 全选
+			allCheckeChange(e){
+				this.$refs.productList.allSelect(e.value)
+			},
+			allCheckedCallback(val){
+				this.allChecked = val
+			},
+			printOnce(opt,tsc,blesdk,data){
+				const _this = this
+				const dealer = this.$store.state.vuex_userData
+				// 60*40 打印模板
+				const command = printTempl(tsc,{
+					dealerName: dealer.orgName,
+					shelfName: this.basicInfoData.shelfName || '',
+					productCode: data.productCode || '',
+					productName: data.product.productName|| '',
+					shelfPlaceCode: data.shelfPlaceCode || '',
+					currentInven: data.printQty,
+					printDate: this.$u.timeFormat(this.timestamp, 'yyyy-mm-dd hh:MM'),
+					printUser: dealer.userNameCN,
+					barCode: `${data.shelfSn}&${data.productCode}&${data.productSn}&${data.shelfPlaceSn}`
+				})
+				// 开始批量打印 
+				blesdk.senBlData(
+				opt.deviceId, 
+				opt.serviceId, 
+				opt.writeId, 
+				command.getData(), 
+				function(){
+					const result =_this.$refs.productList.getAllChecked()
+					_this.printIndex = _this.printIndex + 1
+					if(_this.printIndex < result.length){
+						_this.printOnce(opt,tsc,blesdk,result[_this.printIndex])
+					}else{
+						_this.printIndex = 0
+						_this.$refs.kkprinter.onPrintSuccess()
+						_this.isParinting = false
+						uni.hideLoading()
+						clzConfirm({
+						  title: '提示',
+						  content: '打印已经结束,是否返回上页!',
+						  success (ret) {
+							if (ret.confirm || ret.index == 0) {
+								uni.navigateBack()
+							} 
+						  }
+						})
+					}
+				});
+			},
+			closeConnect(){
+				this.isParinting = false
+				uni.hideLoading()
+			},
+			// 批量打印 
+			startPrint(opt,tsc,blesdk){
+				const result =this.$refs.productList.getAllChecked()
+				console.log(result,result.length)
+				if(result.length){
+					 if(this.isParinting){
+					 	return
+					 }
+					 this.isParinting = true
+					 uni.showLoading({
+					 	mask: true,
+					 	title: '正在打印中,请勿息屏或退出应用!'
+					 })
+					 this.printOnce(opt,tsc,blesdk,result[this.printIndex])
+				}else{
+					this.toashMsg("请选择产品!")
+					this.$refs.kkprinter.onPrintFail()
+				}
+			},
+		}
+	}
+</script>
+
+<style lang="less">
+.batchPrint-manualPrint-wrap{
+	width: 100%;
+	height: 100%;
+	overflow: hidden;
+	padding-bottom: 102upx;
+	.productList-search{
+		padding: 20rpx 30rpx;
+		background-color: #fff;
+		position: fixed;
+		left: 0;
+		top: 0;
+		width: 100%;
+		display: flex;
+		z-index: 100;
+		.search{
+			padding: 0.1rem;
+			border-radius: 50rpx;
+			border:1rpx solid #eee;
+			width: 100%;
+			.input{
+				flex-grow: 1;
+				padding: 4rpx;
+			}
+			.icon{
+				width: 13%;
+				text-align: center;
+				font-size: 46rpx;
+				color: #999;
+			}
+		}
+	}
+	.batchPrint-manualPrint-body{
+		.part-list{
+			padding: 10rpx 25rpx;
+			background-color: #fff;
+			margin-bottom: 20rpx;
+			border-radius: 25rpx;
+			box-shadow: 2rpx 3rpx 5rpx #eee;
+		}
+	}
+	.batchPrint-manualPrint-footer{
+		padding: 10upx 32upx 12upx;
+		background-color: #fff;
+		position: fixed;
+		left: 0;
+		bottom: 0;
+		width: 100%;
+		box-shadow: 3px 1px 7px #eee;
+		display: flex;
+		align-items: center;
+		justify-content: space-between;
+		z-index: 1000;
+	}
+}
+</style>

+ 224 - 0
pages/batchShelves/batchPrint/productList.vue

@@ -0,0 +1,224 @@
+<template>
+	<view class="partList-box flex flex_column">
+		<view class="partList-title flex align_center justify_between" v-if="partList.length">
+			<text>{{title}}</text>
+			<view class="heji">
+				共 <text>{{partList.length}}</text> 产品
+			</view>
+		</view>
+		<view class="partList-list">
+			<view class="partList-list-box" v-for="item in partList" :key="item.id">
+				<view class="product flex align_center">
+					<view class="checkbox">
+						<u-checkbox v-model="item.checked" :name="item.id" @change="checkChange" size="40" shape="circle"></u-checkbox>
+					</view>
+					<view class="flex align_center flex_1" @click="checkChange({name:item.id})">
+						<view class="pimgs">
+							<u-image :src="item.product&&item.product.images?item.product.images:`../../static/${$config('themePath')}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
+						</view>
+						<view class="pinfo">
+							<view class="pname">
+								<text>{{item.shelfPlaceCode}}</text>{{item.productCode}}
+							</view>
+							<view class="pname pname1">
+								{{item.product.productName}}
+							</view>
+						</view>
+					</view>
+				</view>
+				<!-- 有复选框 -->
+				<view class="ptools flex align_center justify_between">
+					<view class="ptxt">
+					   本次上架:<text class="pnums">{{item.qty}}{{item.product&&item.product.unit}}</text>
+					</view>
+					<view class="pcurnums flex align_center">
+						<text>打印数量</text>
+						<view class="u-ninput">
+							<u-number-box :input-height="60" color="#000" bg-color="#fff" v-model="item.printQty" :min="1"></u-number-box>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view class="nodata" v-if="partList.length==0">
+				<u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="120" :text="noDataText" img-width="120" mode="list"></u-empty>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		props: {
+			list: {
+				type: Array,
+				default: function(){
+					return []
+				}
+			},
+			noDataText: {
+				type: String,
+				default: '暂无产品'
+			},
+			title: {
+				type: String,
+				default: '列表'
+			},
+			// model: checkbox 可选择模式,view 只显示
+			model: {
+				type: String,
+				default: 'checkbox'
+			},
+		},
+		data() {
+			return {
+				partList: [],
+			}
+		},
+		methods: {
+			setData(list){
+				const _this = this
+				list.map(item => {
+					item.printQty = item.qty
+					item.checked = false
+				})
+				this.partList = JSON.parse(JSON.stringify(list))
+			},
+			// 全选
+			allSelect(val){
+				this.partList.map(item => {
+					item.checked = val
+				})
+				this.partList.splice()
+			},
+			checkChange(e){
+				const row = this.partList.find(item => item.id == e.name)
+				if(row){
+					row.checked = !row.checked
+					this.partList.splice()
+				}
+				// 判断是否全选
+				const isAllNoChecked = this.partList.filter(item => !item.checked)
+				this.$emit('allChecked',isAllNoChecked.length == 0)
+			},
+			// 获取所有选择的
+			getAllChecked(){
+				return this.partList.filter(item => item.checked && item.printQty)
+			},
+			// 获取所有数据
+			getAllData(){
+				return this.partList
+			},
+			// 数量 change
+			numberChange(value, index){
+				this.$emit('numberChange', value, index)
+			}
+		}
+	}
+</script>
+
+<style lang="less" scoped>
+.partList-box{
+	height: 100%;
+	position: relative;
+	.nodata{
+		padding: 10vh 0;
+	}
+	.partList-title{
+		padding: 15rpx 20rpx;
+		border-bottom: 1rpx solid #eee;
+		width: 100%;
+		background-color: #fff;
+		> text{
+			font-size: 32rpx;
+			color: #222222;
+		}
+		> view{
+			font-size: 30rpx;
+			text{
+				color: red;
+				margin: 0 5rpx;
+			}
+		}
+	}
+	.partList-list{
+		flex-grow: 1;
+	}
+	.partList-list-box{
+		padding: 10px 0;
+		border-bottom: 2rpx solid #f5f5f5;
+		&:last-child{
+			border:0;
+		}
+		.product{
+			flex-grow: 1;
+			.checkbox{
+				width: 60rpx;
+			}
+			.pinfo{
+				flex-grow: 1;
+				padding-left: 20rpx;
+				.pname{
+					color: #666;
+					margin-bottom: 10rpx;
+					text{
+						font-weight: normal;
+						margin-right: 6rpx;
+						padding: 0 20rpx;
+						background: rgba(3, 54, 146, 0.15);
+						border-radius: 100rpx;
+						color: #033692;
+						font-size: 24rpx;
+					}
+				}
+				.pname1{
+					font-weight: bold;
+					font-size: 30rpx;
+				}
+				.pno{
+					background-color: rgba(3, 54, 146, 0.15);
+					border-radius: 50rpx;
+					padding: 0 20rpx;
+					color: #033692;
+					font-size: 24rpx;
+					margin-right: 10rpx;
+				}
+			}
+		}
+		.ptools{
+			margin-top: 20rpx;
+			.ptxt{
+				font-size: 28rpx;
+				color: #999;
+				.pnums{
+					color: #222;
+					padding: 0 4upx;
+				}
+			}
+			.pcurnums{
+				> text{
+					margin-right: 20rpx;
+					font-size: 28rpx;
+					color: #999;
+				}
+			}
+			.u-ninput{
+				border: 2rpx solid #eee;
+				border-radius: 50rpx;
+				padding: 0 6rpx;
+			}
+			/deep/ .u-icon-disabled{
+				background: #fff!important;
+			}
+			/deep/ .u-number-input{
+				margin: 0 0;
+				border: 2rpx solid #eee;
+				border-top: 0;
+				border-bottom: 0;
+			}
+			/deep/ .u-icon-plus, /deep/ .u-icon-minus{
+				border-radius: 50rpx;
+			}
+		}
+	}
+}
+</style>

+ 542 - 0
pages/batchShelves/cartList.vue

@@ -0,0 +1,542 @@
+<template>
+	<view class="content flex flex_column">
+		<view class="product-list flex" v-if="placeTab.length">
+			<scroll-view scroll-y class="leftTabs">
+				<view class="tabbox">
+					<view v-for="item in placeTab" :key="item" :class="curTab==item?'active':''" @click="curTab = item">{{item}}层</view>
+				</view>
+			</scroll-view>
+			<scroll-view scroll-y class="rightCons" v-if="shelfPlaceList">
+				<view 
+				class="partList-list-box" 
+				v-for="item in shelfPlaceList[curTab]" 
+				:key="item.shelfCartSn"
+				>
+					<view class="flex align_center flex_1" @click="editRow(item)">
+						<view class="pimgs">
+							<u-image :src="item.product&&item.product.images?item.product.images:`../../static/${$config('themePath')}/def_img@2x.png`" width="120" height="120" border-radius="10"></u-image>
+						</view>
+						<view class="pinfo">
+							<view class="ptxt">
+								<text>{{item.shelfPlaceCode}}</text>
+								{{item.productCode}}
+							</view>
+							<view class="pname">
+								{{item.product.productName}}
+							</view>
+						</view>
+					</view>
+					<view class="ptools flex align_center justify_between">
+						<view></view>
+						<view class="pcurnums flex align_center">
+							<view class="u-ninput">
+								<u-number-box :long-press="false" :index="item.id" :input-height="60" @blur="updateNums" @plus="updateNums" @minus="updateNums" color="#000" bg-color="#fff" v-model="item.qty" :min="0"></u-number-box>
+							</view>
+						</view>
+					</view>
+				</view>
+			</scroll-view>
+		</view>
+		<view class="product-list" v-else>
+			<view style="padding: 200upx 0 0;">
+				<u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="150" text="暂无货位产品,请录入" img-width="150" mode="list"></u-empty>
+			</view>
+			<view style="text-align: center;margin-top: 50upx;" v-if="!loading">
+				<u-button @click="showLayer=true" type='primary' shape="circle" size="medium">点击录入产品</u-button>
+			</view>
+		</view>
+		<view class="footer-bar flex align_center justify_between" v-if="placeTab.length">
+			<view class="heji flex align_center" @click="showPop=!showPop">
+				所有层合计款数:<text>{{totalKs}}</text>;数量:<text>{{totalNums}}</text>;
+				<u-icon name="arrow-up"></u-icon>
+			</view>
+			<view class="btns">
+				<u-button @click="showLayer=true" type='primary' shape="circle" size="medium">继续录入产品</u-button>
+			</view>
+		</view>
+		
+		<!-- 合计弹框 -->
+		<u-popup mode="bottom" closeable v-model="showPop" :z-index="100">
+			<view class="heji-content">
+				<scroll-view scroll-y="true" style="height: 400rpx;">
+					<view class="heji-con-list">
+						<view class="flex align_center" v-for="item in countData" :key="item.shelfTierCode">
+							<view>{{item.shelfTierCode}}层</view>
+							<view class="flex align_center">
+								<text>款数:{{item.category}}</text>
+								<text>数量:{{item.qty}}</text>
+							</view>
+						</view>
+					</view>
+				</scroll-view>
+			</view>
+		</u-popup>
+		
+		<!-- 选中层 -->
+		<u-popup mode="center" width="80%" :mask-close-able="false" closeable @close="curLayer=''" v-model="showLayer" border-radius="15">
+			<view class="layer-content">
+				 <view class="tits">请选择产品的货架层号</view>
+				 <view class="tagbox flex">
+				 	<view>
+				 		<view class="tag" :class="curLayer==item?'active':''" v-for="item in layerList" :key="item" @click="curLayer=curLayer==item?'':item">
+				 			{{item}}层
+				 		</view>
+				 	</view>
+				 </view>
+				 <view class="newbtn flex justify_between" v-if="curLayer">
+				 	<u-button shape="circle" @click="searchProduct()" size="medium">按产品编码搜索</u-button>
+				 	<u-button @click="scanProduct()" type='primary' shape="circle" size="medium">扫描条形码匹配</u-button>
+				 </view>
+			</view>
+		</u-popup>
+		<!-- 上架确认 -->
+		<choose-type-modal v-if="chooseModal" :totalKs="totalKs" :totalNums="totalNums" :openModal="chooseModal" @confirm="confirmPut" @close="chooseModal = false" />
+		<printStickerModal v-if="showPrintModal" :layer="curTab" :openModal="showPrintModal" @confirm="confirmPrint" @close="showPrintModal = false"></printStickerModal>
+	</view>
+</template>
+
+<script>
+	import { clzConfirm, numberToFixed } from '@/libs/tools';
+	import {queryMapList, queryCountList, shelfCartSave, shelfCartDelete, queryEmptyCostList, shelfCartConfirm} from '@/api/shelfCart.js'
+	import chooseTypeModal from './chooseTypeModal'
+	import printStickerModal from './printStickerModal'
+	export default {
+		components: {
+			chooseTypeModal,
+			printStickerModal
+		},
+		data() {
+			return {
+				loading: false,
+				showPop: false,
+				chooseModal: false,
+				showPrintModal: false,
+				shelfSn: '',
+				shelfName: '',
+				shelfPlaceList: null,
+				placeTab: [],
+				curTab: '',
+				totalKs: 0,
+				totalNums: 0,
+				countData: [],
+				layerList: [],
+				showLayer: false,
+				curLayer: ''
+			}
+		},
+		onShow() {
+			this.curLayer = ''
+			this.pageInit()
+		},
+		onLoad(opts) {
+			this.layerList = 'A、B、C、D、E、F、G、H、I、J、K、L、M、N、O、P、Q、R、S、T、U、V、W、X、Y、Z'.split('、');
+			this.shelfSn = opts.shelfSn
+			this.shelfName = opts.shelfName
+			this.customerSn = opts.customerSn
+			uni.$on("setCostOk",()=>{
+				this.chooseModal = true
+			})
+		},
+		onNavigationBarButtonTap(e) {
+			console.log(e)
+			if(this.placeTab.length){
+				// 上架入库
+				if(e.index == 0){
+					this.toPutaway()
+				}
+				// 打印贴签
+				if(e.index == 1){
+					this.showPrintModal = true
+				}
+			}else{
+				uni.showToast({
+					icon: 'none',
+					title: '还未录入产品,不能操作',
+					duration: 4000
+				})
+			}
+		},
+		methods: {
+			pageInit(flag){
+				this.placeTab = []
+				this.shelfPlaceList = null
+				this.countData = []
+				this.getList(flag)
+				this.getCount()
+			},
+			scanProduct(){
+				this.showLayer = false
+				uni.navigateTo({
+					url: "/pages/batchShelves/scanProduct?shelfSn="+this.shelfSn+'&layer='+this.curLayer+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn+'&from=cartList'
+				})
+			},
+			searchProduct(){
+				this.showLayer = false
+				uni.navigateTo({
+					url: "/pages/batchShelves/searchProduct?shelfSn="+this.shelfSn+'&layer='+this.curLayer+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn+'&from=cartList'
+				})
+			},
+			// 上架入库
+			toPutaway(){
+				uni.showLoading({
+					title: '正在查询...',
+					mask: true
+				})
+				queryEmptyCostList({shelfSn: this.shelfSn}).then(res => {
+					console.log(res)
+					uni.hideLoading()
+					if(res.data&&res.data.length){
+						this.$store.state.vuex_tempData = res.data
+						// 去设置价格
+						uni.navigateTo({
+							url: "/pages/batchShelves/setProductCost?shelfSn="+this.shelfSn+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn
+						})
+					}else{
+						this.chooseModal = true
+					}
+				})
+			},
+			//确认上架
+			confirmPut(data){
+				uni.showLoading({
+					mask: true,
+					title: '正在上架...'
+				})
+				shelfCartConfirm({
+					shelfSn: this.shelfSn,
+					...data
+				}).then(res => {
+					uni.hideLoading()
+					if(res.status == 200){
+						uni.navigateBack()
+					}
+				})
+			},
+			// 打印
+			confirmPrint(type){
+				this.showPrintModal = false
+				const shelfInfo = {
+					shelfSn: this.shelfSn,
+					shelfName: this.shelfName,
+					layer: this.curTab
+				}
+				// 打印当前层
+				if(type == 'manual'){
+					const list = this.shelfPlaceList[this.curTab]
+					this.$store.state.vuex_tempPrintList = list
+					if(shelfInfo&&list.length){
+						uni.navigateTo({
+							url: "/pages/batchShelves/batchPrint/batchPrint?type=manual&data="+encodeURIComponent(JSON.stringify(shelfInfo)) 
+						})
+					}else{
+						uni.showToast({
+							icon: 'none',
+							title: '没有可打印的产品',
+							duration: 5000
+						})
+					}
+				}else{
+					// 搜索打印
+					this.$store.state.vuex_tempPrintList = this.shelfPlaceList
+					uni.navigateTo({
+						url: "/pages/batchShelves/batchPrint/batchPrint?type=search&data="+encodeURIComponent(JSON.stringify(shelfInfo)) 
+					})
+				}
+			},
+			// 编辑
+			editRow(item){
+				this.$store.state.vuex_tempData = item
+				uni.navigateTo({
+					url: "/pages/batchShelves/editShelfHw?shelfSn="+this.shelfSn+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn
+				})
+			},
+			// 获取产品列表
+			getList(flag){
+				uni.showLoading({
+					mask: true,
+					title: '正在加载...'
+				})
+				this.loading = true
+				queryMapList({ shelfSn: this.shelfSn }).then(res => {
+				  console.log(res.data)
+				  uni.hideLoading()
+				  this.loading = false
+				  if (res.status == 200 && res.data) {
+				    this.shelfPlaceList = JSON.stringify(res.data) == '{}' ? null : res.data
+					// 获取层
+					for(let a in res.data){
+						this.placeTab.push(a)
+					}
+					this.placeTab.sort(function(a,b){ return (a+'').localeCompare(b+'');});
+					console.log(this.placeTab)
+					
+					if(!this.curTab&&this.placeTab.length){
+					  this.curTab = this.placeTab[0]
+					}else{
+						if(!this.shelfPlaceList[this.curTab]){
+							this.curTab = this.placeTab[0]
+						}
+					}
+					if(this.placeTab.length == 0){
+						this.shelfPlaceList = null
+						this.curTab = ''
+					}
+				  } else {
+				    this.shelfPlaceList = null
+					this.placeTab = []
+					this.curTab = ''
+				  }
+				})
+			},
+			// 获取统计数据
+			getCount(){
+				this.totalKs = 0
+				this.totalNums = 0
+				queryCountList({shelfSn: this.shelfSn}).then(res => {
+					if(res.status == 200){
+						this.countData = res.data
+						// 计算合计
+						this.countData.map(item => {
+							this.totalKs += item.category||0
+							this.totalNums += item.qty||0
+						})
+					}
+				})
+			},
+			// 删除
+			shelfCartDelete(row){
+				const _this = this
+				clzConfirm({
+				  title: '提示',
+				  content: '确认删除此货位和产品吗?',
+				  success (ret) {
+						if (ret.confirm || ret.index == 0) {
+							uni.showLoading({
+								mask: true,
+								title: '正在删除...'
+							})
+							shelfCartDelete({ shelfCartSn: row.shelfCartSn }).then(res => {
+							  if (res.status == 200) {
+								  _this.toashMsg(res.message)
+								  _this.pageInit(true)
+							  }
+							  uni.hideLoading()
+							})
+						}else{
+							_this.pageInit(true)
+						}
+				  }
+				})
+			},
+			// 修改数量
+			updateNums(e){
+				console.log(e)
+				const row = this.shelfPlaceList[this.curTab].find(item => item.id == e.index)
+				const nums = e.value
+				
+				// 如果小于1,提示是否删除
+				if(nums<1){
+					this.shelfCartDelete(row)
+					return
+				}
+				// 继续修改数量
+				uni.showLoading({
+					mask: true,
+					title: '正在保存...'
+				})
+				const params = {
+					shelfSn: row.shelfSn,
+					shelfName: this.shelfName,
+					shelfTierCode: row.shelfTierCode,
+					shelfPlaceSn: row.shelfPlaceSn||undefined,
+					shelfPlaceCode: row.shelfPlaceCode,
+					productSn: row.productSn,
+					productCode: row.productCode,
+					qty: nums,
+					price: row.price,
+					cost: row.terminalPrice,
+					shelfCartSn: row.shelfCartSn
+				}
+				console.log(params)
+				shelfCartSave(params).then(res => {
+					if(res.status == 200){
+						this.toashMsg(res.message)
+						this.getCount()
+					}
+					uni.hideLoading()
+				})
+			},
+		}
+	}
+</script>
+
+<style lang="less">
+	.content{
+		width: 100%;
+		height: 100vh;
+		overflow: hidden;
+		.product-list{
+			flex-grow: 1;
+			.leftTabs{
+				width: 20%;
+				height: calc(100vh - 110rpx);
+				.tabbox{
+					> view{
+						padding: 0.8rem 0.5rem;
+						border-left: 0.2rem solid #f8f8f8;
+						text-align: center;
+					}
+					.active{
+						border-color: rgb(47, 126, 209);
+						background-color: #fff;
+						color: rgb(47, 126, 209);
+					}
+				}
+			}
+			.rightCons{
+				width: 80%;
+				background-color: #fff;
+				position: relative;
+				padding: 0 20upx;
+				height: calc(100vh - 110rpx);
+				.partList-list-box{
+					padding: 10px 0;
+					border-bottom: 2rpx solid #f5f5f5;
+					.pinfo{
+						flex-grow: 1;
+						padding-left: 20rpx;
+						.ptxt{
+							color: #666;
+							font-size: 26rpx;
+							text{
+								font-weight: normal;
+								margin-right: 10rpx;
+								padding: 0 10rpx;
+								background: rgba(3, 54, 146, 0.15);
+								border-radius: 30rpx;
+								color: #033692;
+								font-size: 24rpx;
+							}
+							margin-bottom: 15upx;
+						}
+						.pname{
+							color: #666;
+							font-size: 30rpx;
+							font-weight: bold;
+						}
+					}
+					.ptools{
+						color: #666;
+						font-size: 26rpx;
+						margin-top: 20rpx;
+						.u-ninput{
+							border: 2rpx solid #eee;
+							border-radius: 50rpx;
+							padding: 0 6rpx;
+						}
+						/deep/ .u-icon-disabled{
+							background: #fff!important;
+						}
+						/deep/ .u-number-input{
+							margin: 0 0;
+							border: 2rpx solid #eee;
+							border-top: 0;
+							border-bottom: 0;
+						}
+						/deep/ .u-icon-plus, /deep/ .u-icon-minus{
+							border-radius: 50rpx;
+						}
+					}
+				}
+			}
+		}
+		.footer-bar{
+			padding: 20rpx;
+			position: relative;
+			z-index: 200;
+			background-color: #fff;
+			.heji{
+				flex-grow: 1;
+				color: #999;
+				text{
+					color: #333;
+				}
+				font-size: 26rpx;
+				padding-right: 30upx;
+			}
+			.btns{
+				button{
+					width: 200rpx;
+					background-color: rgb(51, 95, 182);
+					color: #fff;
+				}
+			}
+		}
+		.heji-content{
+			padding: 60upx 30upx 100upx;
+		}
+		.heji-con-list{
+			> view{
+				display: flex;
+				align-items: center;
+				border-bottom: 2rpx solid #eee;
+				padding: 18rpx 0;
+				> view{
+					&:first-child{
+						font-weight: normal;
+						padding: 4rpx 15rpx;
+						background: rgba(3, 54, 146, 0.15);
+						border-radius: 10rpx;
+						color: #033692;
+						font-size: 24rpx;
+						margin-right: 30upx;
+					}
+					&:last-child{
+						flex-grow: 1;
+						text{
+							margin-right: 20upx;
+						}
+					}
+				}
+			}
+		}
+		
+		.layer-content{
+			padding: 30upx;
+			.tits{
+				padding: 10upx 0 20upx;
+				text-align: center;
+			}
+			.tagbox{
+				flex-grow: 1;
+				> view{
+					margin: 0 auto;
+					overflow: hidden;
+					width: 100%;
+					.tag{
+						width: 16%;
+						background-color: #fff;
+						border:1rpx solid #aeaeae;
+						box-shadow: 2rpx 4rpx 6rpx #eee;
+						border-radius: 15rpx;
+						text-align: center;
+						padding: 10rpx 0;
+						float: left;
+						margin: 10rpx 2%;
+					}
+					.active{
+						background-color: #55aaff;
+						border-color: #55aaff;
+						color: #fff;
+					}
+				}
+			}
+			.newbtn{
+				padding: 40upx 0 10upx;
+				button{
+					width: 45%;
+				}
+			}
+		}
+	}
+</style>

+ 118 - 0
pages/batchShelves/chooseTypeModal.vue

@@ -0,0 +1,118 @@
+<template>
+	<u-mask class="commonModal" :show="isShow" :mask-click-able="false">
+		<view class="modal-con">
+			<view class="modal-title">上架入库后,货架库存将会增加</view>
+			<view class="modal-main">
+				<view class="modal-p">本次共上架入库<text>{{totalKs}}</text>款产品,共<text>{{totalNums}}</text>件</view>
+				<u-input v-model="form.remarks" placeholder="请输入出库备注(最多500字符)" type="textarea" :maxlength="500" :border="true" :auto-height="false" :custom-style="{height: '100upx'}" />
+			</view>
+			<view class="modal-footer">
+				<view class="button-cancel" @click="isShow=false">取消</view>
+				<view class="button-confirm" @click="handleConfirm">确认上架入库</view>
+			</view>
+		</view>
+	</u-mask>
+</template>
+
+<script>
+	export default {
+		props: {
+			openModal: { //  弹框显示状态
+				type: Boolean,
+				default: false
+			},
+			totalKs: {
+				type: [String,Number],
+				default: '0'
+			},
+			totalNums: {
+				type: [String,Number],
+				default: '0'
+			}
+		},
+		data() {
+			return {
+				isShow: this.openModal, //  是否打开弹框
+				form: {
+				  dispatchType: undefined,
+				  remarks: ''
+				},
+				dispatchTypeList: []
+			}
+		},
+		methods: {
+			// 确认
+			handleConfirm(){
+				this.$emit('confirm', this.form, 0)
+			},
+		},
+		watch: {
+			//  父页面传过来的弹框状态
+			openModal (newValue, oldValue) {
+				this.isShow = newValue
+			},
+			//  重定义的弹框状态
+			isShow (newValue, oldValue) {
+				if (!newValue) {
+					this.$emit('close')
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.commonModal{
+		width: 100%;
+		height: 100%;
+		position: absolute;
+		left: 0;
+		top: 0;
+		z-index: 9999999;
+		.modal-con{
+			width: 78%;
+			margin: 50% auto;
+			background-color: #fff;
+			border-radius: 24upx;
+			padding-top: 30upx;
+			font-size: 30upx;
+			.modal-title{
+				text-align: center;
+				font-size: 26upx;
+				color: #666;
+			}
+			.modal-main{
+				margin: 10upx 30upx 30upx;
+				font-size: 30upx;
+				.modal-p{
+					color: #666;
+					text-align: center;
+					margin-bottom: 20upx;
+					font-size: 26upx;
+					text{
+						color: red;
+					}
+				}
+			}
+			.modal-footer{
+				font-size: 30upx;
+				display: flex;
+				justify-content: space-between;
+				align-items: center;
+				text-align: center;
+				border-top: 1upx solid #E5E5E5;
+				.button-cancel{
+					color: #999;
+					border-right: 1upx solid #E5E5E5;
+					flex-grow: 1;
+					padding: 20upx 0;
+				}
+				.button-confirm{
+					color: #2A86F4;
+					flex-grow: 1;
+					padding: 20upx 0;
+				}
+			}
+		}
+	}
+</style>

+ 294 - 0
pages/batchShelves/editShelfHw.vue

@@ -0,0 +1,294 @@
+<template>
+	<view class="content flex flex_column" v-if="nowData">
+		<view class="form-body">
+			<u-form :model="nowData" label-width="180rpx" :error-type="['toast']" ref="uForm">
+				<view style="padding: 20upx 0;" v-if="nowData.shelfProductApi" >
+					<view class="placeCode">
+						{{nowData.shelfPlaceCode}}
+					</view>
+					<view class="flex flex_1 align_center">
+						<view class="pimgs">
+							<u-image :src="nowData.product.images?nowData.product.images:`../../static/${$config('themePath')}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
+						</view>
+						<view class="pinfo flex_1">
+							<view class="ptxt flex align_center justify_between">
+								<text>{{nowData.productCode}}</text>
+								<text class="pkuc">
+									 可用库存:<text>{{nowData.shelfProductApi.qty}}</text>{{nowData.product.unit}}
+								</text>
+							</view>
+							<view class="pname">
+								{{nowData.product.productName}}
+							</view>
+						</view>
+					</view>
+				</view>
+				<view style="padding: 20upx 0;" v-else>
+					<u-form-item label="货位号" required prop="shelfPlaceCode">
+						<u-input v-model="nowData.shelfPlaceCode" @input="placeCodeBlur" :maxlength="30" placeholder="请输入货位号(字母+数字的格式)"/>
+					</u-form-item>
+					<u-gap height="10" bg-color="#f8f8f8"></u-gap>
+					<u-form-item label="绑定产品" required prop="productSn">
+						<view class="pinfo" style="width: 100%;">
+							<view class="ptxt flex align_center justify_between">
+								<text>{{nowData.productCode}}</text>
+								<text class="pcode" @click="toBindProduct">
+									<u-icon name='reload'></u-icon>
+									更换产品
+								</text>
+							</view>
+						</view>
+					</u-form-item>
+					<u-form-item label="">
+						<view class="flex flex_1 align_center">
+							<view class="pimgs">
+								<u-image :src="nowData.product.images?nowData.product.images:`../../static/${$config('themePath')}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
+							</view>
+							<view class="pinfo flex_1">
+								<view class="pname">
+									{{nowData.product.productName}}
+								</view>
+							</view>
+						</view>
+					</u-form-item>
+				</view>
+				<u-gap height="10" bg-color="#f8f8f8"></u-gap>
+				<u-form-item label="本次上架数量" required prop="qty">
+					<view style="width: 100%;" class="flex justify_end">
+						<view class="u-ninput">
+							<u-number-box :min="1" :max="999999" positive-integer v-model="nowData.qty" color="#000" bg-color="#fff" size="30" :input-height="70" :input-width="150"></u-number-box>
+						</view>
+					</view>
+				</u-form-item>
+			</u-form>
+		</view>
+		<view class="flex footer-btn">
+			<u-button class="delbtn" :loading='loading' @click="handleDel" type='primary' shape="circle" size="medium">删除</u-button>
+			<u-button :style="{width:type=='bind'?'45%':'100%'}" class="newbtn" :loading='loading' @click="formSubmit" type='primary' shape="circle" size="medium">保存</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { clzConfirm, numberToFixed } from '@/libs/tools';
+	import { shelfCartSave, shelfCartDelete} from '@/api/shelfCart.js'
+	export default {
+		data() {
+			return {
+				nowData: {
+					shelfPlaceCode: '',
+					productSn: '',
+					qty: '',
+				},
+				rules: {
+					shelfPlaceCode:[
+						{ required: true, message: '请输入货位号', trigger: 'change' },
+						{
+							pattern: /^[a-zA-Z]{1}[0-9]{1,29}$/g,
+							message: '必须字母开头且后面紧跟数字'
+						}
+					],
+					productSn: [{ required: true, message: '请选择绑定产品', trigger: 'change' }],
+					qty: [{ required: true,type:'number', message: '请输入上架数量', trigger: 'change' }],
+				},
+				shelfSn: null,
+				customerSn: '',
+				shelfName: null,
+				loading: false,
+				type:"",
+			}
+		},
+		// 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
+		onReady() {
+			this.$refs.uForm.setRules(this.rules);
+		},
+		onLoad(opts) {
+			const _this = this
+			this.nowData = JSON.parse(JSON.stringify(this.$store.state.vuex_tempData));
+			console.log(this.nowData)
+			this.shelfName = opts.shelfName
+			this.shelfSn = opts.shelfSn
+			this.customerSn = opts.customerSn
+			this.type = this.nowData.shelfProductApi ? 'edit' : 'new'
+			 
+			// 选在产品
+			uni.$on('addProductToHw',function(data){
+				console.log(data)
+				_this.nowData.product.images = data.productMsg
+				_this.nowData.product.productName = data.name
+				_this.nowData.product.unit = data.unit
+				_this.nowData.price = Number(data.price)
+				_this.nowData.cost = Number(data.cost)
+				_this.nowData.productCode = data.code
+				_this.nowData.productSn = data.productSn
+			})
+		},
+		onUnload(){
+			uni.$off("addProductToHw")
+			this.$store.state.vuex_tempData = null
+		},
+		methods: {
+			placeCodeBlur(v){
+				this.$nextTick(() => {
+					this.nowData.shelfPlaceCode = this.nowData.shelfPlaceCode.toLocaleUpperCase()
+				})
+			},
+			// 更换产品
+			toBindProduct(){
+				uni.navigateTo({
+					url: "/pages/shelfSetting/bindProduct?customerSn="+this.customerSn+"&shelfSn="+this.shelfSn
+				})
+			},
+			// 删除
+			handleDel(){
+				const _this = this
+				clzConfirm({
+				  title: '提示',
+				  content: '确认删除此货位和产品吗?',
+				  success (ret) {
+						if (ret.confirm || ret.index == 0) {
+							uni.showLoading({
+								title: '正在删除...'
+							})
+							shelfCartDelete({ shelfCartSn: _this.nowData.shelfCartSn }).then(res => {
+							  console.log(res)
+							  if (res.status == 200) {
+								  _this.toashMsg(res.message)
+								  uni.navigateBack()
+							  }
+							  uni.hideLoading()
+							})
+						}
+				  }
+				})
+			},
+			//  表单提交
+			formSubmit(){
+				const _this = this
+				this.$refs.uForm.validate(valid => {
+					if (valid) {
+						 const row = _this.nowData
+						 uni.showLoading({
+						 	title: '正在保存...'
+						 })
+						 _this.loading = true
+						 const params = {
+						 	shelfSn: this.shelfSn,
+						 	shelfName: this.shelfName,
+						 	shelfTierCode: row.shelfTierCode,
+						 	shelfPlaceSn: row.shelfPlaceSn||undefined,
+						 	shelfPlaceCode: row.shelfPlaceCode,
+						 	productSn: row.productSn,
+						 	productCode: row.productCode,
+						 	qty: row.qty,
+						 	price: row.price,
+						 	cost: row.terminalPrice,
+						 	shelfCartSn: row.shelfCartSn
+						 }
+						 console.log(params)
+						 shelfCartSave(params).then(res => {
+						 	if(res.status == 200){
+						 		this.toashMsg(res.message)
+								uni.navigateBack()
+						 	}
+						 	uni.hideLoading()
+							_this.loading = false
+						 })
+					} else {
+						console.log('验证失败');
+					}
+				});
+			},
+		}
+	}
+</script>
+
+<style lang="less">
+.content{
+	height: 100vh;
+	width: 100%;
+	.placeCode{
+		text-align: center;
+		border-radius: 20rpx;
+		background-color: #eee;
+		padding: 10upx 20upx;
+		margin-bottom: 15upx;
+	}
+	.form-body{
+		> view{
+			background-color: #fff;
+			padding: 0 1.5rem;
+		}
+		.pimgs{
+			padding:0.1rem;
+			background:#f8f8f8;
+			border-radius:0.3rem;
+			padding-right: 20rpx;
+		}
+		.pinfo{
+			line-height:normal;
+			color: #666;
+			padding-left: 15rpx;
+			.pcode{
+				color:rgb(0, 170, 255);
+			}
+			.pname{
+				font-weight: bold;
+			}
+			.pkuc{
+				width: 200rpx;
+				color: #999;
+				text{
+					color: #333;
+				}
+			}
+		}
+		.noproduct{
+			padding: 40rpx 20rpx;
+			text-align: center;
+			color: #999;
+			>view{
+				padding: 10rpx 0;
+			}
+			text{
+				color: #00aaff;
+				margin-left: 10rpx;
+			}
+		}
+		
+		.u-ninput{
+			border: 2rpx solid #eee;
+			border-radius: 50rpx;
+			padding: 0 6rpx;
+		}
+		/deep/ .u-icon-disabled{
+			background: #fff!important;
+		}
+		/deep/ .u-number-input{
+			margin: 0 0;
+			border: 2rpx solid #eee;
+			border-top: 0;
+			border-bottom: 0;
+		}
+		/deep/ .u-icon-plus, /deep/ .u-icon-minus{
+			border-radius: 50rpx;
+		}
+	}
+	.footer-btn{
+		padding: 2.5rem 1rem 0.5rem;
+		justify-content: space-between;
+		button{
+			min-width: 45%;
+			margin: 0 20upx;
+		}
+		.newbtn{
+			background-color: rgb(51, 95, 182);
+			color: #fff;
+		}
+		.delbtn{
+			background-color: #fff;
+			color: red;
+		}
+	}
+}
+</style>

+ 91 - 0
pages/batchShelves/index.vue

@@ -0,0 +1,91 @@
+<template>
+	<view class="content flex flex_column">
+		<view class="tits">请选择产品的货架层号</view>
+		<view class="tagbox flex">
+			<view>
+				<view class="tag" :class="curTag==item?'active':''" v-for="item in list" :key="item" @click="curTag=curTag==item?'':item">
+					{{item}}层
+				</view>
+			</view>
+		</view>
+		<view class="newbtn flex justify_between" v-if="curTag">
+			<u-button shape="circle" @click="searchProduct()" size="medium">按产品编码搜索</u-button>
+			<u-button @click="scanProduct()" type='primary' shape="circle" size="medium">扫描条形码匹配</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				list:[],
+				curTag: '',
+				shelfSn: '',
+				shelfName: '',
+				customerSn: ''
+			}
+		},
+		onLoad(opts) {
+			this.list = 'A、B、C、D、E、F、G、H、I、J、K、L、M、N、O、P、Q、R、S、T、U、V、W、X、Y、Z'.split('、');
+			this.shelfName = opts.shelfName
+			this.shelfSn = opts.shelfSn
+			this.customerSn = opts.customerSn
+		},
+		methods: {
+			scanProduct(){
+				uni.redirectTo({
+					url: "/pages/batchShelves/scanProduct?shelfSn="+this.shelfSn+'&layer='+this.curTag+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn
+				})
+			},
+			searchProduct(){
+				uni.redirectTo({
+					url: "/pages/batchShelves/searchProduct?shelfSn="+this.shelfSn+'&layer='+this.curTag+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.content{
+		width: 100%;
+		height: 100vh;
+		padding: 20upx;
+		background-color: #fff;
+		.tits{
+			padding: 30upx 0;
+			text-align: center;
+		}
+		.tagbox{
+			flex-grow: 1;
+			> view{
+				margin: 0 auto;
+				overflow: hidden;
+				width: 100%;
+				.tag{
+					width: 16%;
+					background-color: #fff;
+					border:1rpx solid #aeaeae;
+					box-shadow: 2rpx 4rpx 6rpx #eee;
+					border-radius: 15rpx;
+					text-align: center;
+					padding: 10rpx 0;
+					float: left;
+					margin: 20rpx 2%;
+				}
+				.active{
+					background-color: #55aaff;
+					border-color: #55aaff;
+					color: #fff;
+				}
+			}
+		}
+		.newbtn{
+			padding: 30upx;
+			button{
+				width: 45%;
+			}
+		}
+	}
+</style>

+ 154 - 0
pages/batchShelves/printStickerModal.vue

@@ -0,0 +1,154 @@
+<template>
+	<u-mask class="commonModal" :show="isShow" :mask-click-able="false">
+		<view class="modal-con">
+			<view class="modal-title">打印贴签</view>
+			<view class="modal-main">
+				<u-radio-group v-model="printType">
+					<u-radio name="manual">
+						<view class="print-con">
+							<u-image class="item-pic" src="../../static/default/icon_print_manual.png" width="80" height="80"></u-image>
+							<view class="print-main">
+								<text class="print-type">打印【{{layer}}】层</text>
+								<text class="print-exp">打印当前层的所有产品</text>
+							</view>
+						</view>
+					</u-radio>
+					<u-radio name="scan">
+						<view class="print-con">
+							<u-image class="item-pic" src="../../static/default/icon_search.png" width="80" height="80"></u-image>
+							<view class="print-main">
+								<text class="print-type">自选打印</text>
+								<text class="print-exp">按产品编码搜索后进行打印</text>
+							</view>
+						</view>
+					</u-radio>
+				</u-radio-group>
+			</view>
+			<view class="modal-footer">
+				<view class="button-cancel" @click="isShow=false">取消</view>
+				<view class="button-confirm" @click="handleConfirm">确定</view>
+			</view>
+		</view>
+	</u-mask>
+</template>
+
+<script>
+	export default {
+		props: {
+			openModal: { //  弹框显示状态
+				type: Boolean,
+				default: false
+			},
+			layer: {
+				type: String,
+				default:''
+			}
+		},
+		data() {
+			return {
+				isShow: this.openModal, //  是否打开弹框
+				printType: 'manual'
+			}
+		},
+		methods: {
+			// 确认
+			handleConfirm(){
+				this.$emit('confirm', this.printType)
+			}
+		},
+		watch: {
+			//  父页面传过来的弹框状态
+			openModal (newValue, oldValue) {
+				this.isShow = newValue
+			},
+			//  重定义的弹框状态
+			isShow (newValue, oldValue) {
+			  if (!newValue) {
+			    this.$emit('close')
+			  }
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.commonModal{
+		width: 100%;
+		height: 100%;
+		position: absolute;
+		left: 0;
+		top: 0;
+		.modal-con{
+			width: 70%;
+			margin: 50% auto 0;
+			background-color: #fff;
+			border-radius: 24upx;
+			font-size: 26upx;
+			.modal-title{
+				text-align: center;
+				font-size: 30upx;
+				color: #000;
+				padding: 30upx 30upx 0;
+			}
+			.modal-main{
+				margin: 20upx 0 30upx;
+				/deep/ .u-radio{
+					width: 94%!important;
+					flex-direction: row-reverse;
+					justify-content: space-between;
+					margin: 0 3%;
+				}
+				/deep/ .u-radio__icon-wrap{
+					flex-shrink: 0;
+				}
+				/deep/ .u-radio__label{
+					flex-grow: 1;
+					border-bottom: 2upx dashed #E5E5E5;
+					padding: 3% 0;
+				}
+				.print-con{
+					display: flex;
+					justify-content: space-between;
+					align-items: center;
+					.item-pic{
+						flex-shrink: 0;
+						margin-right: 20upx;
+					}
+					.print-main{
+						flex-grow: 1;
+						.print-type{
+							display: block;
+							font-size: 30upx;
+							color: #222;
+						}
+						.print-exp{
+							display: block;
+							font-size: 26upx;
+							color: #666E75;
+							line-height: 40upx;
+						}
+					}
+				}
+			}
+			.modal-footer{
+				font-size: 30upx;
+				display: flex;
+				justify-content: space-between;
+				align-items: center;
+				text-align: center;
+				border-top: 1upx solid #E5E5E5;
+				.button-cancel{
+					color: #999;
+					border-right: 1upx solid #E5E5E5;
+					flex-grow: 1;
+					padding: 20upx 0;
+				}
+				.button-confirm{
+					color: #2A86F4;
+					flex-grow: 1;
+					padding: 20upx 0;
+				}
+			}
+		}
+	}
+</style>

+ 352 - 0
pages/batchShelves/scanProduct.vue

@@ -0,0 +1,352 @@
+<template>
+	<view class="scanCode-wrap">
+		<view class="barCode" id="barcode"></view>
+		<view class="info-body">
+			<view class="info" v-if="productInfo">
+				<view>
+					<view class="shelfPlaceCode">
+						<text v-if="productInfo.shelfCartApi">{{productInfo.shelfCartApi.shelfPlaceCode}}</text>
+						<text v-else-if="productInfo.shelfProductApi">{{productInfo.shelfProductApi.shelfPlaceCode}}</text>
+						<text v-else>{{shelfPlaceCode}}</text>
+					</view>
+					<view class="flex flex_1 align_center">
+						<view class="pimgs">
+							<u-image :src="productInfo.images?productInfo.images:`../../static/${$config('themePath')}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
+						</view>
+						<view class="pinfo flex_1">
+							<view class="ptxt flex align_center justify_between">
+								<view>{{productInfo.code}}</view>
+								<view class="pcode" v-if="productInfo.shelfProductApi">
+									可用库存:
+									<text>{{productInfo.shelfProductApi.qty}}</text>
+									{{productInfo.unit}}
+								</view>
+							</view>
+							<view class="pname">
+								{{productInfo.productName}}
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="product-nums">
+					<view>本次上架数量<text>(左右滑动选择)</text></view>
+					<view class="numsBox flex align_center justify_between">
+						<view class="a-left" @click="numsBoxScroll(0)"><u-icon name="arrow-left"></u-icon></view>
+						<scroll-view class="scroll-nums" scroll-x="true" :scroll-left="scleft">
+							<view class="ntabs-box flex align_center">
+								<view :id="'nums'+item" class="ntabs" @click="saveData(item)" :class="curQty==item?'active':''" v-for="item in 99" :key="item">
+									{{item<10?('&nbsp;'+item+'&nbsp;'):item}}
+								</view>
+							</view>
+						</scroll-view>
+						<view class="a-right" @click="numsBoxScroll(1)"><u-icon name="arrow-right"></u-icon></view>
+					</view>
+				</view>
+				<view class="infoTits" v-if="productInfo.shelfCartApi">产品已录入,请确认数量</view>
+			</view>
+			<view class="noData" v-else>
+				暂无扫描结果
+			</view>
+		</view>
+		<!-- 确认弹框 -->
+		<u-popup v-model="confirmModal" closeable mode="bottom" border-radius="14" width="80%" @close="modalConfirm">
+			<view style="display: flex;flex-direction:column;justify-content: center;padding: 30rpx 30rpx 120rpx;">
+				<view style="margin-top: 40rpx;text-align: center;">没有找到该产品,请重新扫描</view>
+				<view style="color: #999;padding: 30upx 30upx 50upx;text-align: center;">试一试</view>
+				<view style="text-align: center;display: flex;justify-content: space-between;">
+					<u-button style="width: 40%;" type='primary' shape="circle" @click="searchProduct()" size="medium">按产品编码搜索</u-button>
+					<!-- <u-button style="width: 40%;" @click="modalConfirm" type='primary' shape="circle" size="medium">继续扫码</u-button> -->
+				</view>
+			</view>
+		</u-popup>
+	</view>
+</template>
+
+<script>
+	import { queryProduct, shelfCartSave } from '@/api/shelfCart'
+	export default {
+		components: { },
+		data() {
+			return {
+				barcode:null,
+				shelfSn: null,
+				shelfName: '',
+				layer:'',
+				confirmModal: false,
+				productInfo: null,
+				shelfPlaceCode: '',
+				shelfCartSn: '',
+				curQty: '',
+				scleft: 0,
+				fromPage: null,
+				qrCode: '',
+				numsWidth: 52
+			}
+		},
+		onReady() {
+			uni.setNavigationBarTitle({
+				title: '扫描条形码—' +this.layer+'层'
+			})
+			// 设置高度
+			const query = uni.createSelectorQuery().in(this);
+			query.select('#barcode').boundingClientRect(data => {
+				this.barcode.setStyle({
+					width: data.width + 'px',
+					height: data.height	+ 'px'	// 调整扫码控件的位置
+				})
+			}).exec()
+		},
+		onLoad(options) {
+			this.shelfSn = options.shelfSn
+			this.layer = options.layer
+			this.shelfName = options.shelfName
+			this.customerSn = options.customerSn
+			this.fromPage = options.from||''
+			console.log(options)
+			// 初始化摄像头
+			this.init()
+		},
+		onBackPress(e) {
+			if(!this.fromPage){
+				uni.redirectTo({
+					url: "/pages/batchShelves/cartList?shelfSn="+this.shelfSn+'&layer='+this.layer+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn
+				})
+			}else{
+				return false
+			}
+			return true
+		},
+		onNavigationBarButtonTap(e) {
+			 this.searchProduct()
+		},
+		methods: {
+			numsBoxScroll(type){
+				this.scleft = type ? (this.scleft+this.numsWidth*3) : (this.scleft-this.numsWidth*3)
+			},
+			searchProduct(){
+				uni.redirectTo({
+					url: "/pages/batchShelves/searchProduct?shelfSn="+this.shelfSn+'&layer='+this.layer+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn+'&from='+this.fromPage
+				})
+			},
+			// 扫码结果
+			scanResult(){
+				const _this = this
+				uni.showLoading({
+					title: "正在查询产品信息"
+				})
+				let params = {
+					qrCode: this.qrCode,
+					shelfSn: this.shelfSn,
+					shelfTierCode: this.layer
+				}
+				console.log(params)
+				queryProduct(params).then(res => {
+					console.log(res)
+					if(res.status == 200&&res.data&&res.data.productList&&res.data.productList.length){
+						const ret = res.data.productList[0]
+						 this.productInfo = ret
+						 this.shelfPlaceCode = res.data.shelfPlaceCode
+						 // 数量区域宽度
+						 const query = uni.createSelectorQuery().in(_this);
+						 query.select('#nums1').boundingClientRect(data => {
+							 _this.numsWidth = data ? (data.width + 20) : 52
+						 }).exec()
+						 // 已录入
+						 if(ret.shelfCartApi){
+							 this.curQty = ret.shelfCartApi.qty
+							 _this.scleft = (_this.curQty -1) * _this.numsWidth
+						 }else{
+							 this.curQty = ''
+							 this.scleft = 0
+						 }
+						 setTimeout(()=>{
+							 this.barcode.start()
+						 },2000)
+					}else{
+						this.confirmModal = true
+					}
+					uni.hideLoading()
+				})
+			},
+			// 保存
+			saveData(nums){
+				uni.showLoading({
+					title: '正在保存...'
+				})
+				const row = this.productInfo
+				const item = row.shelfCartApi || row.shelfProductApi
+				const params = {
+					shelfSn: this.shelfSn,
+					shelfName: this.shelfName,
+					shelfTierCode: item?item.shelfTierCode:this.layer,
+					shelfPlaceSn: item?item.shelfPlaceSn:undefined,
+					shelfPlaceCode: item?item.shelfPlaceCode:this.shelfPlaceCode,
+					productSn: row.productSn,
+					productCode: row.code,
+					qty: nums,
+					price: row.price,
+					cost: row.terminalPrice,
+					shelfCartSn: item?item.shelfCartSn:undefined
+				}
+				console.log(params)
+				shelfCartSave(params).then(res => {
+					console.log(res)
+					if(res.status == 200){
+						this.toashMsg('保存成功,继续扫描')
+						this.curQty = nums
+						this.scanResult()
+					}
+					setTimeout(()=>{
+						uni.hideLoading()
+					},4000)
+				})
+			},
+			modalConfirm(){
+				this.confirmModal = false
+				this.barcode.start()
+			},
+			startScan(){
+				this.barcode.start()
+			},
+			init(){
+				const _this = this
+				// 初始化
+				this.barcode = plus.barcode.create('barcode', [
+					plus.barcode.QR,
+					plus.barcode.EAN13,
+					plus.barcode.EAN8,
+					plus.barcode.UPCA,
+					plus.barcode.UPCE,
+					plus.barcode.CODABAR,
+					plus.barcode.CODE39,
+					plus.barcode.CODE128,
+					plus.barcode.ITF
+				], {
+					top:'0px',
+					left:'0px',
+					width: '100%',
+					height: '45%',
+					position: 'static',
+					frameColor: '#00aaff',
+					scanbarColor: '#00aaff'
+				})
+				 
+				// 扫码成功后
+				this.barcode.onmarked = function(type, result) {
+					console.log(type,result)
+					_this.qrCode = result
+					_this.scanResult()
+				}
+				// 扫码识别出错
+				this.barcode.onerror = function(error){
+					console.log(error)
+					_this.toashMsg("条形码错误!")
+					_this.barcode.start()
+				}
+				
+				 const currentWebview = this.$mp.page.$getAppWebview()
+				 currentWebview.append(this.barcode)
+				 this.barcode.start()
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	page{
+		height: 100vh;
+	}
+	.scanCode-wrap{
+		width: 100%;
+		height: 100vh;
+		display: flex;
+		flex-direction: column;
+		.barCode{
+			height: 45%;
+		}
+		.info-body{
+			flex-grow: 1;
+			overflow: auto;
+			.noData{
+				padding: 100rpx 20rpx 0;
+				text-align: center;
+				color: #999;
+			}
+			.info{
+				background-color: #FFFFFF;
+				padding: 10rpx 30upx;
+				font-size: 32rpx;
+				margin-top: 20rpx;
+				.shelfPlaceCode{
+					background-color: #f6f6f6;
+					text-align: center;
+					padding: 10rpx 20rpx;
+					border-radius: 50rpx;
+					margin-bottom: 15rpx;
+				}
+				.pimgs{
+					padding:0.1rem;
+					background:#f8f8f8;
+					border-radius:0.3rem;
+				}
+				.pinfo{
+					line-height:normal;
+					padding-left: 20rpx;
+					color: #666;
+					.pcode{
+						color:#999;
+						text{
+							color: #000;
+						}
+					}
+				}
+				
+				.product-nums{
+					border-top: 10rpx solid #eee;
+					margin-top: 20rpx;
+					> view{
+						&:first-child{
+							text-align: center;
+							color: #999;
+							margin-top: 20rpx;
+							text{
+								font-size: 24rpx;
+							}
+						}
+					}
+					.numsBox{
+						.scroll-nums{
+							width: 80%;
+							padding: 10rpx 0;
+							.ntabs-box{
+								margin: 10rpx 0;
+							}
+							.ntabs{
+								background-color: #fff;
+								border:1rpx solid #aeaeae;
+								box-shadow: 2rpx 4rpx 6rpx #eee;
+								border-radius: 15rpx;
+								padding: 10rpx 15rpx;
+								margin: 10rpx 20rpx;
+							}
+							.active{
+								border-color: crimson;
+								background-color: crimson;
+								color: #FFFFFF;
+							}
+							.a-left,.a-right{
+								color: #666;
+							}
+						}
+					}
+				}
+				.infoTits{
+					padding: 30rpx;
+					text-align: center;
+					color: red;
+					font-size: 24rpx;
+				}
+			}
+		}
+	}
+</style>

+ 279 - 0
pages/batchShelves/searchProduct.vue

@@ -0,0 +1,279 @@
+<template>
+	<view class="productList flex flex_column">
+		<view class="productList-search">
+			<view class="search flex align_center">
+				<view class="input">
+					<u-search 
+					v-model="queryWord" 
+					@input="$u.debounce(getProductList, 800)"
+					@custom="$u.debounce(getProductList, 500)" 
+					@search="$u.debounce(getProductList, 500)" 
+					@clear="clearSearch" 
+					bg-color="#fff" 
+					:show-action="false"
+					placeholder="请输入产品编码查询"></u-search>
+				</view>
+				<!-- <view class="icon">
+				</view> -->
+			</view>
+		</view>
+		<view class="productList-body">
+			<view v-if="status == 'loading'"><u-loadmore :status="status" :load-text="loadText" /></view>
+			<view class="partList-list-box" v-for="item in productList" :key="item.shelfCartSn">
+				<view class="flex align_center flex_1">
+					<view class="pimgs">
+						<u-image :src="item.images?item.images:`../../static/${$config('themePath')}/def_img@2x.png`" width="120" height="120" border-radius="10"></u-image>
+					</view>
+					<view class="pinfo">
+						<view class="pname">
+							<text v-if="item.shelfCartApi">{{item.shelfCartApi.shelfPlaceCode}}</text>
+							<text v-else-if="item.shelfProductApi">{{item.shelfProductApi.shelfPlaceCode}}</text>
+							{{item.productName}}
+						</view>
+						<view class="ptxt flex justify_between">
+							<text style="word-break: break-all;">{{item.code}}</text>
+							<view v-if="item.shelfProductApi">
+								可用库存:<text>{{item.shelfProductApi.qty}}</text>{{item.unit}}
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="ptools flex align_center justify_between">
+					<view></view>
+					<view class="pcurnums flex align_center">
+						<view class="u-ninput" v-if="item.shelfCartApi">
+							<u-number-box :long-press="false" :index="item.id" :input-height="60" @blur="updateNums" @minus="updateNums" @plus="updateNums" color="#000" bg-color="#fff" v-model="item.shelfCartApi.qty" :min="1"></u-number-box>
+						</view>
+						<view v-else>
+							<u-button @click="addItem(item)" plain style="height: 50rpx;line-height: 50rpx;" size="mini" shape="circle">
+								<u-icon name="plus"></u-icon> 添加
+							</u-button>
+						</view>
+					</view>
+				</view>
+			</view>
+			<view v-if="productList && productList.length == 0 && status == 'nomore'">
+				<u-empty :text="noDataText" mode="list" :img-width="200" :margin-top="60"></u-empty>
+			</view>
+			<view style="padding: 20upx;" v-if="productList.length && status != 'nomore'">
+				<u-loadmore :status="status" :load-text="loadText" />
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { queryProductPage, shelfCartSave } from '@/api/shelfCart'
+	export default {
+		data() {
+			return {
+				shelfSn: null,
+				shelfName: '',
+				layer:'',
+				queryWord: '',
+				productList: [],
+				total: 0, // 列表总数
+				noDataText: '暂无产品',
+				status: 'nomore',
+				shelfPlaceCode: '',
+				fromPage: null,
+				loadText: {
+					loading: '努力加载中',
+					loadmore: '最多显示前20条匹配产品,请尝试输入更多内容'
+				}
+			}
+		},
+		onLoad(options) {
+			this.shelfSn = options.shelfSn
+			this.layer = options.layer
+			this.shelfName = options.shelfName
+			this.customerSn = options.customerSn
+			this.fromPage = options.from||''
+			console.log(options)
+		},
+		onReady() {
+			uni.setNavigationBarTitle({
+				title: '按产品编码搜索—' +this.layer+'层'
+			})
+		},
+		onBackPress(e) {
+			console.log(e)
+			if(!this.fromPage){
+				uni.redirectTo({
+					url: "/pages/batchShelves/cartList?shelfSn="+this.shelfSn+'&layer='+this.layer+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn
+				})
+			}else{
+				return false
+			}
+			return true
+		},
+		onNavigationBarButtonTap(e) {
+			 this.scanProduct()
+		},
+		methods: {
+			scanProduct(){
+				uni.redirectTo({
+					url: "/pages/batchShelves/scanProduct?shelfSn="+this.shelfSn+'&layer='+this.layer+'&shelfName='+this.shelfName+'&customerSn='+this.customerSn+'&from='+this.fromPage
+				})
+			},
+			clearSearch(){
+				this.queryWord = ''
+				this.productList = []
+				this.getProductList()
+			},
+			getProductList(){
+				const _this = this
+				if(this.queryWord == ''){
+					this.productList = []
+					return
+				}
+				let params = {
+					pageNo:1,
+					pageSize:20,
+					code: this.$u.trim(this.queryWord),
+					shelfSn: this.shelfSn,
+					shelfTierCode: this.layer
+				}
+				console.log(params)
+				this.status = 'loading'
+				queryProductPage(params).then(res => {
+					console.log(res)
+					if(res.status == 200&&res.data&&res.data.page&&res.data.page.list&&res.data.page.list.length){
+						this.productList = res.data.page.list
+						this.shelfPlaceCode = res.data.shelfPlaceCode
+						this.total = res.data.page.count
+						this.status = 'loadmore'
+					}else{
+						this.productList = []
+						this.shelfPlaceCode = ''
+						this.total = 0
+						this.noDataText = '没有搜索到相关产品'
+						this.status = 'nomore'
+					}
+					console.log(this.status)
+				})
+			},
+			// 新增
+			addItem(item){
+				this.saveData(item,1)
+			},
+			// 修改数量
+			updateNums(e){
+				console.log(e)
+				const row = this.productList.find(item => item.id == e.index)
+				const nums = e.value
+				this.saveData(row,nums)
+			},
+			saveData(row,nums){
+				// 继续修改数量
+				uni.showLoading({
+					title: '正在保存...'
+				})
+				const item = row.shelfCartApi || row.shelfProductApi
+				const params = {
+					shelfSn: this.shelfSn,
+					shelfName: this.shelfName,
+					shelfTierCode: item?item.shelfTierCode:this.layer,
+					shelfPlaceSn: item?item.shelfPlaceSn:undefined,
+					shelfPlaceCode: item?item.shelfPlaceCode:this.shelfPlaceCode,
+					productSn: row.productSn,
+					productCode: row.code,
+					qty: nums,
+					price: row.price,
+					cost: row.terminalPrice,
+					shelfCartSn: item?item.shelfCartSn:undefined
+				}
+				console.log(params)
+				shelfCartSave(params).then(res => {
+					uni.hideLoading()
+					if(res.status == 200){
+						this.toashMsg(res.message)
+						this.getProductList()
+					}
+				})
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+	.productList{
+		width: 100%;
+		height: 100vh;
+		.productList-search{
+			padding: 20rpx 30rpx;
+			background-color: #FFFFFF;
+			.search{
+				padding: 0.1rem;
+				border-radius: 50rpx;
+				border:1rpx solid #eee;
+				.input{
+					flex-grow: 1;
+					padding: 4rpx;
+				}
+				.icon{
+					width: 13%;
+					text-align: center;
+					font-size: 46rpx;
+					color: #999;
+				}
+			}
+		}
+		.productList-body{
+			flex-grow: 1;
+			background-color: #fff;
+			padding: 0 40upx;
+			overflow: auto;
+			.partList-list-box{
+				padding: 10px 0;
+				border-bottom: 2rpx solid #f5f5f5;
+				.pinfo{
+					flex-grow: 1;
+					padding-left: 20rpx;
+					.pname{
+						color: #666;
+						font-size: 26rpx;
+						font-weight: bold;
+						word-break: break-all;
+						text{
+							font-weight: normal;
+							margin-right: 10rpx;
+							padding: 0 10rpx;
+							background: rgba(3, 54, 146, 0.15);
+							border-radius: 30rpx;
+							color: #033692;
+							font-size: 26rpx;
+						}
+					}
+					.ptxt{
+						color: #666;
+						font-size: 26rpx;
+						padding: 10upx 0;
+					}
+				}
+				.ptools{
+					color: #666;
+					font-size: 24rpx;
+					.u-ninput{
+						border: 2rpx solid #eee;
+						border-radius: 50rpx;
+						padding: 0 6rpx;
+					}
+					/deep/ .u-icon-disabled{
+						background: #fff!important;
+					}
+					/deep/ .u-number-input{
+						margin: 0 0;
+						border: 2rpx solid #eee;
+						border-top: 0;
+						border-bottom: 0;
+					}
+					/deep/ .u-icon-plus, /deep/ .u-icon-minus{
+						border-radius: 50rpx;
+					}
+				}
+			}
+		}
+		 
+	}
+</style>

+ 140 - 0
pages/batchShelves/setProductCost.vue

@@ -0,0 +1,140 @@
+<template>
+	<view class="content flex flex_column">
+		<view class="uni-icon-error tits">以下产品需设置结算价(即修理厂的进货价),否则无法上架入库</view>
+		<view class="proudct-body">
+			<view class="partList-list-box" v-for="(item,index) in partList" :key="item.id">
+				<view class="product flex align_center">
+					<view class="flex align_center justify_between">
+						<view class="pimgs">
+							<u-image :src="item.product.images?item.product.images:`../../static/${$config('themePath')}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
+						</view>
+						<view class="pinfo">
+							<view class="pname">
+								<text>{{item.shelfPlaceCode}}</text>
+								{{item.productCode}}
+							</view>
+							<view class="pname pname1">
+								{{item.product.productName}}
+							</view>
+						</view>
+					</view>
+				</view>
+				<view class="pcurnums flex align_center justify_end">
+					<text>结算价</text>
+					<view class="u-ninput">
+						<u-input trim border type="digit" clearable @blur="numberToFixed(item,2,999999)" v-model="item.cost" placeholder="请输入价格,最多两位小数"/>
+					</view>
+				</view>
+			</view>
+		</view>
+		<view class="footer-bar">
+			<u-button type='primary' shape="circle" size="medium" @click="submitForm">设置完成</u-button>
+		</view>
+	</view>
+</template>
+
+<script>
+	import { clzConfirm, numberToFixed } from '@/libs/tools';
+	import {updateBatchById, shelfCartConfirm} from '@/api/shelfCart.js'
+	export default {
+		data() {
+			return {
+				partList:[],
+			}
+		},
+		onLoad() {
+			this.partList = this.$store.state.vuex_tempData
+			this.partList.map(item => {
+				item.cost = ''
+			})
+		},
+		onUnload() {
+			this.$store.state.vuex_tempData = null
+		},
+		methods: {
+			// 小数点后两位
+			numberToFixed: function (item, num, max) {
+				let val = item.cost
+				let ret = numberToFixed(val, num, max)
+				this.$set(item,'cost',Number(ret <= 0 ? '' : ret))
+				this.partList = JSON.parse(JSON.stringify(this.partList))
+			},
+			submitForm(){
+				const hasEmpty = this.partList.filter(item => !item.cost)
+				console.log(hasEmpty)
+				if(hasEmpty.length){
+					this.toashMsg("请输入结算价")
+				}else{
+					uni.showLoading({
+						mask: true,
+						title: '正在设置价格...'
+					})
+					updateBatchById(this.partList).then(res => {
+						uni.hideLoading()
+						if(res.status == 200){
+							uni.$emit("setCostOk")
+							uni.navigateBack()
+						}
+					})
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="less">
+.content{
+	width: 100%;
+	height: 100vh;
+	.tits{
+		padding: 20upx 30upx;
+		color: darkorange;
+		font-size: 24rpx;
+	}
+	.proudct-body{
+		flex-grow: 1;
+		width: 100%;
+		overflow: auto;
+		background-color: #fff;
+		padding: 0 20upx;
+	}
+	.partList-list-box{
+		padding: 10px 0;
+		border-bottom: 2rpx solid #f5f5f5;
+		.product{
+			flex-grow: 1;
+			.pinfo{
+				flex-grow: 1;
+				padding-left: 20rpx;
+				.pname{
+					color: #191919;
+					margin-bottom: 5rpx;
+					text{
+						font-weight: normal;
+						margin-right: 10rpx;
+						padding: 0 10rpx;
+						background: rgba(3, 54, 146, 0.15);
+						border-radius: 30rpx;
+						color: #033692;
+						font-size: 24rpx;
+					}
+				}
+			}
+		}
+		.pcurnums{
+			color: #999;
+			.u-ninput{
+				width: 60%;
+				padding: 0 10rpx;
+			}
+		}
+	}
+	.footer-bar{
+		padding: 20upx;
+		button{
+			width: 80%;
+		}
+		text-align: center;
+	}
+}
+</style>

+ 13 - 10
pages/common/partList.vue

@@ -7,13 +7,15 @@
 		<view class="partList-list">
 		<view class="partList-list">
 			<view class="partList-list-box" v-for="item in partList" :key="item.id">
 			<view class="partList-list-box" v-for="item in partList" :key="item.id">
 				<view class="product flex align_center">
 				<view class="product flex align_center">
-					<view class="checkbox" v-if="model == 'checkbox'"><u-checkbox v-model="item.checked" :name="item.id" @change="checkChange" size="40" shape="circle"></u-checkbox></view>
+					<view class="checkbox" v-if="model == 'checkbox'">
+						<u-checkbox v-model="item.checked" :name="item.id" @change="checkChange" size="40" shape="circle"></u-checkbox>
+					</view>
 					<view class="flex align_center flex_1">
 					<view class="flex align_center flex_1">
-						<view class="pimgs">
-							<u-image :src="item.product&&item.product.productMsg?item.product.productMsg:`../../static/${theme}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
+						<view class="pimgs" @click="checkChange({name:item.id})">
+							<u-image :src="item.product&&item.product.productMsg?item.product.productMsg:`../../static/${$config('themePath')}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
 						</view>
 						</view>
 						<view class="pinfo">
 						<view class="pinfo">
-							<view class="pname">
+							<view class="pname" @click="checkChange({name:item.id})">
 								<text v-if="item.shelfPlaceCode">
 								<text v-if="item.shelfPlaceCode">
 									{{item.shelfPlaceCode}}
 									{{item.shelfPlaceCode}}
 								</text>
 								</text>
@@ -24,7 +26,8 @@
 									<text class="pcode">{{item.product&&item.product.code?item.product.code:'--'}}</text>
 									<text class="pcode">{{item.product&&item.product.code?item.product.code:'--'}}</text>
 								</view>
 								</view>
 								<view v-if="pageType=='replenishmentSign'||pageType=='manualPrint'||pageType=='scanCodePrint'">
 								<view v-if="pageType=='replenishmentSign'||pageType=='manualPrint'||pageType=='scanCodePrint'">
-									实发数量:<text class="pnums">{{item.confirmQty||item.confirmQty==0?item.confirmQty:'--'}}{{item.product&&item.product.unit?item.product.unit:'--'}}</text>
+									{{item.billState == 'FINISH'?'签收数量':'实发数量'}}:
+									<text class="pnums">{{item.confirmQty||item.confirmQty==0?item.confirmQty:'--'}}{{item.product&&item.product.unit?item.product.unit:'--'}}</text>
 								</view>
 								</view>
 								<view v-if="pageType=='replenishmentOut'">
 								<view v-if="pageType=='replenishmentOut'">
 									x<text class="pnums">{{item.confirmQty||item.confirmQty==0?item.confirmQty:'--'}}</text>
 									x<text class="pnums">{{item.confirmQty||item.confirmQty==0?item.confirmQty:'--'}}</text>
@@ -64,13 +67,13 @@
 					<view class="pcurnums flex align_center" v-if="pageType=='recall'">
 					<view class="pcurnums flex align_center" v-if="pageType=='recall'">
 						<text>实退数量</text>
 						<text>实退数量</text>
 						<view class="u-ninput">
 						<view class="u-ninput">
-							<u-number-box color="#000" bg-color="#fff" v-model="item.confirmQty" :min="1" :max="item.qty"></u-number-box>
+							<u-number-box color="#000" :input-height="60" bg-color="#fff" v-model="item.confirmQty" :min="1" :max="item.qty"></u-number-box>
 						</view>
 						</view>
 					</view>
 					</view>
 					<view class="pcurnums flex align_center" v-if="pageType=='manualPrint'">
 					<view class="pcurnums flex align_center" v-if="pageType=='manualPrint'">
 						<text>打印数量</text>
 						<text>打印数量</text>
 						<view class="u-ninput">
 						<view class="u-ninput">
-							<u-number-box color="#000" bg-color="#fff" v-model="item.printQty" :min="1" :max="item.confirmQty"></u-number-box>
+							<u-number-box color="#000" :input-height="60" bg-color="#fff" v-model="item.printQty" :min="1" :max="item.confirmQty"></u-number-box>
 						</view>
 						</view>
 					</view>
 					</view>
 				</view>
 				</view>
@@ -80,7 +83,7 @@
 					<view class="pcurnums flex align_center" v-if="pageType=='replenishmentSign'">
 					<view class="pcurnums flex align_center" v-if="pageType=='replenishmentSign'">
 						<text>入库数量</text>
 						<text>入库数量</text>
 						<view class="u-ninput">
 						<view class="u-ninput">
-							<u-number-box color="#000" bg-color="#fff" v-model="item.putQty" @change="numberChange" :min="0" :max="item.confirmQty"></u-number-box>
+							<u-number-box color="#000" :input-height="60" bg-color="#fff" v-model="item.putQty" @change="numberChange" :min="0" :max="999999"></u-number-box>
 						</view>
 						</view>
 					</view>
 					</view>
 				</view>
 				</view>
@@ -124,6 +127,7 @@
 			list(newValue, oldValue) {
 			list(newValue, oldValue) {
 				const _this = this
 				const _this = this
 				this.totalNums = 0
 				this.totalNums = 0
+				this.pageType = this.fromPage
 				newValue.map(item => {
 				newValue.map(item => {
 					if(_this.pageType=='replenishmentSign'){  // 补货签收
 					if(_this.pageType=='replenishmentSign'){  // 补货签收
 						this.totalNums = this.totalNums + item.confirmQty
 						this.totalNums = this.totalNums + item.confirmQty
@@ -147,7 +151,6 @@
 					item.checked = false
 					item.checked = false
 				})
 				})
 				this.partList = JSON.parse(JSON.stringify(newValue))
 				this.partList = JSON.parse(JSON.stringify(newValue))
-				this.pageType = this.fromPage
 			}
 			}
 		},
 		},
 		onLoad() {
 		onLoad() {
@@ -263,7 +266,7 @@
 			}
 			}
 		}
 		}
 		.ptools{
 		.ptools{
-			margin-top: 20rpx;
+			margin-top: 30rpx;
 			.pcurnums{
 			.pcurnums{
 				> text{
 				> text{
 					margin-right: 20rpx;
 					margin-right: 20rpx;

+ 77 - 15
pages/common/printTag/printTag.vue

@@ -1,31 +1,42 @@
 <template>
 <template>
 	<view class="printTag">
 	<view class="printTag">
+		<u-alert-tips :show="show" @close="show = false" type="warning" description="正在打印中,请勿息屏或退出应用!"></u-alert-tips>
 		<view class="print-nums flex flex_column align_center justify_center">
 		<view class="print-nums flex flex_column align_center justify_center">
 			<view>打印数量</view>
 			<view>打印数量</view>
 			<view class="u-ninput">
 			<view class="u-ninput">
 				<u-number-box :min="1" v-model="printNum" color="#000" bg-color="#fff" size="30" :input-height="70" :input-width="100"></u-number-box>
 				<u-number-box :min="1" v-model="printNum" color="#000" bg-color="#fff" size="30" :input-height="70" :input-width="100"></u-number-box>
 			</view>
 			</view>
 		</view>
 		</view>
+		<view class="print-radio" v-if="fromPage == 'bdtq'">
+			<u-radio-group v-model="numType" @change="qtyChange">
+				<u-radio :name="1">按当前库存打印</u-radio>
+				<u-radio :name="2">按最大库容打印</u-radio>
+			</u-radio-group>
+		</view>
 		<view class="shelf-info">
 		<view class="shelf-info">
 			<view class="shelf-info-title">
 			<view class="shelf-info-title">
-				<view>{{infoData&&infoData.shelfName || '--'}}</view>
+				<view class="shelf-name">{{infoData&&infoData.shelfName || '--'}}</view>
 				<view class="pno">{{infoData&&infoData.shelfPlaceCode}}</view>
 				<view class="pno">{{infoData&&infoData.shelfPlaceCode}}</view>
 			</view>
 			</view>
-			<view>产品编码:{{fromPage == 'smdy'?infoData.productCode : infoData.productEntity&&infoData.productEntity.code}}</view>
-			<view>产品名称:{{fromPage == 'smdy'?infoData.productName : infoData.productEntity&&infoData.productEntity.productName}}</view>
-			<view>{{fromPage == 'smdy'?'实发':'库存'}}数量:{{fromPage == 'smdy'?infoData.confirmQty : infoData.qty}}</view>
+			<view class="shelf-info-body">
+				<view>产品编码:{{fromPage == 'smdy'?infoData.productCode : infoData.productEntity&&infoData.productEntity.code}}</view>
+				<view>产品名称:{{fromPage == 'smdy'?infoData.productName : infoData.productEntity&&infoData.productEntity.productName}}</view>
+				<view>{{fromPage == 'smdy'?'实发数量':'当前库存'}}:{{fromPage == 'smdy'?infoData.confirmQty : infoData.qty}}{{infoData.productEntity&&infoData.productEntity.unit}}</view>
+				<view v-if="fromPage == 'bdtq'">最大库容:{{infoData.maxQty}}{{infoData.productEntity&&infoData.productEntity.unit}}</view>
+			</view>
 		</view>
 		</view>
 		<view class="buttons flex align_center justify_center">
 		<view class="buttons flex align_center justify_center">
 			<view v-if="fromPage == 'bdtq'"><u-button @click="cancel" shape="circle" plain>返回列表</u-button></view>
 			<view v-if="fromPage == 'bdtq'"><u-button @click="cancel" shape="circle" plain>返回列表</u-button></view>
 			<view v-if="fromPage == 'smdy'"><u-button @click="cancel" shape="circle" plain>重新扫描</u-button></view>
 			<view v-if="fromPage == 'smdy'"><u-button @click="cancel" shape="circle" plain>重新扫描</u-button></view>
 			<view>
 			<view>
-				<kk-printer ref="kkprinter" @startPrint="startPrint"></kk-printer>
+				<kk-printer @closeConnect="closeConnect" ref="kkprinter" @startPrint="startPrint"></kk-printer>
 			</view>
 			</view>
 		</view>
 		</view>
 	</view>
 	</view>
 </template>
 </template>
 
 
 <script>
 <script>
+	import { clzConfirm, numberToFixed } from '@/libs/tools';
 	import { shelfDetail } from '@/api/shelf'
 	import { shelfDetail } from '@/api/shelf'
 	import kkPrinter from '@/components/kk-printer/index.vue';
 	import kkPrinter from '@/components/kk-printer/index.vue';
 	import {printTempl} from '@/libs/printTools.js'
 	import {printTempl} from '@/libs/printTools.js'
@@ -36,20 +47,26 @@
 		},
 		},
 		data() {
 		data() {
 			return {
 			return {
+				show: false,
 				infoData: null,
 				infoData: null,
 				fromPage: '',
 				fromPage: '',
 				printInfo: null,
 				printInfo: null,
-				printNum: 0,
-				isParinting: false
+				printNum: 1,
+				isParinting: false,
+				numType: 1
 			}
 			}
 		},
 		},
 		onLoad(options) {
 		onLoad(options) {
 			const _this = this
 			const _this = this
 			_this.fromPage = options.page
 			_this.fromPage = options.page
-			_this.infoData = options.data ? JSON.parse(options.data) : {},
+			_this.infoData = options.data ? JSON.parse(options.data) : {};
 			_this.printNum = _this.fromPage == 'smdy' ? _this.infoData.confirmQty : _this.infoData.qty
 			_this.printNum = _this.fromPage == 'smdy' ? _this.infoData.confirmQty : _this.infoData.qty
 			_this.printNum = _this.printNum||1
 			_this.printNum = _this.printNum||1
 			console.log(_this.infoData)
 			console.log(_this.infoData)
+			// 保持屏幕常亮
+			uni.setKeepScreenOn({
+				keepScreenOn: true
+			});
 		},
 		},
 		onUnload() {
 		onUnload() {
 			// this.$refs.kkprinter.closeConnect()
 			// this.$refs.kkprinter.closeConnect()
@@ -57,15 +74,29 @@
 			this.infoData = null
 			this.infoData = null
 			this.printInfo = null
 			this.printInfo = null
 			this.fromPage = ''
 			this.fromPage = ''
+			// 保持屏幕常亮
+			uni.setKeepScreenOn({
+				keepScreenOn: false
+			});
 		},
 		},
 		// 监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack
 		// 监听页面返回,返回 event = {from:backbutton、 navigateBack} ,backbutton 表示来源是左上角返回按钮或 android 返回键;navigateBack表示来源是 uni.navigateBack
 		onBackPress(event){
 		onBackPress(event){
 			if(event.from == 'backbutton'){
 			if(event.from == 'backbutton'){
-				this.cancel()
+				if(this.isParinting){
+					uni.showToast({
+						icon:'none',
+						title: '正在打印中...'
+					})
+				}else{
+					this.cancel()
+				}
 				return true  // 阻止默认返回行为(会导致无限循环)
 				return true  // 阻止默认返回行为(会导致无限循环)
 			}
 			}
 		},
 		},
 		methods: {
 		methods: {
+			qtyChange(v){
+				this.printNum = v == '1' ? this.infoData.qty : this.infoData.maxQty
+			},
 			cancel(){
 			cancel(){
 				if(this.fromPage == 'bdtq'){  // 补打贴签
 				if(this.fromPage == 'bdtq'){  // 补打贴签
 					uni.navigateBack({delta: 1})
 					uni.navigateBack({delta: 1})
@@ -107,6 +138,10 @@
 				}
 				}
 				console.log('printInfo-----------',_this.printInfo)
 				console.log('printInfo-----------',_this.printInfo)
 			},
 			},
+			closeConnect(){
+				this.isParinting = false
+				uni.hideLoading()
+			},
 			// 打印
 			// 打印
 			startPrint(opt,tsc,blesdk){
 			startPrint(opt,tsc,blesdk){
 				console.log(opt,'opt')
 				console.log(opt,'opt')
@@ -123,14 +158,24 @@
 					return
 					return
 				}
 				}
 				this.isParinting = true
 				this.isParinting = true
+				this.show = true
 				const command = printTempl(tsc,this.printInfo)
 				const command = printTempl(tsc,this.printInfo)
 				blesdk.senBlData(opt.deviceId, opt.serviceId, opt.writeId, command.getData(), this.onPrintSuccess);
 				blesdk.senBlData(opt.deviceId, opt.serviceId, opt.writeId, command.getData(), this.onPrintSuccess);
 			},
 			},
 			// 打印成功
 			// 打印成功
 			onPrintSuccess(){
 			onPrintSuccess(){
-				// uni.navigateBack()
 				this.$refs.kkprinter.onPrintSuccess()
 				this.$refs.kkprinter.onPrintSuccess()
 				this.isParinting = false
 				this.isParinting = false
+				this.show = false
+				clzConfirm({
+				  title: '提示',
+				  content: '打印已经结束,是否返回上页!',
+				  success (ret) {
+					if (ret.confirm || ret.index == 0) {
+						uni.navigateBack()
+					} 
+				  }
+				})
 			}
 			}
 		}
 		}
 	}
 	}
@@ -142,7 +187,7 @@
 	width: 100vh;
 	width: 100vh;
 	padding: 50rpx 30rpx;
 	padding: 50rpx 30rpx;
 	.print-nums{
 	.print-nums{
-		padding: 50rpx 30rpx;
+		padding: 50rpx 30rpx 10rpx;
 		color: #999;
 		color: #999;
 		font-size: 32rpx;
 		font-size: 32rpx;
 		> view{
 		> view{
@@ -166,23 +211,40 @@
 			border-radius: 50rpx;
 			border-radius: 50rpx;
 		}
 		}
 	}
 	}
+	.print-radio{
+		padding: 20rpx 20rpx 50rpx;
+		text-align: center;
+	}
 	.shelf-info{
 	.shelf-info{
 		background-color: #f8f8f8;
 		background-color: #f8f8f8;
-		padding: 30rpx;
 		border-radius: 12rpx;
 		border-radius: 12rpx;
 		color: #707070;
 		color: #707070;
 		.shelf-info-title{
 		.shelf-info-title{
-			font-size: 32rpx;
+			font-size: 30rpx;
 			color: #222222;
 			color: #222222;
 			display: flex;
 			display: flex;
 			justify-content: space-between;
 			justify-content: space-between;
-			margin-bottom: 10rpx;
+			border-bottom: 1rpx solid #eee;
+			padding: 15rpx 30rpx;
+			font-weight: bold;
+			.shelf-name{
+				flex:1;
+				margin-right: 10rpx;
+			}
 			.pno{
 			.pno{
 				background: rgba(3, 54, 146, 0.15);
 				background: rgba(3, 54, 146, 0.15);
 				border-radius: 100rpx;
 				border-radius: 100rpx;
-				padding: 4rpx 20rpx;
+				padding: 0 20rpx;
 				color: #033692;
 				color: #033692;
 				font-size: 26rpx;
 				font-size: 26rpx;
+				height: 40rpx;
+				margin-top:5rpx;
+			}
+		}
+		.shelf-info-body{
+			padding: 15rpx 30rpx;
+			> view{
+				padding: 5rpx 0;
 			}
 			}
 		}
 		}
 	}
 	}

+ 103 - 46
pages/index/index.vue

@@ -1,57 +1,97 @@
 <template>
 <template>
 	<view class="homePage-container">
 	<view class="homePage-container">
-		 <!-- 数字货架 -->
-		 <div class="panel-box">
-		 	<div class="panel-title"><div class="texts">补货管理</div></div>
-		 	<div class="panel-body"><iconItemsList :list="storageRacksNavList"></iconItemsList></div>
-		 </div>
-		 <!-- 调回管理 -->
-		 <div class="graid-box">
-			 <div class="graid-box-1" @click="toPage('/pages/shuntBackManage/shuntBackList')">
-				 <div class="icon">
-					 <u-icon name="huowu-tuihui" custom-prefix="iscm-icon" size="70"></u-icon>
-				 </div>
-				 <div class="title">调回管理</div>
-				 <div>商品调回记录查询</div>
+		 <view id="tjCons">
+			 <!-- 数字货架 -->
+			 <div class="panel-box" v-if="$hasPermissions('M_ERManage_mobile')">
+			 	<div class="panel-title"><div class="texts">补货管理</div></div>
+			 	<div class="panel-body"><iconItemsList :list="storageRacksNavList"></iconItemsList></div>
 			 </div>
 			 </div>
-			 <div class="graid-box-1" @click="toPage('/pages/latePlay/chooseBulk')">
-				 <div class="icon">
-				 	<u-icon name="icon_remark" custom-prefix="iscm-icon" size="70"></u-icon>
+			 <!-- 调回管理 -->
+			 <div class="graid-box">
+				 <div class="graid-box-1" @click="toPage('/pages/shuntBackManage/shuntBackList')" v-if="$hasPermissions('M_BackToManage_mobile')">
+					 <div class="icon">
+						 <u-icon name="huowu-tuihui" custom-prefix="iscm-icon" size="70"></u-icon>
+					 </div>
+					 <div class="title">调回管理</div>
 				 </div>
 				 </div>
-				 <div class="title">补打贴签</div>
-				 <div>遗漏标签快捷处理</div>
-			 </div>
-			 <div class="graid-box-1" @click="toPage('/pages/approveStore/list')">
-				 <div class="icon">
-				 	<u-icon name="mendianzhuanxiangshenhe" custom-prefix="iscm-icon" size="70"></u-icon>
-					<u-badge type="error" size="mini" :offset="[-5,20]" :count="storeAuthNums"></u-badge>
+				 <div class="graid-box-1" @click="toPage('/pages/latePlay/chooseBulk')" v-if="$hasPermissions('M_printLabel_mobile')">
+					 <div class="icon">
+						<u-icon name="dayin" custom-prefix="iscm-icon" size="65"></u-icon>
+					 </div>
+					 <div class="title">补打贴签</div>
+				 </div>
+				 <div class="graid-box-1" @click="toPage('/pages/shelfSetting/shelfList')" v-if="$hasPermissions('M_shelfSetting_mobile')">
+					 <div class="icon">
+						<u-icon name="ison_shelf" custom-prefix="iscm-icon" size="65"></u-icon>
+					 </div>
+					 <div class="title">货架设置</div>
+				 </div>
+				 <div class="graid-box-1" @click="toPage('/pages/approveStore/list')" v-if="$hasPermissions('M_auditStore_mobile')">
+					 <div class="icon">
+						<u-icon name="mendianzhuanxiangshenhe" custom-prefix="iscm-icon" size="70"></u-icon>
+						<u-badge type="error" size="mini" :offset="[-5,20]" :count="storeAuthNums"></u-badge>
+					 </div>
+					 <div class="title">门店审核</div>
+				 </div>
+				 <div class="graid-box-1" @click="toPage('/pages/stockCheck/shelfList')" v-if="$hasPermissions('M_stockCheck_mobile')">
+					 <div class="icon">
+						<u-icon name="icon_warehousing" custom-prefix="iscm-icon" size="65"></u-icon>
+						<u-badge type="error" size="mini" :offset="[-5,20]" :count="stockCheckNums"></u-badge>
+					 </div>
+					 <div class="title">库存盘点</div>
+				 </div>
+				 <div class="graid-box-1" @click="toPage('/pages/shelfOrder/shelfOrder')" v-if="$hasPermissions('M_shelfOrder_mobile')">
+					 <div class="icon">
+						<u-icon name="icon_order" custom-prefix="iscm-icon" size="65"></u-icon>
+					 </div>
+					 <div class="title">货架订单</div>
 				 </div>
 				 </div>
-				 <div class="title">门店审核</div>
-				 <div>审核门店的认证申请</div>
+				 <!-- <div class="graid-box-1" @click="toPage('/pages/index/printAbc')">
+					 <div class="title">打印ABC</div>
+				 </div> -->
 			 </div>
 			 </div>
-			 <!-- <div class="graid-box-1" @click="toPage('/pages/index/printAbc')">
-				 <div class="title">打印ABC</div>
-				 <div>遗漏标签快捷处理</div>
-			 </div> -->
-		 </div>
+			 <!-- 货架订单 -->
+			 <!-- <view class="sales-list"  v-if="$hasPermissions('M_shelfOrder_mobile')">
+			 	<view class="title">
+			 		<text class="title-name" @click="$refs.salesList.refash()">
+			 			货架订单 
+			 			<u-icon name="reload" color="#2979ff" size="28"></u-icon>
+			 		</text>
+			 		<view class="title-all" @click="toPage('/pages/shelfOrder/shelfOrder')">查看全部<u-icon name="arrow-right" color="rgb(144, 147, 153)" size="28"></u-icon></view>
+			 	</view>
+			 </view> -->
+		 </view>
+		 <!-- 销售单列表 -->
+		 <!-- <listComponent ref="salesList" :height="listHeight"  v-if="$hasPermissions('M_shelfOrder_mobile')" /> -->
 	</view>
 	</view>
 </template>
 </template>
 <script>
 <script>
 	import iconItemsList from '@/components/icon-items-list/icon-items-list.vue';
 	import iconItemsList from '@/components/icon-items-list/icon-items-list.vue';
+	import listComponent from '@/pages/shelfOrder/listComponent.vue'
 	import { shelfReplenishStateCount } from '@/api/shelfReplenish'
 	import { shelfReplenishStateCount } from '@/api/shelfReplenish'
+	import { queryStockCheckWaitStateNum } from '@/api/stockCheck'
 	import { xprhStoreApplyQueryPage } from '@/api/approveStore'
 	import { xprhStoreApplyQueryPage } from '@/api/approveStore'
 	export default {
 	export default {
 		components: {
 		components: {
 			iconItemsList,
 			iconItemsList,
+			listComponent
 		},
 		},
 		data() {
 		data() {
 			return {
 			return {
 				// 数字货架
 				// 数字货架
 				storageRacksNavList: [],
 				storageRacksNavList: [],
 				theme: '',
 				theme: '',
-				storeAuthNums: 0
+				storeAuthNums: 0,
+				stockCheckNums: 0,
+				listHeight: 400
 			}
 			}
 		},
 		},
+		onReady() {
+			const query = uni.createSelectorQuery().in(this);
+			query.select('#tjCons').boundingClientRect(data => {
+			  this.listHeight = Math.floor(data.height-40)
+			}).exec();
+		},
 		onLoad() {
 		onLoad() {
 			// 设置底部tabbar 样式
 			// 设置底部tabbar 样式
 			const theme = getApp().globalData.theme
 			const theme = getApp().globalData.theme
@@ -99,6 +139,7 @@
 		onShow() {
 		onShow() {
 			this.queryByTypeSum()
 			this.queryByTypeSum()
 			this.getStoreNums()
 			this.getStoreNums()
+			this.getStockCheckNums()
 		},
 		},
 		methods:{
 		methods:{
 			toPage(url){
 			toPage(url){
@@ -118,6 +159,11 @@
 				xprhStoreApplyQueryPage({pageNo:1,pageSize:1,auditStatus:'WAIT'}).then(res => {
 				xprhStoreApplyQueryPage({pageNo:1,pageSize:1,auditStatus:'WAIT'}).then(res => {
 					 this.storeAuthNums = res.data.count || 0
 					 this.storeAuthNums = res.data.count || 0
 				})
 				})
+			},
+			getStockCheckNums(){
+				queryStockCheckWaitStateNum().then(res => {
+					 this.stockCheckNums = res.data || 0
+				})
 			}
 			}
 		}
 		}
 	}
 	}
@@ -126,16 +172,19 @@
 <style lang="scss">
 <style lang="scss">
 	.homePage-container {
 	.homePage-container {
 		width: 100%;
 		width: 100%;
-		padding: 30rpx;
+		padding: 0 30rpx;
 		.graid-box{
 		.graid-box{
 			display: flex;
 			display: flex;
 			align-items: center;
 			align-items: center;
+			flex-wrap: wrap;
+			background-color: #ffffff;
+			border-radius: 30upx;
+			padding: 10upx 20upx;
+			box-shadow: 3upx 2upx 6upx #eee;
+			margin-bottom: 20upx;
 			.graid-box-1{
 			.graid-box-1{
-				background-color: #ffffff;
-				border-radius: 30upx;
-				box-shadow: 3upx 2upx 6upx #eee;
-				padding: 30rpx;
-				width: 50%;
+				padding: 20rpx 0;
+				width: 25%;
 				font-size: 24rpx;
 				font-size: 24rpx;
 				color: #424D5E;
 				color: #424D5E;
 				text-align: center;
 				text-align: center;
@@ -149,21 +198,14 @@
 					position: relative;
 					position: relative;
 				}
 				}
 			}
 			}
-			> div{
-				&:first-child{
-					margin-right: 15rpx;
-				}
-				&:last-child{
-					margin-left: 15rpx;
-				}
-			}
 		}
 		}
 		.panel-box {
 		.panel-box {
 			background-color: #ffffff;
 			background-color: #ffffff;
 			border-radius: 30upx;
 			border-radius: 30upx;
 			padding: 10upx 20upx;
 			padding: 10upx 20upx;
 			box-shadow: 3upx 2upx 6upx #eee;
 			box-shadow: 3upx 2upx 6upx #eee;
-			margin-bottom: 30upx;
+			margin-top: 20upx;
+			margin-bottom: 20upx;
 			.panel-title {
 			.panel-title {
 				display: flex;
 				display: flex;
 				align-items: center;
 				align-items: center;
@@ -190,5 +232,20 @@
 				}
 				}
 			}
 			}
 		}
 		}
+		.sales-list{
+			.title{
+				display: flex;
+				align-items: center;
+				justify-content: space-between;
+				.title-name{
+					font-size: 32upx;
+					color: #333;
+					font-weight: 1000;
+				}
+				.title-all{
+					color: rgb(144, 147, 153);
+				}
+			}
+		}
 	}
 	}
 </style>
 </style>

+ 1 - 1
pages/index/printAbc.vue

@@ -2,7 +2,7 @@
 	<view class="replenishment-manualPrint-wrap">
 	<view class="replenishment-manualPrint-wrap">
 		<view class="replenishment-manualPrint-footer">
 		<view class="replenishment-manualPrint-footer">
 			<view>
 			<view>
-				<kk-printer ref="kkprinter" defaultText="开始打印" @startPrint="startPrint"></kk-printer>
+				<kk-printer @closeConnect="closeConnect" ref="kkprinter" defaultText="开始打印" @startPrint="startPrint"></kk-printer>
 			</view>
 			</view>
 		</view>
 		</view>
 	</view>
 	</view>

+ 34 - 14
pages/latePlay/chooseBulk.vue

@@ -2,13 +2,14 @@
 	<view class="moreShelfPart flex flex_column">
 	<view class="moreShelfPart flex flex_column">
 		<view class="moreShelfPart-search">
 		<view class="moreShelfPart-search">
 			<u-search
 			<u-search
-			placeholder="请输入货名称搜索" 
+			placeholder="请输入货名称搜索" 
 			v-model="shelfName" 
 			v-model="shelfName" 
 			:show-action="isGobleSearch" 
 			:show-action="isGobleSearch" 
+			@input="change"
 			@focus="isGobleSearch=true"
 			@focus="isGobleSearch=true"
 			@blur="isGobleSearch=false"
 			@blur="isGobleSearch=false"
-			@custom="getShelfList" 
-			@search="getShelfList" 
+			@custom="search" 
+			@search="search" 
 			@clear="clearSearch"
 			@clear="clearSearch"
 			:action-style="{'color': '#fff', 'font-size': '24upx', 'background-color': '#57a3f3', 'border-radius': '6upx', 'padding': '12upx 0'}">
 			:action-style="{'color': '#fff', 'font-size': '24upx', 'background-color': '#57a3f3', 'border-radius': '6upx', 'padding': '12upx 0'}">
 			</u-search>
 			</u-search>
@@ -25,15 +26,18 @@
 						</view>
 						</view>
 						<view class="item-detail">
 						<view class="item-detail">
 							<text class="item-detail-text">
 							<text class="item-detail-text">
-								{{item.customerEntity&&item.customerEntity.provinceName}}{{item.customerEntity&&item.customerEntity.cityName}}{{item.customerEntity&&item.customerEntity.countyName}}{{item.customerEntity&&item.customerEntity.customerAddr}}
+								地址:{{item.customerEntity&&item.customerEntity.provinceName}}{{item.customerEntity&&item.customerEntity.cityName}}{{item.customerEntity&&item.customerEntity.countyName}}{{item.customerEntity&&item.customerEntity.customerAddr}}
 							</text>
 							</text>
 						</view>
 						</view>
 					</view>
 					</view>
+					<view class="arrow">
+						<u-icon name="arrow-right" color="#969da3" size="28"></u-icon>
+					</view>
 				</view>
 				</view>
 				<view v-if="shelfList&&shelfList.length==0">
 				<view v-if="shelfList&&shelfList.length==0">
-					<u-empty v-if="status!='loading'" :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="240" :text="noDataText" mode="list" :margin-top="50"></u-empty>
+					<u-empty v-if="status!='loading'" :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="180" :text="noDataText" mode="list" :margin-top="50"></u-empty>
 				</view>
 				</view>
-				<view style="padding: 20upx;" v-if="total>pageSize || status=='loading'">
+				<view style="padding: 20upx;" v-else>
 					<u-loadmore :status="status" />
 					<u-loadmore :status="status" />
 				</view>
 				</view>
 			</scroll-view>
 			</scroll-view>
@@ -63,6 +67,14 @@
 		methods: {
 		methods: {
 			clearSearch(){
 			clearSearch(){
 				this.shelfName = ''
 				this.shelfName = ''
+				this.search()
+			},
+			change(v){
+				if(v==''){
+					this.clearSearch()
+				}
+			},
+			search(){
 				this.pageNo = 1
 				this.pageNo = 1
 				this.shelfList = []
 				this.shelfList = []
 				this.getShelfList()
 				this.getShelfList()
@@ -82,12 +94,12 @@
 						let list = res.data.list
 						let list = res.data.list
 						if (list && list.length){
 						if (list && list.length){
 							// 分页 拼接数据
 							// 分页 拼接数据
-							if (_this.pageNo != 1) {
-								_this.shelfList = _this.shelfList ? _this.shelfList.concat(list) : list
-							} else {
-								_this.shelfList = list
+							if(_this.pageNo>1){
+								_this.shelfList = _this.shelfList.concat(res.data.list || [])
+							}else{
+								_this.shelfList = res.data.list || []
 							}
 							}
-							this.total = res.data.count
+							_this.total = res.data.count
 							if (_this.shelfList.length == res.data.count) {
 							if (_this.shelfList.length == res.data.count) {
 								_this.status = 'nomore'
 								_this.status = 'nomore'
 							} else {
 							} else {
@@ -95,10 +107,10 @@
 							}
 							}
 						} else {
 						} else {
 							_this.shelfList = list || []
 							_this.shelfList = list || []
-							this.total = 0
+							_this.total = 0
 							_this.status = 'nomore'
 							_this.status = 'nomore'
 						}
 						}
-						_this.noDataText = '暂无配件'
+						_this.noDataText = '暂无货架'
 					}else{
 					}else{
 						_this.status = 'loadmore'
 						_this.status = 'loadmore'
 						_this.shelfList = []
 						_this.shelfList = []
@@ -149,9 +161,17 @@
 				padding:20upx 10upx;
 				padding:20upx 10upx;
 				border-bottom: 2rpx solid #f5f5f5;
 				border-bottom: 2rpx solid #f5f5f5;
 				display: flex;
 				display: flex;
+				align-items: center;
+				&:active{
+					background: #f8f8f8;
+				}
+				.arrow{
+					text-align: right;
+					padding-left: 20rpx;
+				}
 				.item-info{
 				.item-info{
 					.item-name{
 					.item-name{
-						font-size: 32upx;
+						font-size: 30upx;
 						display: flex;
 						display: flex;
 						align-items: center;
 						align-items: center;
 					}
 					}

+ 272 - 82
pages/latePlay/chooseProduct.vue

@@ -1,20 +1,31 @@
 <template>
 <template>
 	<view class="moreShelfPart flex flex_column">
 	<view class="moreShelfPart flex flex_column">
 		<view class="moreShelfPart-search">
 		<view class="moreShelfPart-search">
-			<u-search
-			placeholder="请输入货位号/产品编码/产品名称搜索" 
-			v-model="queryWord" 
-			:show-action="isGobleSearch" 
-			@focus="isGobleSearch=true" 
-			@blur="isGobleSearch=false"
-			@custom="searchPart" 
-			@search="searchPart" 
-			@clear="clearSearch"
-			:action-style="{'color': '#fff', 'font-size': '24upx', 'background-color': '#57a3f3', 'border-radius': '6upx', 'padding': '12upx 0'}">
-			</u-search>
-			<view class="p-title">
+			<view class="p-title flex align_center">
 				<text></text>
 				<text></text>
-				{{shelfInfo.shelfName}}
+				<view class="shelfName flex">
+					<view>{{shelfInfo.shelfName}}</view>
+				</view>
+				<view class="btns" @click="showTab = true">
+					筛选:({{curTab!='all'?(curTab+'层'):'全部'}})
+					<u-icon size="20" name="arrow-down"></u-icon>
+				</view>
+			</view>
+			<view class="search flex align_center">
+				<view class="input">
+					<u-search 
+					v-model="queryWord" 
+					@custom="getpartList" 
+					@search="getpartList" 
+					@clear="clearSearch" 
+					@input="$u.debounce(changeSearch, 800)"
+					bg-color="#fff" 
+					:show-action="false"
+					placeholder="请输入货位号/产品编码/产品名称搜索"></u-search>
+				</view>
+				<view class="icon" @click="toScan">
+					<u-icon name="scan"></u-icon>
+				</view>
 			</view>
 			</view>
 		</view>
 		</view>
 		<view class="moreShelfPart-body">
 		<view class="moreShelfPart-body">
@@ -27,49 +38,59 @@
 							</view>
 							</view>
 							<view class="pinfo">
 							<view class="pinfo">
 								<view class="pname">
 								<view class="pname">
-									<text>{{item.shelfPlaceCode}}</text>{{item.productEntity&&item.productEntity.productName}}
+									<text>{{item.shelfPlaceCode}}</text>{{item.productCode}}
+								</view>
+								<view class="pname pname1">
+									{{item.productName}}
 								</view>
 								</view>
 								<view class="ptxt flex align_center justify_between">
 								<view class="ptxt flex align_center justify_between">
 									<view>
 									<view>
-										<text class="pcode">{{item.productEntity&&item.productEntity.code}}</text>
+									  最大库容:<text class="pnums">{{item.maxQty}}{{item.productEntity&&item.productEntity.unit}}</text>
+									   / 当前库存:<text class="pnums">{{item.qty}}{{item.productEntity&&item.productEntity.unit}}</text>
 									</view>
 									</view>
-									<view>
-									  库存数量:<text class="pnums">{{item.qty}}{{item.productEntity&&item.productEntity.unit}}</text>
+									<view v-if="item.qty" class="print" @click.stop="print(item)">
+										<u-image :src="`/static/${$config('themePath')}/icon_printer@3x.png`" width="45" height="45"></u-image>
 									</view>
 									</view>
 								</view>
 								</view>
 							</view>
 							</view>
 						</view>
 						</view>
 					</view>
 					</view>
-					<view class="ptools flex align_center justify_between">
-						<view></view>
-						<view class="print" @click="print(item)">
-							<u-image :src="`/static/${$config('themePath')}/icon_printer@3x.png`" width="48" height="48"></u-image>
-						</view>
-					</view>
 				</view>
 				</view>
 				<view v-if="partList&&partList.length==0">
 				<view v-if="partList&&partList.length==0">
 					<u-empty v-if="status!='loading'" :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="240" :text="noDataText" mode="list" :margin-top="50"></u-empty>
 					<u-empty v-if="status!='loading'" :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="240" :text="noDataText" mode="list" :margin-top="50"></u-empty>
 				</view>
 				</view>
-				<view style="padding: 20upx;" v-if="total>pageSize || status=='loading'">
+				<view style="padding: 20upx;" v-if="status!='loadmore'">
 					<u-loadmore :status="status" />
 					<u-loadmore :status="status" />
 				</view>
 				</view>
 			</scroll-view>
 			</scroll-view>
 		</view>
 		</view>
+		<!-- 筛选项 -->
+		<u-popup v-model="showTab" mode="right" width="70%">
+			<view class="tabBox flex flex_column">
+				<view class="tabs">
+					<view class="flex">
+						<view :class="curTab=='all'?'active':''" @click="tabChange('all')">全部层</view>
+						<view :class="item==curTab?'active':'all'" v-for="item in placeTab" :key="item" @click="tabChange(item)">{{item}}层</view>
+					</view>
+				</view>
+			</view>
+		</u-popup>
 	</view>
 	</view>
 </template>
 </template>
 
 
 <script>
 <script>
-	import { getShelfProductList } from '@/api/shelf'
+	import { queryShelfProductList,getProductPlace } from '@/api/shelf'
 	export default {
 	export default {
 		data() {
 		data() {
 			return {
 			return {
 				queryWord: '',
 				queryWord: '',
 				isGobleSearch: false,
 				isGobleSearch: false,
 				partList: [],
 				partList: [],
+				allList: [],
 				pageNo:1,
 				pageNo:1,
-				pageSize: 10,
+				pageSize: 15,
 				total: 0, // 列表总数
 				total: 0, // 列表总数
-				noDataText: '暂无货架',
+				noDataText: '暂无数据',
 				status: 'loading',
 				status: 'loading',
 				vinstatus: 'loading',
 				vinstatus: 'loading',
 				shelfInfo: {
 				shelfInfo: {
@@ -77,6 +98,14 @@
 					shelfName: ''
 					shelfName: ''
 				},
 				},
 				theme: '',
 				theme: '',
+				showTab: false,
+				placeTab: [],
+				curTab: 'all',
+				customBtnStyle: {  //  自定义按钮样式
+					borderColor: this.$config('primaryColor'),
+					backgroundColor: this.$config('primaryColor'),
+					color: '#fff'
+				},
 			}
 			}
 		},
 		},
 		onLoad(options) {
 		onLoad(options) {
@@ -86,74 +115,171 @@
 				shelfName: options.shelfName
 				shelfName: options.shelfName
 			}
 			}
 			this.getpartList()
 			this.getpartList()
+			this.getShelfPlace()
+		},
+		// 批量打印
+		onNavigationBarButtonTap(e) {
+			if(this.queryWord=='' && this.placeTab.length>1){
+				if(this.curTab=='all'){
+					uni.showToast({
+						icon: 'none',
+						title: '请先筛选层,按层批量打印!',
+						duration: 5000
+					})
+					return
+				}
+			}
+			
+			const list = this.allList.filter(item => item.qty>0)
+			this.$store.state.vuex_tempPrintList = list
+			if(this.shelfInfo&&list.length){
+				uni.navigateTo({
+					url: "/pages/shelfSetting/batchPrint?page=bdtq&data="+encodeURIComponent(JSON.stringify(this.shelfInfo)) 
+				})
+			}else{
+				uni.showToast({
+					icon: 'none',
+					title: '没有可打印的产品',
+					duration: 5000
+				})
+			}
 		},
 		},
 		methods: {
 		methods: {
+			getShelfPlace(flag){
+				getProductPlace({ shelfSn: this.shelfInfo.shelfSn }).then(res => {
+				  if (res.status == 200) {
+					for(let a in res.data){
+						this.placeTab.push(a)
+					}
+					if(!flag){
+					  this.curTab = 'all'
+					}
+				  } else {
+				    this.placeTab = []
+				  }
+				})
+			},
+			handleClear(){
+				this.curTab = 'all'
+				this.changeSearch()
+			},
+			// -------------------
 			clearSearch(){
 			clearSearch(){
 				this.queryWord = ''
 				this.queryWord = ''
+				this.changeSearch()
+			},
+			changeSearch(v){
 				this.pageNo = 1
 				this.pageNo = 1
+				this.allList = []
 				this.partList = []
 				this.partList = []
 				this.getpartList()
 				this.getpartList()
 			},
 			},
-			// 搜索配件
-			searchPart(){
-				this.getpartList()
+			tabChange(item){
+				this.curTab=item
+				this.showTab = false
+				this.changeSearch()
 			},
 			},
 			// 获取数字货架列表
 			// 获取数字货架列表
 			getpartList(){
 			getpartList(){
 				const _this = this
 				const _this = this
 				let params = {
 				let params = {
-				    pageNo: this.pageNo,
-				    pageSize: this.pageSize,
 					shelfSn: this.shelfInfo.shelfSn,
 					shelfSn: this.shelfInfo.shelfSn,
-					queryWord: this.queryWord
+					queryWord: this.queryWord,
+					shelfPlaceCodeHead: this.curTab == 'all' ? '' : this.curTab
 				}
 				}
 				_this.status = 'loading'
 				_this.status = 'loading'
-				getShelfProductList(params).then(res => {
+				queryShelfProductList(params).then(res => {
+					console.log(res)
 					uni.hideLoading()
 					uni.hideLoading()
 					if(res.status == 200){
 					if(res.status == 200){
-						let list = res.data.list
-						console.log(list)
+						let list = res.data
 						if (list && list.length){
 						if (list && list.length){
-							// 分页 拼接数据
-							if (_this.pageNo != 1) {
-								_this.partList = _this.partList ? _this.partList.concat(list) : list
-							} else {
-								_this.partList = list
-							}
-							this.total = res.data.count
-							if (_this.partList.length == res.data.count) {
-								_this.status = 'nomore'
-							} else {
-								_this.status = 'loadmore'
-							}
-						} else {
-							_this.partList = list || []
-							this.total = 0
+							_this.allList = list
+							_this.partList = list.slice(0,this.pageSize)
+							_this.total = _this.allList.length
 							_this.status = 'nomore'
 							_this.status = 'nomore'
+						} else {
+							_this.allList = []
+							_this.partList = []
+							_this.status = 'loadmore'
 						}
 						}
-						_this.noDataText = '暂无配件'
+						_this.noDataText = '没有搜索到产品'
 					}else{
 					}else{
 						_this.status = 'loadmore'
 						_this.status = 'loadmore'
 						_this.partList = []
 						_this.partList = []
 						_this.total = 0
 						_this.total = 0
 						_this.noDataText = res.message ? res.message : '网络似乎出错了,请稍后再试'
 						_this.noDataText = res.message ? res.message : '网络似乎出错了,请稍后再试'
 					}
 					}
+					this.showTab = false
 				})
 				})
 			},
 			},
 			// 加载更多
 			// 加载更多
 			onreachBottom () {
 			onreachBottom () {
 				if(this.partList.length < this.total ){
 				if(this.partList.length < this.total ){
-					if(this.isGobleSearch&&this.queryWord==''){
-						return
-					}
-					this.pageNo++
-					this.getpartList()
+					this.pageNo = this.pageNo + 1
+					this.partList = this.allList.slice(0,this.pageSize*this.pageNo)
 				}else{
 				}else{
 					this.status = "nomore"
 					this.status = "nomore"
 				}
 				}
 			},
 			},
 			print(data){
 			print(data){
-				uni.navigateTo({ url: "/pages/common/printTag/printTag?page=bdtq&data="+JSON.stringify(data) })
+				uni.navigateTo({ url: "/pages/common/printTag/printTag?page=bdtq&data="+JSON.stringify(data)})
+			},
+			// 扫描
+			toScan(){
+				this.mpaasScanModule = uni.requireNativePlugin("wss-scan")
+				this.mpaasScanModule.scan(
+				{
+					"scanMode":"Customized",
+					"scanStyle":{
+						"scanFrameSizePlus":{"width":250,"height":250},
+						"scanFrameSize":200,
+						"scanLight":"visible",
+						"scanText":"对准条形码/二维码进行识别",
+						"scanTitle":"扫码打印",
+					}
+				},
+				(result) => {
+					console.log(result)
+					if(result.scanStatus == 1){
+						this.scanResult(result)
+					}
+				})
+			},
+			// 扫描结果
+			scanResult(data){
+				const params = {
+					shelfSn: this.shelfInfo.shelfSn,
+				}
+				// 二维码
+				if(data.scanType == 'QRCODE'){
+					const ret = data.scanValue.split("&")
+					params.queryWord = ret[1] // 产品编码
+				}else{
+					params.qrCode = data.scanValue
+				}
+				queryShelfProductList(params).then(res => {
+					console.log(res)
+					if(res.status == 200){
+						if(res.data&&res.data.length){
+							if(res.data[0].qty){
+								this.print(res.data[0])
+							}else{
+								uni.showToast({
+									icon: "none",
+									title: "产品库存不足,不能打印",
+									duration: 5000
+								})
+							}
+						}else{
+							uni.showToast({
+								icon: "none",
+								title: "产品不属于此货架,请重新扫描",
+								duration: 5000
+							})
+						}
+					}
+				})
 			}
 			}
 		}
 		}
 	}
 	}
@@ -164,23 +290,56 @@
 		width: 100%;
 		width: 100%;
 		height: 100vh;
 		height: 100vh;
 		.moreShelfPart-search{
 		.moreShelfPart-search{
-			padding: 20rpx 20rpx 0;
+			padding: 10rpx 20rpx;
 			background-color: #FFFFFF;
 			background-color: #FFFFFF;
 			border-bottom: 2rpx solid #f5f5f5;
 			border-bottom: 2rpx solid #f5f5f5;
-		}
-		.p-title{
-			padding: 20rpx;
-			display: flex;
-			align-items: center;
-			color: #222;
-			font-size: 32rpx;
-			text{
-				display: block;
-				height: 32rpx;
-				width: 6rpx;
-				background: #0485F6;
-				margin-right: 10rpx;
-				border-radius: 10rpx;
+			
+			.p-title{
+				padding: 0 10rpx;
+				display: flex;
+				align-items: center;
+				color: #222;
+				font-size: 30rpx;
+				> text{
+						display: block;
+						height: 30rpx;
+						width: 6rpx;
+						background: #0485F6;
+						margin-right: 10rpx;
+						border-radius: 10rpx;
+					}
+				.shelfName{
+					flex-grow: 1;
+					font-weight: bold;
+					width: 60%;
+					> view{
+						overflow: hidden;
+						white-space: nowrap;
+						text-overflow: ellipsis;
+					}
+				}
+				.btns{
+					width:200rpx;
+					text-align: right;
+					font-size: 28rpx;
+					color: #0485F6;
+				}
+			}
+			.search{
+				margin-top: 15upx;
+				padding: 0.1rem;
+				border-radius: 50rpx;
+				border:1rpx solid #eee;
+				.input{
+					flex-grow: 1;
+					padding: 4rpx;
+				}
+				.icon{
+					width: 13%;
+					text-align: center;
+					font-size: 46rpx;
+					color: #999;
+				}
 			}
 			}
 		}
 		}
 		.moreShelfPart-body{
 		.moreShelfPart-body{
@@ -188,7 +347,7 @@
 			background-color: #fff;
 			background-color: #fff;
 		}
 		}
 		.nav-right{
 		.nav-right{
-			height: calc(100vh - 180rpx);
+			height: calc(100vh - 160rpx);
 			box-sizing: border-box;
 			box-sizing: border-box;
 			
 			
 			.partList-list-box{
 			.partList-list-box{
@@ -206,20 +365,22 @@
 						flex-grow: 1;
 						flex-grow: 1;
 						padding-left: 20rpx;
 						padding-left: 20rpx;
 						.pname{
 						.pname{
-							font-size: 32rpx;
 							color: #191919;
 							color: #191919;
-							font-weight: bold;
 							margin-bottom: 10rpx;
 							margin-bottom: 10rpx;
 							text{
 							text{
 								font-weight: normal;
 								font-weight: normal;
 								margin-right: 6rpx;
 								margin-right: 6rpx;
-								padding: 0 10rpx;
+								padding: 0 20rpx;
 								background: rgba(3, 54, 146, 0.15);
 								background: rgba(3, 54, 146, 0.15);
 								border-radius: 100rpx;
 								border-radius: 100rpx;
 								color: #033692;
 								color: #033692;
-								font-size: 28rpx;
+								font-size: 24rpx;
 							}
 							}
 						}
 						}
+						.pname1{
+							font-weight: bold;
+							font-size: 32rpx;
+						}
 						.pno{
 						.pno{
 							background-color: rgba(3, 54, 146, 0.15);
 							background-color: rgba(3, 54, 146, 0.15);
 							border-radius: 50rpx;
 							border-radius: 50rpx;
@@ -237,13 +398,42 @@
 						}
 						}
 					}
 					}
 				}
 				}
-				.ptools{
-					margin-top: 20rpx;
-					.print{
-						padding: 0 10rpx;
+			}
+		}
+		
+		// 筛选
+		.tabBox{
+			height: 100vh;
+			.tabs{
+				flex-grow: 1;
+				overflow: auto;
+				padding: 20rpx;
+				> view{
+					flex-wrap: wrap;
+					justify-content: space-between;
+					> view{
+						width: 45%;
+						border: 1rpx solid #eee;
+						padding: 15rpx;
+						border-radius: 50rpx;
+						text-align: center;
+						margin-bottom: 15rpx;
+					}
+					.active{
+						border:0;
+						background-color: #0485F6;
+						color: #fff;
 					}
 					}
 				}
 				}
 			}
 			}
+			.btns{
+				display: flex;
+				padding: 20upx;
+				justify-content: space-between;
+				.handle-btn {
+					font-size: 28upx;
+				}
+			}
 		}
 		}
 	}
 	}
 </style>
 </style>

+ 163 - 0
pages/login/apply-trial.vue

@@ -0,0 +1,163 @@
+<template>
+	<view class="apply-wrap">
+		<view class="login-body">
+			<u-form :model="form" :error-type="['toast']" ref="uForm" label-position="top">
+				<u-form-item label="门店名称" required prop="name">
+					<u-input v-model="form.name" maxlength="30" placeholder="请输入门店名称(最多30个字符)"/>
+				</u-form-item>
+				<u-form-item label="门店地址" required prop="addrDetail">
+					<u-input v-model="form.addrDetail" placeholder="请输入门店详细地址"/>
+				</u-form-item>
+				<u-form-item label="手机号码" required prop="contactPhone">
+					<u-input v-model="form.contactPhone" type="number" maxlength="11" placeholder="请输入手机号码"/>
+				</u-form-item>
+				<u-form-item label="姓名" required prop="userName">
+					<u-input v-model="form.userName" maxlength="11" placeholder="请输入姓名"/>
+				</u-form-item>
+			</u-form>
+			<view class="login-form">
+				<view class="form-btn-con">
+					<button class="form-btn" :style="{background:$config('primaryColor')}" @click="formSubmit">提交</button>
+					<text class="apply-btn" @click="goLogin">已有账号?去登录</text>
+				</view>
+			</view>
+		</view>
+	</view>
+</template>
+
+<script>
+	import Address from '@/components/address.vue'
+	import { clzConfirm } from '@/libs/tools.js'
+	import { register } from '@/api/user.js'
+	export default{
+		components: {
+			Address,
+		},
+		data(){
+			return{
+				theme: '',
+				form: {
+					name: '',
+					addrProvince: '',
+					addrCity: '',
+					addrDistrict: '',
+					addrDetail: '',
+					contactPhone: '',
+					userName: '',
+				},
+				rules: {
+					name: [
+						{ 
+							required: true, 
+							message: '请输入门店名称', 
+							// 可以单个或者同时写两个触发验证方式 
+							trigger: ['change','blur'],
+						}
+					],
+					addrDetail: [
+						{
+							required: true, 
+							message: '请输入详细地址', 
+							trigger: 'change'
+						}
+					],
+					contactPhone: [
+						{
+							required: true, 
+							message: '请输入手机号', 
+							trigger: 'change'
+						}
+					],
+					userName: [
+						{
+							required: true, 
+							message: '请输入姓名', 
+							trigger: 'change'
+						}
+					],
+				},
+				areaIdArr: [],  //  省市区id数组
+			}
+		},
+		// 必须要在onReady生命周期,因为onLoad生命周期组件可能尚未创建完毕
+		onReady() {
+			this.$refs.uForm.setRules(this.rules);
+			this.theme = getApp().globalData.theme;
+		},
+		methods: {
+			//  表单提交
+			formSubmit(){
+				this.$refs.uForm.validate(valid => {
+					if (valid) {
+						console.log('验证通过');
+						this.submitData()
+					} else {
+						console.log('验证失败');
+					}
+				});
+			},
+			submitData(){
+				let obj = this.form
+				//  申请试用
+				uni.showLoading({
+					title: '正在提交申请...'
+				})
+				register(obj).then(res => {
+					uni.hideLoading()
+					clzConfirm({
+					    title: '提示',
+					    content: '资料已提交成功,客服会在3个工作日内同您联系。请保持电话畅通,谢谢!',
+						showCancel: false,
+						success: function (ret) {
+					        if (ret.confirm||ret.index==0) {
+								uni.reLaunch({
+									url: '/pages/login/login'
+								})
+					        }
+					    }
+					})
+				})
+			},
+			//  选择省区市
+			areaConfirm(e) {
+				console.log('已选择的省市区', e)
+				this.areaIdArr = [ e.provinceCode, e.cityCode, e.areaCode ]
+				this.form.label = e.label
+			},
+			openAddress(){
+				//  省市区  回显     参数为省市区id数组
+				this.$refs.applyAddress.open(this.areaIdArr)
+			},
+			//  去登录
+			goLogin(){
+				uni.navigateBack()
+			},
+		}
+	}
+</script>
+<style scoped lang="scss">
+	@import './login.scss';
+	.apply-wrap .login-form{
+		padding-top: 40upx;
+		.form-btn-con{
+			margin: 0;
+		}
+	}
+	.apply-wrap .login-body{
+		display: block;
+	}
+	.apply-wrap .authUserYs{
+		padding: 60upx 0 30upx 0;
+	}
+	.getcode-btn {
+		color: #0485F6 !important;
+		border: none !important;
+		background: none !important;
+		font-size: 28upx;
+		margin: 0;
+		padding: 0;
+		&:after{
+			border: none !important;
+		}
+	}
+</style>

+ 1 - 2
pages/login/login.scss

@@ -81,9 +81,8 @@
 				display: block;
 				display: block;
 				text-align: center;
 				text-align: center;
 				margin-top: 30upx;
 				margin-top: 30upx;
-				border: 1upx solid #BBBBBB;
 				padding: 24upx 0;
 				padding: 24upx 0;
-				border-radius: 100upx;
+				border-radius: 120upx;
 			}
 			}
 		}
 		}
 		.forget-pass{
 		.forget-pass{

+ 40 - 5
pages/login/login.vue

@@ -24,6 +24,7 @@
 				</view>
 				</view>
 				<view class="form-btn-con">
 				<view class="form-btn-con">
 					<button class="form-btn" :disabled="isDisabled" :style="{'background':isDisabled?'#e5e5e5':$config('primaryColor')}" form-type="submit">登录</button>
 					<button class="form-btn" :disabled="isDisabled" :style="{'background':isDisabled?'#e5e5e5':$config('primaryColor')}" form-type="submit">登录</button>
+					<text class="apply-btn" v-if="isIos" @click="applyTrial">没有账号?请申请注册</text>
 				</view>
 				</view>
 			</form>
 			</form>
 		</view>
 		</view>
@@ -46,6 +47,7 @@ import { checkVersionToLoadUpdate, setStorageForAppVersion,clzConfirm } from '@/
 import { isvalidNumLetter } from '@/libs/validate.js';
 import { isvalidNumLetter } from '@/libs/validate.js';
 import { login } from '@/api/user.js';
 import { login } from '@/api/user.js';
 import { getSysVersion } from '@/api/data.js'
 import { getSysVersion } from '@/api/data.js'
+import skJGPush from '@/libs/jgPush.js'
 export default {
 export default {
 	data() {
 	data() {
 		return {
 		return {
@@ -57,7 +59,9 @@ export default {
 			isAuthuserYs: false, // 是否同意隐私政策
 			isAuthuserYs: false, // 是否同意隐私政策
 			envTips: '',
 			envTips: '',
 			showEnvTips: false,
 			showEnvTips: false,
-			theme: ''
+			theme: '',
+			isIos: false,
+			messageInfo: null
 		};
 		};
 	},
 	},
 	computed: {
 	computed: {
@@ -65,6 +69,22 @@ export default {
 			return this.form.username == '' || this.form.password == ''
 			return this.form.username == '' || this.form.password == ''
 		}
 		}
 	},
 	},
+	onLoad() {
+		const token = this.$store.state.vuex_token
+		if(token){
+			this.AndroidCheckUpdate(1)
+		}
+		this.isIos = uni.getSystemInfoSync().platform == "ios"
+		
+		// 点击消息
+		uni.$on('openMessage',item =>{
+			this.messageInfo = item
+			this.AndroidCheckUpdate()
+		})
+	},
+	onUnload() {
+		uni.$off('openMessage')
+	},
 	onShow() {
 	onShow() {
 		this.isRemember = this.$store.state.vuex_isRemember;
 		this.isRemember = this.$store.state.vuex_isRemember;
 		this.envTips = getApp().globalData.envTips;
 		this.envTips = getApp().globalData.envTips;
@@ -86,20 +106,30 @@ export default {
 		//#endif
 		//#endif
 	},
 	},
 	methods: {
 	methods: {
+		//  申请试用
+		applyTrial() {
+			uni.navigateTo({
+				url: '/pages/login/apply-trial'
+			});
+		},
 		// 版本更新
 		// 版本更新
-		AndroidCheckUpdate(){
+		AndroidCheckUpdate(type){
 			let _this = this
 			let _this = this
 			let version = getApp().globalData.version
 			let version = getApp().globalData.version
 			uni.showLoading({
 			uni.showLoading({
 				title: '正在登录...'
 				title: '正在登录...'
 			});
 			});
-			getSysVersion({versionType:version.platform=='android'?'ANDROID':'IOS'}).then(ret => {
+			getSysVersion({versionType:uni.getSystemInfoSync().platform == "ios"?'IOS':'ANDROID'}).then(ret => {
 				if(ret.status == 200){
 				if(ret.status == 200){
 					if(ret.data){
 					if(ret.data){
 						this.$store.state.vuex_versionInfo = ret.data || null
 						this.$store.state.vuex_versionInfo = ret.data || null
 						checkVersionToLoadUpdate(ret.data,0,_this.formSubmit)
 						checkVersionToLoadUpdate(ret.data,0,_this.formSubmit)
 					}else{
 					}else{
-						this.formSubmit()
+						if(type){
+							this.toMain();
+						}else{
+							this.formSubmit();
+						}
 					}
 					}
 				}
 				}
 				uni.hideLoading()
 				uni.hideLoading()
@@ -139,11 +169,14 @@ export default {
 			login(_this.form).then(res => {
 			login(_this.form).then(res => {
 				uni.hideLoading();
 				uni.hideLoading();
 				if (res.status == 200) {
 				if (res.status == 200) {
-					console.log(_this.fiterAuthCode(res.data.auth_user))
+					// console.log(_this.fiterAuthCode(res.data.auth_user))
 					_this.$u.vuex('vuex_userData', _this.fiterAuthCode(res.data.auth_user));
 					_this.$u.vuex('vuex_userData', _this.fiterAuthCode(res.data.auth_user));
 					_this.$u.vuex('vuex_token', res.data.access_token);
 					_this.$u.vuex('vuex_token', res.data.access_token);
 					_this.$u.vuex('vuex_authOrgs',res.data.auth_orgs);
 					_this.$u.vuex('vuex_authOrgs',res.data.auth_orgs);
 					getApp().globalData.token = res.data.access_token;
 					getApp().globalData.token = res.data.access_token;
+					console.log(res.data.auth_user)
+					// 设置别名
+					skJGPush.setAlias({'alias':'user_'+ getApp().globalData.buildType +'_' + res.data.auth_user.userid ,'sequence': new Date().getTime()})
 					//登录成功将用户名密码存储到用户本地
 					//登录成功将用户名密码存储到用户本地
 					if (_this.isRemember) {
 					if (_this.isRemember) {
 						//用户勾选“记住密码”
 						//用户勾选“记住密码”
@@ -164,6 +197,8 @@ export default {
 			});
 			});
 		},
 		},
 		toMain() {
 		toMain() {
+			console.log(this.messageInfo)
+			this.$store.state.vuex_tempData = this.messageInfo
 			// 跳转到首页
 			// 跳转到首页
 			uni.switchTab({
 			uni.switchTab({
 				url: '/pages/sales/index'
 				url: '/pages/sales/index'

+ 8 - 8
pages/replenishmentManage/chooseTypeModal.vue

@@ -1,11 +1,11 @@
 <template>
 <template>
 	<u-mask class="commonModal" :show="isShow" :mask-click-able="false">
 	<u-mask class="commonModal" :show="isShow" :mask-click-able="false">
 		<view class="modal-con">
 		<view class="modal-con">
-			<view class="modal-title">选择配送方式</view>
+			<!-- <view class="modal-title">选择配送方式</view> -->
 			<view class="modal-main">
 			<view class="modal-main">
-				<u-radio-group v-model="form.dispatchType" width="50%" style="width: 100%;">
+				<!-- <u-radio-group v-model="form.dispatchType" width="50%" style="width: 100%;">
 					<u-radio v-for="(item, index) in dispatchTypeList" :key="index" :name="item.code">{{item.dispName}}</u-radio>
 					<u-radio v-for="(item, index) in dispatchTypeList" :key="index" :name="item.code">{{item.dispName}}</u-radio>
-				</u-radio-group>
+				</u-radio-group> -->
 				<view style="padding: 20upx 0 16upx;">备注</view>
 				<view style="padding: 20upx 0 16upx;">备注</view>
 				<u-input v-model="form.remarks" placeholder="请输入出库备注(最多500字符)" type="textarea" :maxlength="500" :border="true" :auto-height="false" :custom-style="{height: '100upx'}" />
 				<u-input v-model="form.remarks" placeholder="请输入出库备注(最多500字符)" type="textarea" :maxlength="500" :border="true" :auto-height="false" :custom-style="{height: '100upx'}" />
 			</view>
 			</view>
@@ -37,17 +37,17 @@
 			}
 			}
 		},
 		},
 		mounted() {
 		mounted() {
-			this.getLookUpItem()
+			// this.getLookUpItem()
 		},
 		},
 		methods: {
 		methods: {
 			// 确认
 			// 确认
 			handleConfirm(){
 			handleConfirm(){
 				const _this = this;
 				const _this = this;
 				//  表单校验
 				//  表单校验
-				if (!_this.form.dispatchType) {
-					uni.showToast({ icon: 'none', title: '请选择配送方式' });
-					return;
-				}
+				// if (!_this.form.dispatchType) {
+				// 	uni.showToast({ icon: 'none', title: '请选择配送方式' });
+				// 	return;
+				// }
 				this.$emit('confirm', _this.form)
 				this.$emit('confirm', _this.form)
 			},
 			},
 			// 配送方式
 			// 配送方式

+ 8 - 2
pages/replenishmentManage/confirm.vue

@@ -9,7 +9,7 @@
 					<view class="item-num">
 					<view class="item-num">
 						<view class="num-t">x {{item.qty||item.qty==0?item.qty:'--'}} {{item.product&&item.product.unit?item.product.unit:'--'}}</view>
 						<view class="num-t">x {{item.qty||item.qty==0?item.qty:'--'}} {{item.product&&item.product.unit?item.product.unit:'--'}}</view>
 						<view class="num-v">
 						<view class="num-v">
-							<u-number-box color="#000" bg-color="#fff" v-model="item.confirmQty" @change="handlerChange" :min="0" :max="item.qty"></u-number-box>
+							<u-number-box color="#000" bg-color="#fff" v-model="item.confirmQty" @change="handlerChange" :min="0" :max="999999"></u-number-box>
 						</view>
 						</view>
 					</view>
 					</view>
 				</view>
 				</view>
@@ -17,7 +17,7 @@
 			<u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="240" :text="noDataText" img-width="120" v-if="listdata.length==0 && status!='loading'" mode="list"></u-empty>
 			<u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="240" :text="noDataText" img-width="120" v-if="listdata.length==0 && status!='loading'" mode="list"></u-empty>
 		</scroll-view>
 		</scroll-view>
 		<view class="replenishment-confirm-footer" v-if="listdata.length>0">
 		<view class="replenishment-confirm-footer" v-if="listdata.length>0">
-			<u-button @click="confirmModal=true" type="success" :custom-style="customStyle" hover-class="none" shape="circle">确定补货({{confirmQty}}/{{totalQty}})</u-button>
+			<u-button @click="confirmModal=true" :loading="loading" type="success" :custom-style="customStyle" hover-class="none" shape="circle">确定补货({{confirmQty}}/{{totalQty}})</u-button>
 		</view>
 		</view>
 		<!-- 确认弹框 -->
 		<!-- 确认弹框 -->
 		<common-modal :openModal="confirmModal" content="确认对该数字货架进行补货吗?" confirmText="确认补货" @confirm="modalConfirm" @close="confirmModal=false" />
 		<common-modal :openModal="confirmModal" content="确认对该数字货架进行补货吗?" confirmText="确认补货" @confirm="modalConfirm" @close="confirmModal=false" />
@@ -34,6 +34,7 @@
 		components: { commonModal, stockModal },
 		components: { commonModal, stockModal },
 		data() {
 		data() {
 			return {
 			return {
+				loading: false,
 				listdata: [],
 				listdata: [],
 				status: 'loadmore',
 				status: 'loadmore',
 				noDataText: '暂无数据',
 				noDataText: '暂无数据',
@@ -113,6 +114,7 @@
 					replenishBillNo: this.listdata[0].replenishBillNo,
 					replenishBillNo: this.listdata[0].replenishBillNo,
 					detailList: arr
 					detailList: arr
 				}
 				}
+				this.loading = true
 				// 校验产品库存是否足够
 				// 校验产品库存是否足够
 				shelfReplenishDetailStock(params).then(res => {
 				shelfReplenishDetailStock(params).then(res => {
 					if (res.status == 200) {
 					if (res.status == 200) {
@@ -121,7 +123,9 @@
 							this.paramsData = params
 							this.paramsData = params
 							this.confirmModal = false
 							this.confirmModal = false
 							this.stockModal = true
 							this.stockModal = true
+							this.loading = false
 						} else {
 						} else {
+							this.confirmModal = false
 							this.confirmFun(params)
 							this.confirmFun(params)
 						}
 						}
 					}
 					}
@@ -130,6 +134,7 @@
 			// 提交确认
 			// 提交确认
 			confirmFun (params) {
 			confirmFun (params) {
 				shelfReplenishConfirm(params).then(res => {
 				shelfReplenishConfirm(params).then(res => {
+					this.loading = false
 					if (res.status == 200) {
 					if (res.status == 200) {
 						this.toashMsg(res.message)
 						this.toashMsg(res.message)
 						uni.$emit('refreshBL')
 						uni.$emit('refreshBL')
@@ -143,6 +148,7 @@
 			// 库存不足  confirm
 			// 库存不足  confirm
 			modalStock(params){
 			modalStock(params){
 				this.stockModal = false
 				this.stockModal = false
+				this.loading = true
 				this.confirmFun(params)
 				this.confirmFun(params)
 			}
 			}
 		}
 		}

+ 3 - 6
pages/replenishmentManage/detail.vue

@@ -16,10 +16,10 @@
 					<view class="label"><u-icon name="ison_shelf" custom-prefix="iscm-icon" size="32"></u-icon><text>货架名称</text></view>
 					<view class="label"><u-icon name="ison_shelf" custom-prefix="iscm-icon" size="32"></u-icon><text>货架名称</text></view>
 					<view class="info-txt">{{basicInfoData.shelfInfo&&basicInfoData.shelfInfo.shelfName || '--'}}</view>
 					<view class="info-txt">{{basicInfoData.shelfInfo&&basicInfoData.shelfInfo.shelfName || '--'}}</view>
 				</view>
 				</view>
-				<view v-if="pageType=='success'">
+				<!-- <view v-if="pageType=='success'">
 					<view class="label"><u-icon name="icon_delivery" custom-prefix="iscm-icon" size="32"></u-icon><text>配送方式</text></view>
 					<view class="label"><u-icon name="icon_delivery" custom-prefix="iscm-icon" size="32"></u-icon><text>配送方式</text></view>
 					<view class="info-txt">{{basicInfoData.dispatchTypeDictValue || '--'}}</view>
 					<view class="info-txt">{{basicInfoData.dispatchTypeDictValue || '--'}}</view>
-				</view>
+				</view> -->
 				<view v-if="pageType=='success'">
 				<view v-if="pageType=='success'">
 					<view class="label"><u-icon name="icon_remark" custom-prefix="iscm-icon" size="32"></u-icon><text>出库备注</text></view>
 					<view class="label"><u-icon name="icon_remark" custom-prefix="iscm-icon" size="32"></u-icon><text>出库备注</text></view>
 					<view class="info-txt">{{basicInfoData.remarks || '--'}}</view>
 					<view class="info-txt">{{basicInfoData.remarks || '--'}}</view>
@@ -78,11 +78,8 @@
 			getPartList(){
 			getPartList(){
 				const _this = this
 				const _this = this
 				shelfReplenishDetailList({ replenishBillSn: this.replenishBillSn }).then(res => {
 				shelfReplenishDetailList({ replenishBillSn: this.replenishBillSn }).then(res => {
+					console.log(res.data)
 					if(res.status == 200 && res.data){
 					if(res.status == 200 && res.data){
-						res.data.map(item =>{
-							item.confirmQty = item.confirmQty ? Number(item.confirmQty) : 0
-							item.putQty = item.confirmQty ? Number(item.confirmQty) : 0
-						})
 						this.partList = res.data || []
 						this.partList = res.data || []
 					}else{
 					}else{
 						this.partList = []
 						this.partList = []

+ 55 - 4
pages/replenishmentManage/manualPrint.vue

@@ -11,13 +11,14 @@
 				<u-checkbox size="40" @change="allCheckeChange" v-model="allChecked" shape="circle">{{allChecked?'取消全选':'全选'}}</u-checkbox>
 				<u-checkbox size="40" @change="allCheckeChange" v-model="allChecked" shape="circle">{{allChecked?'取消全选':'全选'}}</u-checkbox>
 			</view>
 			</view>
 			<view>
 			<view>
-				<kk-printer ref="kkprinter" defaultText="开始打印" @startPrint="startPrint"></kk-printer>
+				<kk-printer @closeConnect="closeConnect" ref="kkprinter" defaultText="开始打印" @startPrint="startPrint"></kk-printer>
 			</view>
 			</view>
 		</view>
 		</view>
 	</view>
 	</view>
 </template>
 </template>
 
 
 <script>
 <script>
+	import { clzConfirm, numberToFixed } from '@/libs/tools';
 	import kkPrinter from '@/components/kk-printer/index.vue';
 	import kkPrinter from '@/components/kk-printer/index.vue';
 	import { shelfReplenishDetail, shelfReplenishDetailList, shelfReplenishPrintSign } from '@/api/shelfReplenish'
 	import { shelfReplenishDetail, shelfReplenishDetailList, shelfReplenishPrintSign } from '@/api/shelfReplenish'
 	import partList from '@/pages/common/partList.vue'
 	import partList from '@/pages/common/partList.vue'
@@ -26,11 +27,13 @@
 		components: { partList, kkPrinter },
 		components: { partList, kkPrinter },
 		data() {
 		data() {
 			return {
 			return {
+				show: false,
 				replenishBillSn: '',
 				replenishBillSn: '',
 				basicInfoData:null,
 				basicInfoData:null,
 				partList: [],
 				partList: [],
 				allChecked: false,
 				allChecked: false,
 				printIndex: 0,
 				printIndex: 0,
+				isParinting: false
 			}
 			}
 		},
 		},
 		onReady() {
 		onReady() {
@@ -43,9 +46,30 @@
 			this.replenishBillSn = option.sn
 			this.replenishBillSn = option.sn
 			this.getDetail()
 			this.getDetail()
 			this.getPartList()
 			this.getPartList()
+			// 保持屏幕常亮
+			uni.setKeepScreenOn({
+				keepScreenOn: true
+			});
 		},
 		},
 		onUnload() {
 		onUnload() {
 			// this.$refs.kkprinter.closeConnect()
 			// this.$refs.kkprinter.closeConnect()
+			// 保持屏幕常亮
+			uni.setKeepScreenOn({
+				keepScreenOn: false
+			});
+		},
+		onBackPress(event){
+			if(event.from == 'backbutton'){
+				if(this.isParinting){
+					uni.showToast({
+						icon:'none',
+						title: '正在打印中...'
+					})
+				}else{
+					uni.navigateBack({delta: 1})
+				}
+				return true  // 阻止默认返回行为(会导致无限循环)
+			}
 		},
 		},
 		methods: {
 		methods: {
 			// 查询详情
 			// 查询详情
@@ -64,10 +88,19 @@
 				shelfReplenishDetailList({ replenishBillSn: this.replenishBillSn }).then(res => {
 				shelfReplenishDetailList({ replenishBillSn: this.replenishBillSn }).then(res => {
 					if(res.status == 200 && res.data){
 					if(res.status == 200 && res.data){
 						res.data.map(item =>{
 						res.data.map(item =>{
-							item.confirmQty = item.confirmQty ? Number(item.confirmQty) : 0
-							item.printQty = item.confirmQty ? Number(item.confirmQty) : 0
+							if(item.billState == 'FINISH'){
+								item.confirmQty = item.putQty ? Number(item.putQty) : 0
+								item.printQty = item.confirmQty ? Number(item.confirmQty) : 0
+							}else{
+								item.confirmQty = item.confirmQty ? Number(item.confirmQty) : 0
+								item.printQty = item.confirmQty ? Number(item.confirmQty) : 0
+							}
 						})
 						})
 						this.partList = res.data || []
 						this.partList = res.data || []
+						this.$nextTick(()=>{
+							this.allCheckeChange({value:true})
+							this.allChecked = true
+						})
 					}else{
 					}else{
 						this.partList = []
 						this.partList = []
 					}
 					}
@@ -111,9 +144,23 @@
 						_this.printIndex = 0
 						_this.printIndex = 0
 						_this.$refs.kkprinter.onPrintSuccess()
 						_this.$refs.kkprinter.onPrintSuccess()
 						_this.isParinting = false
 						_this.isParinting = false
+						uni.hideLoading()
+						clzConfirm({
+						  title: '提示',
+						  content: '打印已经结束,是否返回上页!',
+						  success (ret) {
+							if (ret.confirm || ret.index == 0) {
+								uni.navigateBack()
+							} 
+						  }
+						})
 					}
 					}
 				});
 				});
 			},
 			},
+			closeConnect(){
+				this.isParinting = false
+				uni.hideLoading()
+			},
 			// 批量打印 
 			// 批量打印 
 			startPrint(opt,tsc,blesdk){
 			startPrint(opt,tsc,blesdk){
 				const result =this.$refs.partList.getAllChecked()
 				const result =this.$refs.partList.getAllChecked()
@@ -122,6 +169,10 @@
 					 	return
 					 	return
 					 }
 					 }
 					 this.isParinting = true
 					 this.isParinting = true
+					 uni.showLoading({
+					 	mask: true,
+					 	title: '正在打印中,请勿息屏或退出应用!'
+					 })
 					 this.printOnce(opt,tsc,blesdk,result[this.printIndex])
 					 this.printOnce(opt,tsc,blesdk,result[this.printIndex])
 				}else{
 				}else{
 					this.toashMsg("请选择产品!")
 					this.toashMsg("请选择产品!")
@@ -140,7 +191,7 @@
 	overflow: hidden;
 	overflow: hidden;
 	padding-bottom: 102upx;
 	padding-bottom: 102upx;
 	.replenishment-manualPrint-body{
 	.replenishment-manualPrint-body{
-		> view{
+		.part-list{
 			padding: 10rpx 25rpx;
 			padding: 10rpx 25rpx;
 			background-color: #fff;
 			background-color: #fff;
 			margin-bottom: 20rpx;
 			margin-bottom: 20rpx;

+ 2 - 1
pages/replenishmentManage/outWarehousing.vue

@@ -24,7 +24,7 @@
 		</view>
 		</view>
 		<view class="replenishment-outWarehousing-footer">
 		<view class="replenishment-outWarehousing-footer">
 			<u-button class="button" @click="printModal=true" :custom-style="customDefalutStyle" hover-class="none" shape="circle">打印标签</u-button>
 			<u-button class="button" @click="printModal=true" :custom-style="customDefalutStyle" hover-class="none" shape="circle">打印标签</u-button>
-			<u-button class="button" @click="goSendOutGoods" type="success" :custom-style="customStyle" hover-class="none" shape="circle">发货出库</u-button>
+			<u-button class="button" @click="goSendOutGoods" :loading="loading" type="success" :custom-style="customStyle" hover-class="none" shape="circle">发货出库</u-button>
 		</view>
 		</view>
 		<!-- 打印贴签 -->
 		<!-- 打印贴签 -->
 		<print-sticker-modal :openModal="printModal" @confirm="modalPrint" @close="printModal=false" />
 		<print-sticker-modal :openModal="printModal" @confirm="modalPrint" @close="printModal=false" />
@@ -39,6 +39,7 @@
 		components: { partList, printStickerModal },
 		components: { partList, printStickerModal },
 		data() {
 		data() {
 			return {
 			return {
+				loading: false,
 				replenishBillSn: '',
 				replenishBillSn: '',
 				basicInfoData:null,
 				basicInfoData:null,
 				partList: [],
 				partList: [],

+ 47 - 13
pages/replenishmentManage/replenishmentList.vue

@@ -20,10 +20,17 @@
 						</view>
 						</view>
 						<view class="check-col">
 						<view class="check-col">
 							<view>补货单号:{{item.replenishBillNo}}</view>
 							<view>补货单号:{{item.replenishBillNo}}</view>
-							<view v-if="item.billState=='WAIT_CONFIRM' || item.billState=='CANCEL'">应发数量:{{item.totalQty}}</view>
-							<view v-if="item.billState=='WAIT_OUT_STOCK' || item.billState=='WAIT_CHECK'">实发数量:{{item.totalConfirmQty}}</view>
-							<view v-if="item.billState=='FINISH'">入库数量:{{item.totalPutQty}}</view>
-							<view>{{item.createDate}}</view>
+							<view class="flex align_center justify_between">
+								<view v-if="item.billState=='WAIT_CONFIRM' || item.billState=='CANCEL'">应发数量:{{item.totalQty}}</view>
+								<view v-if="item.billState=='WAIT_OUT_STOCK' || item.billState=='WAIT_CHECK'">实发数量:{{item.totalConfirmQty}}</view>
+								<view v-if="item.billState=='FINISH'">入库数量:{{item.totalPutQty}}</view>
+							</view>
+						</view>
+						<view class="ptools flex align_center justify_between">
+							<view><text>{{item.createDate}}</text></view>
+							<view class="print" v-if="item.billState!='CANCEL'&&item.billState!='WAIT_CONFIRM'" @click.stop="print(item)">
+								<u-image :src="`/static/${$config('themePath')}/icon_printer@3x.png`" width="48" height="48"></u-image>
+							</view>
 						</view>
 						</view>
 					 </view>
 					 </view>
 					 <u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="240" :text="noDataText" img-width="120" v-if="list.length==0 && status!='loading'" mode="list"></u-empty>
 					 <u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="240" :text="noDataText" img-width="120" v-if="list.length==0 && status!='loading'" mode="list"></u-empty>
@@ -33,13 +40,16 @@
 				</scroll-view>
 				</scroll-view>
 			</swiper-item>
 			</swiper-item>
 		</swiper>
 		</swiper>
+		<!-- 打印贴签 -->
+		<print-sticker-modal v-if="printModal" :openModal="printModal" @confirm="modalPrint" @close="printModal=false" />
 	</view>
 	</view>
 </template>
 </template>
 
 
 <script>
 <script>
+	import printStickerModal from './printStickerModal.vue'
 	import { shelfReplenishList, shelfReplenishStateCount } from '@/api/shelfReplenish'
 	import { shelfReplenishList, shelfReplenishStateCount } from '@/api/shelfReplenish'
 	export default {
 	export default {
-		components: {},
+		components: {printStickerModal},
 		data() {
 		data() {
 			return {
 			return {
 				status: 'loadmore',
 				status: 'loadmore',
@@ -76,10 +86,12 @@
 				current: 0,
 				current: 0,
 				swiperCurrent: 0,
 				swiperCurrent: 0,
 				pageNo: 1,
 				pageNo: 1,
-				pageSize: 6,
+				pageSize: 15,
 				list: [],
 				list: [],
 				total: 0,
 				total: 0,
 				action:'swiperChange', // 操作类型,上划分页,或左右滑动
 				action:'swiperChange', // 操作类型,上划分页,或左右滑动
+				printModal: false,
+				tempData: null
 			}
 			}
 		},
 		},
 		onLoad(options) {
 		onLoad(options) {
@@ -127,6 +139,7 @@
 						this.swiperCurrent = current
 						this.swiperCurrent = current
 						this.current = current
 						this.current = current
 						this.resetPage()
 						this.resetPage()
+						this.queryByTypeSum(true)
 					}
 					}
 				}
 				}
 			},
 			},
@@ -194,13 +207,15 @@
 				}
 				}
 			},
 			},
 			// 查询每个状态的数据条数
 			// 查询每个状态的数据条数
-			queryByTypeSum () {
+			queryByTypeSum (flag) {
 				shelfReplenishStateCount({}).then(res => {
 				shelfReplenishStateCount({}).then(res => {
 					if (res.data && res.status == 200) {
 					if (res.data && res.status == 200) {
 						this.tabList[1].count = res.data.WAIT_CONFIRM || 0
 						this.tabList[1].count = res.data.WAIT_CONFIRM || 0
 						this.tabList[2].count = res.data.WAIT_OUT_STOCK || 0
 						this.tabList[2].count = res.data.WAIT_OUT_STOCK || 0
 						this.tabList[3].count = res.data.WAIT_CHECK || 0
 						this.tabList[3].count = res.data.WAIT_CHECK || 0
-						this.getRow(1)
+						if(!flag){
+							this.getRow(1)
+						}
 					}
 					}
 				})
 				})
 			},
 			},
@@ -208,7 +223,20 @@
 				const _this = this
 				const _this = this
 				const index = this.tabList.findIndex(item => item.status == tab)
 				const index = this.tabList.findIndex(item => item.status == tab)
 				_this.tabsChange(index)
 				_this.tabsChange(index)
-			}
+			},
+			print(item){
+				this.tempData = item
+				this.printModal=true
+			},
+			// 打印贴签 confirm
+			modalPrint(type){
+				this.printModal = false
+				if(type == 'manual'){  // 手动打印
+					uni.navigateTo({ url: "/pages/replenishmentManage/manualPrint?sn="+this.tempData.replenishBillSn })
+				}else if(type == 'scan'){  // 扫码打印
+					uni.navigateTo({ url: "/pages/replenishmentManage/scanCodePrint?sn="+this.tempData.replenishBillSn })
+				}
+			},
 		}
 		}
 	}
 	}
 </script>
 </script>
@@ -245,8 +273,8 @@
 		// 列表样式
 		// 列表样式
 		.check-order-list{
 		.check-order-list{
 			background: #ffffff;
 			background: #ffffff;
-			padding: 25upx 35upx;
-			margin: 25upx;
+			padding: 20upx 30upx;
+			margin: 20upx;
 			border-radius: 25upx;
 			border-radius: 25upx;
 			box-shadow: 1px 1px 3px #EEEEEE;
 			box-shadow: 1px 1px 3px #EEEEEE;
 			.check-row{
 			.check-row{
@@ -268,8 +296,14 @@
 			.check-col{
 			.check-col{
 				> view{
 				> view{
 					padding: 2rpx 0;
 					padding: 2rpx 0;
-					color: #707070;
-					font-size: 26rpx;
+					font-size: 28rpx;
+					color: #666666;
+				}
+			}
+			.ptools{
+				color: #707070;
+				.print{
+					padding: 0 10rpx;
 				}
 				}
 			}
 			}
 		}
 		}

+ 5 - 1
pages/replenishmentManage/scanCodePrint.vue

@@ -97,7 +97,11 @@
 				shelfReplenishDetailList({ replenishBillSn: this.replenishBillSn }).then(res => {
 				shelfReplenishDetailList({ replenishBillSn: this.replenishBillSn }).then(res => {
 					if(res.status == 200 && res.data){
 					if(res.status == 200 && res.data){
 						res.data.map(item =>{
 						res.data.map(item =>{
-							item.confirmQty = item.confirmQty ? Number(item.confirmQty) : 0
+							if(item.billState == 'FINISH'){
+								item.confirmQty = item.putQty ? Number(item.putQty) : 0
+							}else{
+								item.confirmQty = item.confirmQty ? Number(item.confirmQty) : 0
+							}
 						})
 						})
 						this.partList = res.data || []
 						this.partList = res.data || []
 					}else{
 					}else{

+ 4 - 1
pages/replenishmentManage/sendOutGoods.vue

@@ -14,7 +14,7 @@
 				<u-icon name="scan" size="34"></u-icon>
 				<u-icon name="scan" size="34"></u-icon>
 				点击扫码
 				点击扫码
 			</u-button>
 			</u-button>
-			<u-button v-else @click="handleOutGoods" type="success" :custom-style="customStyle" hover-class="none" shape="circle">立即出库</u-button>
+			<u-button v-else @click="handleOutGoods" :loading="loading" type="success" :custom-style="customStyle" hover-class="none" shape="circle">立即出库</u-button>
 		</view>
 		</view>
 		<!-- 确认弹框 -->
 		<!-- 确认弹框 -->
 		<common-modal v-if="confirmModal" :openModal="confirmModal" :title="contTitle?'扫码成功':'扫码失败'" :content="contModal" confirmText="继续扫码" @confirm="modalConfirm" @close="confirmModal=false" />
 		<common-modal v-if="confirmModal" :openModal="confirmModal" :title="contTitle?'扫码成功':'扫码失败'" :content="contModal" confirmText="继续扫码" @confirm="modalConfirm" @close="confirmModal=false" />
@@ -35,6 +35,7 @@
 		components: { partList, commonModal, chooseTypeModal },
 		components: { partList, commonModal, chooseTypeModal },
 		data() {
 		data() {
 			return {
 			return {
+				loading: false,
 				barcode:null,
 				barcode:null,
 				replenishBillSn: null,
 				replenishBillSn: null,
 				shelfSn: null,
 				shelfSn: null,
@@ -143,6 +144,7 @@
 				  shelfSn: _this.shelfSn
 				  shelfSn: _this.shelfSn
 				}
 				}
 				console.log(params)
 				console.log(params)
+				this.loading = true
 				shelfReplenishOutStock(params).then(res => {
 				shelfReplenishOutStock(params).then(res => {
 					console.log(res)
 					console.log(res)
 				  if (res.status == 200) {
 				  if (res.status == 200) {
@@ -157,6 +159,7 @@
 				  }else{
 				  }else{
 					  _this.toashMsg(res.message)
 					  _this.toashMsg(res.message)
 				  }
 				  }
+				  this.loading = false
 				})
 				})
 			},
 			},
 			// 确认出库
 			// 确认出库

+ 9 - 4
pages/replenishmentManage/signWarehousing.vue

@@ -8,10 +8,10 @@
 						<text>待签收</text>
 						<text>待签收</text>
 					</view>
 					</view>
 				</view>
 				</view>
-				<view>
+				<!-- <view>
 					<view class="label"><u-icon name="icon_delivery" custom-prefix="iscm-icon" size="32"></u-icon><text>配送方式</text></view>
 					<view class="label"><u-icon name="icon_delivery" custom-prefix="iscm-icon" size="32"></u-icon><text>配送方式</text></view>
 					<view class="info-txt">{{basicInfoData.dispatchTypeDictValue || '--'}}</view>
 					<view class="info-txt">{{basicInfoData.dispatchTypeDictValue || '--'}}</view>
-				</view>
+				</view> -->
 				<view>
 				<view>
 					<view class="label"><u-icon name="icon_remark" custom-prefix="iscm-icon" size="32"></u-icon><text>出库备注</text></view>
 					<view class="label"><u-icon name="icon_remark" custom-prefix="iscm-icon" size="32"></u-icon><text>出库备注</text></view>
 					<view class="info-txt">{{basicInfoData.remarks || '--'}}</view>
 					<view class="info-txt">{{basicInfoData.remarks || '--'}}</view>
@@ -23,7 +23,7 @@
 			</view>
 			</view>
 		</view>
 		</view>
 		<view class="replenishment-putWarehousing-footer">
 		<view class="replenishment-putWarehousing-footer">
-			<u-button @click="confirmModal=true" type="success" :custom-style="customStyle" hover-class="none" shape="circle">确定签收({{confirmQty}}/{{totalQty}})</u-button>
+			<u-button @click="confirmModal=true" type="success" :loading="loading" :custom-style="customStyle" hover-class="none" shape="circle">确定签收({{confirmQty}}/{{totalQty}})</u-button>
 		</view>
 		</view>
 		<!-- 确认弹框 -->
 		<!-- 确认弹框 -->
 		<common-modal :openModal="confirmModal" content="签收后数字货架的产品数量将增加,确认签收吗?" confirmText="确认签收" @confirm="modalConfirm" @close="confirmModal=false" />
 		<common-modal :openModal="confirmModal" content="签收后数字货架的产品数量将增加,确认签收吗?" confirmText="确认签收" @confirm="modalConfirm" @close="confirmModal=false" />
@@ -38,6 +38,7 @@
 		components: { partList, commonModal },
 		components: { partList, commonModal },
 		data() {
 		data() {
 			return {
 			return {
+				loading: false,
 				replenishBillSn: '',
 				replenishBillSn: '',
 				basicInfoData:null,
 				basicInfoData:null,
 				partList: [],
 				partList: [],
@@ -99,7 +100,8 @@
 			// 确认签收 confirm
 			// 确认签收 confirm
 			modalConfirm(){
 			modalConfirm(){
 				const arr = []
 				const arr = []
-				this.partList.map((item, index) => {
+				const retList = this.$refs.partList.getAllData()
+				retList.map((item, index) => {
 				  if (item.putQty || item.putQty == 0) {
 				  if (item.putQty || item.putQty == 0) {
 				    arr.push({
 				    arr.push({
 						productSn: item.productSn,
 						productSn: item.productSn,
@@ -114,6 +116,8 @@
 				  replenishBillSn: this.replenishBillSn,
 				  replenishBillSn: this.replenishBillSn,
 				  detailList: arr
 				  detailList: arr
 				}
 				}
+				console.log(params)
+				this.loading = true
 				shelfReplenishPutStock(params).then(res => {
 				shelfReplenishPutStock(params).then(res => {
 					if(res.status == 200){
 					if(res.status == 200){
 						uni.$emit('refreshBL')
 						uni.$emit('refreshBL')
@@ -121,6 +125,7 @@
 						uni.navigateBack()
 						uni.navigateBack()
 					}
 					}
 					this.toashMsg(res.message)
 					this.toashMsg(res.message)
+					this.loading = false
 				})
 				})
 			},
 			},
 			// 数量 change
 			// 数量 change

+ 4 - 1
pages/replenishmentManage/stockModal.vue

@@ -6,7 +6,10 @@
 				<view class="modal-box" v-for="(item, index) in list" :key="index">
 				<view class="modal-box" v-for="(item, index) in list" :key="index">
 					<view class="modal-p-header">
 					<view class="modal-p-header">
 						<view class="modal-p-code">{{item.product&&item.product.code?item.product.code:'--'}}</view>
 						<view class="modal-p-code">{{item.product&&item.product.code?item.product.code:'--'}}</view>
-						<view class="modal-p-num">库存<text class="txt-red">{{item.stockQty||item.stockQty==0?item.stockQty:'--'}}</text>/补货<text class="txt-main">{{item.confirmQty||item.confirmQty==0?item.confirmQty:'--'}}</text>{{item.product&&item.product.unit?item.product.unit:'--'}}</view>
+						<view class="modal-p-num">
+							库存<text class="txt-red">{{item.stockQty||item.stockQty==0?item.stockQty:'--'}}</text>/
+							补货<text class="txt-main">{{item.qty||(item.confirmQty||item.confirmQty==0?item.confirmQty:'--')}}</text>
+							{{item.product&&item.product.unit?item.product.unit:'--'}}</view>
 					</view>
 					</view>
 					<view class="modal-p-footer">{{item.product&&item.product.name?item.product.name:'--'}}</view>
 					<view class="modal-p-footer">{{item.product&&item.product.name?item.product.name:'--'}}</view>
 				</view>
 				</view>

+ 24 - 51
pages/sales/addCustomer.vue

@@ -1,14 +1,14 @@
 <template>
 <template>
 	<view class="addCustomer-content">
 	<view class="addCustomer-content">
 		<view class="content-form">
 		<view class="content-form">
-			<u-form :model="form" ref="uForm"  label-width="180" :error-type="['toast']">
-				<u-form-item label="客户名称" required ><u-input v-model.trim="form.customerName" placeholder="请输入客户名称(最多30个字符)" input-align="right" :maxlength="60"/></u-form-item>
-				<u-form-item label="客户地址" required >
+			<u-form :model="form" ref="uForm" label-width="150rpx" :error-type="['toast']">
+				<u-form-item label="客户名称" required prop="customerName" ><u-input v-model.trim="form.customerName" placeholder="请输入客户名称(最多30个字符)" input-align="right" :maxlength="60"/></u-form-item>
+				<u-form-item label="客户地址" required prop="provinceSn">
 					<u-input v-model="areaInfo.label" :disabled="true" input-align="right" placeholder="请选择客户地址" @click="openAddress"/>
 					<u-input v-model="areaInfo.label" :disabled="true" input-align="right" placeholder="请选择客户地址" @click="openAddress"/>
 					<u-icon name="arrow-right" color="#C0C4CC" slot="right"  @click="openAddress"></u-icon>
 					<u-icon name="arrow-right" color="#C0C4CC" slot="right"  @click="openAddress"></u-icon>
 				</u-form-item>
 				</u-form-item>
 				<u-form-item label="详细地址">
 				<u-form-item label="详细地址">
-					<textarea :auto-height="true" input-align="right" placeholder="请输入详细地址(最多60个字符)" :maxlength="60" v-model="form.customerAddr" class="receiveAddress" placeholder-style="color:#C0C4CC;font-size:28upx;"/>
+					<u-input type="textarea" :auto-height="true" input-align="right" placeholder="请输入详细地址(最多60个字符)" :maxlength="60" v-model="form.customerAddr"/>
 				</u-form-item>
 				</u-form-item>
 				<u-form-item label="联系人">
 				<u-form-item label="联系人">
 					<u-input v-model="form.contactName" input-align="right" placeholder="请输入联系人(最多20个字符)" :maxlength="20"/>
 					<u-input v-model="form.contactName" input-align="right" placeholder="请输入联系人(最多20个字符)" :maxlength="20"/>
@@ -84,6 +84,12 @@
 					priceType: undefined, //  价格类型
 					priceType: undefined, //  价格类型
 					settleStyleSn: undefined //  收款方式
 					settleStyleSn: undefined //  收款方式
 				},
 				},
+				rules: {
+					customerName: [{ required: true, message: '请输入客户名称', trigger: 'change' }],
+					provinceSn: [{ required: true, message: '请选择客户地址', trigger: 'change' }],
+					priceType: [{ required: true, message: '请选择价格类型', trigger: 'change' }],
+					settleStyleSn: [{ required: true, message: '请选择收款方式', trigger: 'change' }],
+				},
 				showSettle:false,//结算方式初始值
 				showSettle:false,//结算方式初始值
 				settleTypeList:[],//收款方式列表
 				settleTypeList:[],//收款方式列表
 				settleStyleName:'',//收款方式名称
 				settleStyleName:'',//收款方式名称
@@ -173,41 +179,6 @@
 			customerSubmit(){
 			customerSubmit(){
 				this.$refs.uForm.validate(valid => {
 				this.$refs.uForm.validate(valid => {
 					if (valid) {
 					if (valid) {
-						if (this.form.customerName ==='') {
-							uni.showToast({
-								title: '请输入客户名称',
-								icon: 'none'
-							})
-							return false
-						}
-						if(this.form.contactMobile){
-							if (!isvalidPhone(this.form.contactMobile)) {
-								uni.showToast({
-									title: '请输入正确的联系手机',
-									icon: 'none'
-								})
-								return false
-							}
-						}
-						//  省市区
-						if(this.areaIdArr.length == 0){
-							uni.showToast({icon: 'none',title: '请选择客户地址'})
-							return
-						}
-						if (!this.form.priceType) {
-							uni.showToast({
-								title: '请选择价格类型',
-								icon: 'none'
-							})
-							return false
-						}
-						if (!this.form.settleStyleSn) {
-							uni.showToast({
-								title: '请选择收款方式',
-								icon: 'none'
-							})
-							return false
-						}
 						const params=Object.assign({},this.form)
 						const params=Object.assign({},this.form)
 						console.log(params,'params')
 						console.log(params,'params')
 						if(this.form.id) {
 						if(this.form.id) {
@@ -223,10 +194,18 @@
 									uni.redirectTo({
 									uni.redirectTo({
 										url:'/pages/sales/addSales?pageType=add&nowId='+res.data.id
 										url:'/pages/sales/addSales?pageType=add&nowId='+res.data.id
 									})
 									})
-								}
-								// 门店审核通过
-								if(this.backPage == 'authPass'){
-									uni.$emit("addCustome",res.data)
+								}else{
+									// 门店审核通过
+									if(this.backPage == 'authPass'){
+										uni.$emit("addCustome",res.data)
+									}
+									// 货架设置关联客户
+									if(this.backPage == 'shelfSeting'){
+										uni.$emit("setCustome",res.data)
+									}
+									if(this.backPage == 'shelfEdit'){
+										uni.$emit("editCustome",res.data)
+									}
 									uni.navigateBack({
 									uni.navigateBack({
 										delta: 2
 										delta: 2
 									})
 									})
@@ -254,15 +233,9 @@
 		display: flex;
 		display: flex;
 		flex-direction: column;
 		flex-direction: column;
 		.content-form{
 		.content-form{
-			flex-grow:1;
+			flex:1;
+			padding: 0 0.5rem;
 			overflow: auto;
 			overflow: auto;
-			.receiveAddress{
-				width: 100%;
-				line-height: 1.5em;
-				box-sizing: border-box;
-				font-style: normal;
-				text-align: end;
-			}
 		}
 		}
 		.form-footer-btn{
 		.form-footer-btn{
 			background-color: #fff;
 			background-color: #fff;

+ 42 - 7
pages/sales/chooseCustomer.vue

@@ -1,21 +1,31 @@
 <template>
 <template>
 	<view class="chooseCustomer-content">
 	<view class="chooseCustomer-content">
 		<view class="search">
 		<view class="search">
-			<view class="flex justify_between align_center search-title">
+			<view class="flex justify_between align_center search-title" v-if="backPage!='shelfSeting'">
 				<text class="search-label">客户名称</text>
 				<text class="search-label">客户名称</text>
-				<view class="search-btn" v-if="backPage == 'addSales'||backPage == 'authPass'">
+				<view class="search-btn" v-if="backPage != 'salesRecord'">
 					<text>没有搜索到?</text>
 					<text>没有搜索到?</text>
 					<text>点击</text>
 					<text>点击</text>
 					<text @click="addCustomer">新增客户</text>
 					<text @click="addCustomer">新增客户</text>
 				</view>
 				</view>
 			</view>
 			</view>
+			<view v-else>
+				<view class="shelfName">{{shelfName}}</view>
+				<view class="flex justify_between align_center search-title">
+					<view class="search-btn">
+						<text>请先设置此货架的关联客户。没有搜索到?</text>
+						<text>点击</text>
+						<text @click="addCustomer">新增客户</text>
+					</view>
+				</view>
+			</view>
 			<u-search
 			<u-search
 				placeholder="请输入客户名称搜索" 
 				placeholder="请输入客户名称搜索" 
 				v-model="queryWord" 
 				v-model="queryWord" 
 				height="90"
 				height="90"
-				@input="searchBrand"
-				@blur="searchBrand"
-				@search="searchBrand"
+				@input="$u.debounce(searchBrand, 500)"
+				@blur="$u.debounce(searchBrand, 500)"
+				@search="$u.debounce(searchBrand, 500)"
 				@clear="clearSearch"
 				@clear="clearSearch"
 				:showAction="false">
 				:showAction="false">
 			</u-search>
 			</u-search>
@@ -44,12 +54,25 @@
 				pageSize:20,
 				pageSize:20,
 				pageNo:1,
 				pageNo:1,
 				scrollH:300,
 				scrollH:300,
-				backPage:''
+				backPage:'',
+				shelfName: ''
 			}
 			}
 		},
 		},
 		onLoad(opts) {
 		onLoad(opts) {
 			uni.$on('clear',this.clearSearch)
 			uni.$on('clear',this.clearSearch)
 			this.backPage = opts.backPage
 			this.backPage = opts.backPage
+			
+			let title = '选择客户'
+			if(opts.backPage == 'shelfSeting'){
+				title = '关联客户'
+			}
+			if(opts.backPage == 'shelfEdit'){
+				title = '修改关联客户'
+			}
+			uni.setNavigationBarTitle({
+				title: title
+			})
+			this.shelfName = opts.shelfName
 		},
 		},
 		onShow() {
 		onShow() {
 			this.init()
 			this.init()
@@ -112,6 +135,15 @@
 					uni.$emit("addCustome",item)
 					uni.$emit("addCustome",item)
 					uni.navigateBack()
 					uni.navigateBack()
 				}
 				}
+				// 货架设置关联客户
+				if(this.backPage == 'shelfSeting'){
+					uni.$emit("setCustome",item)
+					uni.navigateBack()
+				}
+				if(this.backPage == 'shelfEdit'){
+					uni.$emit("editCustome",item)
+					uni.navigateBack()
+				}
 			}
 			}
 		},
 		},
 	}
 	}
@@ -126,6 +158,9 @@
 		display: flex;
 		display: flex;
 		flex-direction: column;
 		flex-direction: column;
 		.search{
 		.search{
+			.shelfName{
+				font-weight: bold;
+			}
 			.search-title{
 			.search-title{
 				padding: 20upx 0;
 				padding: 20upx 0;
 				.search-label{
 				.search-label{
@@ -133,7 +168,7 @@
 					font-weight: 600;
 					font-weight: 600;
 				}
 				}
 				.search-btn{
 				.search-btn{
-					font-size: 28upx;
+					font-size: 24upx;
 					color: #999;
 					color: #999;
 					text:last-child{
 					text:last-child{
 						display: inline-block;
 						display: inline-block;

+ 2 - 2
pages/sales/chooseProduct.vue

@@ -23,7 +23,7 @@
 						</view>
 						</view>
 					</view>
 					</view>
 					<view class="list-item-footer flex align_center justify_between">
 					<view class="list-item-footer flex align_center justify_between">
-						<view class="footer-item" v-if="searchParams && searchParams.cost">
+						<view class="footer-item" v-if="searchParams && searchParams.cost &&$hasPermissions('M_showCostPrice_mobile')">
 							<view>{{toThousands(item.putCost||0, 2)}}</view>
 							<view>{{toThousands(item.putCost||0, 2)}}</view>
 							<view class="color_6">成本价</view>
 							<view class="color_6">成本价</view>
 						</view>
 						</view>
@@ -45,7 +45,7 @@
 					</view>
 					</view>
 				</view>
 				</view>
 				<view v-if="listData && listData.length == 0">
 				<view v-if="listData && listData.length == 0">
-					<u-empty :text="noDataText" mode="list" :img-width="200" :margin-top="30"></u-empty>
+					<u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="150" :text="noDataText" mode="list" :margin-top="50"></u-empty>
 				</view>
 				</view>
 				<view style="padding-bottom: 20upx;">
 				<view style="padding-bottom: 20upx;">
 					<u-loadmore v-if="totalNum>listData.length || status=='loading'" :status="status" />
 					<u-loadmore v-if="totalNum>listData.length || status=='loading'" :status="status" />

+ 3 - 3
pages/sales/edit.vue

@@ -41,7 +41,7 @@
 					<view>
 					<view>
 						急件总款数:<text class="sales-total-num" :style="{color: $config('warringColor')}">{{detailData && (detailData.oosCategory || detailData.oosCategory==0) ? toThousands(detailData.oosCategory) : '--'}}</text>;急件总数量:<text class="sales-total-num" :style="{color: $config('warringColor')}">{{detailData && (detailData.oosQty || detailData.oosQty==0) ? toThousands(detailData.oosQty) : '--'}}</text>;赠品总数量:<text class="sales-total-num" :style="{color: $config('warringColor')}">{{detailData && (detailData.giftQty || detailData.giftQty==0) ? toThousands(detailData.giftQty) : '--'}}</text>;
 						急件总款数:<text class="sales-total-num" :style="{color: $config('warringColor')}">{{detailData && (detailData.oosCategory || detailData.oosCategory==0) ? toThousands(detailData.oosCategory) : '--'}}</text>;急件总数量:<text class="sales-total-num" :style="{color: $config('warringColor')}">{{detailData && (detailData.oosQty || detailData.oosQty==0) ? toThousands(detailData.oosQty) : '--'}}</text>;赠品总数量:<text class="sales-total-num" :style="{color: $config('warringColor')}">{{detailData && (detailData.giftQty || detailData.giftQty==0) ? toThousands(detailData.giftQty) : '--'}}</text>;
 					</view>
 					</view>
-					<view>
+					<view v-if="$hasPermissions('M_showCostPrice_mobile')">
 						总成本:<text class="sales-total-num" :style="{color: $config('warringColor')}">¥{{detailData && (detailData.totalCost || detailData.totalCost==0) ? toThousands(detailData.totalCost, 2) : '--'}}</text>;总毛利:<text class="sales-total-num" :style="{color: $config('warringColor')}">¥{{detailData && (detailData.grossProfit || detailData.grossProfit==0) ? toThousands(detailData.grossProfit, 2) : '--'}}</text>;
 						总成本:<text class="sales-total-num" :style="{color: $config('warringColor')}">¥{{detailData && (detailData.totalCost || detailData.totalCost==0) ? toThousands(detailData.totalCost, 2) : '--'}}</text>;总毛利:<text class="sales-total-num" :style="{color: $config('warringColor')}">¥{{detailData && (detailData.grossProfit || detailData.grossProfit==0) ? toThousands(detailData.grossProfit, 2) : '--'}}</text>;
 					</view>
 					</view>
 				</view>
 				</view>
@@ -54,7 +54,7 @@
 					<view class="sales-list-item border-b flex align_center justify_between" v-for="(item, index) in listData" :key="item.id">
 					<view class="sales-list-item border-b flex align_center justify_between" v-for="(item, index) in listData" :key="item.id">
 						<view class="font_13 flex_1 flex justify_between">
 						<view class="font_13 flex_1 flex justify_between">
 							<view class="pimgs">
 							<view class="pimgs">
-								<u-image :src="item.productMainImage?item.productMainImage:`../../static/${theme}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
+								<u-image :src="item.productMainImage?item.productMainImage:`../../static/${$config('themePath')}/def_img@2x.png`" width="128" height="128" border-radius="10"></u-image>
 								<view v-if="item.oosFlag == 1" class="sign" :style="{backgroundColor: $config('errorColor')}">急</view>
 								<view v-if="item.oosFlag == 1" class="sign" :style="{backgroundColor: $config('errorColor')}">急</view>
 								<view v-if="item.price < item.cost" class="sign" :style="{backgroundColor: $config('errorColor')}">亏</view>
 								<view v-if="item.price < item.cost" class="sign" :style="{backgroundColor: $config('errorColor')}">亏</view>
 								<view v-if="item.price == 0" class="sign" :style="{backgroundColor: $config('errorColor')}">赠</view>
 								<view v-if="item.price == 0" class="sign" :style="{backgroundColor: $config('errorColor')}">赠</view>
@@ -80,7 +80,7 @@
 						</view> -->
 						</view> -->
 					</view>
 					</view>
 					<view v-if="listData && listData.length == 0">
 					<view v-if="listData && listData.length == 0">
-						<u-empty :text="noDataText" mode="list" :img-width="200" :margin-top="30"></u-empty>
+						<u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="150" :text="noDataText" mode="list" :margin-top="50"></u-empty>
 					</view>
 					</view>
 					<view style="padding: 20upx;">
 					<view style="padding: 20upx;">
 						<u-loadmore v-if="totalNum>listData.length || status=='loading'" :status="status" />
 						<u-loadmore v-if="totalNum>listData.length || status=='loading'" :status="status" />

+ 26 - 9
pages/sales/index.vue

@@ -2,7 +2,7 @@
 	<view class="sales-warp">
 	<view class="sales-warp">
 		<view id="tjCons">
 		<view id="tjCons">
 			<!--销售数据统计 -->
 			<!--销售数据统计 -->
-			<view class="content-data">
+			<view class="content-data" v-if="$hasPermissions('M_salesTj_mobile')">
 				<view class="date-type">
 				<view class="date-type">
 					<text v-for="(item, index) in tabNav" :key="index" :class="[index == navInd ? 'active_day' : '']" @click="seleteTime(index)">{{item.name}}</text>
 					<text v-for="(item, index) in tabNav" :key="index" :class="[index == navInd ? 'active_day' : '']" @click="seleteTime(index)">{{item.name}}</text>
 				</view>
 				</view>
@@ -23,7 +23,7 @@
 			</view>
 			</view>
 			<!-- 产品报价及新增销售单 -->
 			<!-- 产品报价及新增销售单 -->
 			<view class="nav-cont flex align_center justify_between">
 			<view class="nav-cont flex align_center justify_between">
-				<view class="nav-item" @click="toPage('/pages/sales/productPricing')">
+				<view class="nav-item" @click="toPage('/pages/sales/productPricing')" v-if="$hasPermissions('M_productPrice_mobile')">
 					<u-image class="nav-pic" style="margin-top: 5upx;" :src="`../../static/${theme}/navIcon/price_icon.png`" width="60" height="60"></u-image>
 					<u-image class="nav-pic" style="margin-top: 5upx;" :src="`../../static/${theme}/navIcon/price_icon.png`" width="60" height="60"></u-image>
 					<text class="nav-txt" style="margin-top: 5upx;">产品报价</text>
 					<text class="nav-txt" style="margin-top: 5upx;">产品报价</text>
 				</view>
 				</view>
@@ -31,7 +31,7 @@
 					<u-image class="nav-pic" :src="`../../static/${theme}/navIcon/sale_icon.png`" width="70" height="70"></u-image>
 					<u-image class="nav-pic" :src="`../../static/${theme}/navIcon/sale_icon.png`" width="70" height="70"></u-image>
 					<text class="nav-txt">新增销售单</text>
 					<text class="nav-txt">新增销售单</text>
 				</view> -->
 				</view> -->
-				<view class="nav-item" @click="toPage('/pages/webviews/openview?title=产品查询&url=https://jgqp.51cjml.com/h5/#!/')">
+				<view class="nav-item" @click="toPage('/pages/webviews/openview?title=产品查询&url=https://jgqp.51cjml.com/h5/#!/')" v-if="$hasPermissions('M_queryProduct_mobile')">
 					<u-image class="nav-pic" :src="`../../static/${theme}/navIcon/pfind.png`" width="64" height="64"></u-image>
 					<u-image class="nav-pic" :src="`../../static/${theme}/navIcon/pfind.png`" width="64" height="64"></u-image>
 					<text class="nav-txt">产品查询</text>
 					<text class="nav-txt">产品查询</text>
 				</view>
 				</view>
@@ -54,9 +54,10 @@
 
 
 <script>
 <script>
 	import ListComponent from './listComponent.vue'
 	import ListComponent from './listComponent.vue'
-	import { toThousands } from '@/libs/tools'
+	import { toThousands, openMessagePage } from '@/libs/tools'
 	import { bizData } from '@/api/sales'
 	import { bizData } from '@/api/sales'
 	import { listLookUp, getLookUpDatas } from '@/api/data.js'
 	import { listLookUp, getLookUpDatas } from '@/api/data.js'
+	import { setReadNotice } from "@/api/user.js"
 	export default{
 	export default{
 		components: { ListComponent },
 		components: { ListComponent },
 		data(){
 		data(){
@@ -75,10 +76,10 @@
 		onReady() {
 		onReady() {
 			const query = uni.createSelectorQuery().in(this);
 			const query = uni.createSelectorQuery().in(this);
 			query.select('#tjCons').boundingClientRect(data => {
 			query.select('#tjCons').boundingClientRect(data => {
-			  this.listHeight = Math.floor(data.height + 18)
+			  this.listHeight = Math.floor(data.height)
 			}).exec();
 			}).exec();
 		},
 		},
-		onLoad() {
+		onLoad(opts) {
 			const _this = this
 			const _this = this
 			this.$nextTick(function(){
 			this.$nextTick(function(){
 				// 监听整改完成后刷新事件
 				// 监听整改完成后刷新事件
@@ -86,7 +87,15 @@
 					_this.$refs.salesList.refash()
 					_this.$refs.salesList.refash()
 				})
 				})
 			})
 			})
-			
+			// 点击消息打开
+			const msg = this.$store.state.vuex_tempData
+			console.log('toMessage',msg)
+			if(msg){
+				setReadNotice({'noticeId': msg.extras.noticeId}).then(res => {
+					openMessagePage(msg)
+				})
+			}
+			// 底部tab
 			const theme = getApp().globalData.theme
 			const theme = getApp().globalData.theme
 			this.theme = theme
 			this.theme = theme
 			uni.setTabBarItem({
 			uni.setTabBarItem({
@@ -98,11 +107,13 @@
 			  "index": 1,
 			  "index": 1,
 			  "iconPath": "static/"+theme+"/tabbar/stock.png",
 			  "iconPath": "static/"+theme+"/tabbar/stock.png",
 			  "selectedIconPath": "static/"+theme+"/tabbar/stock-active.png",
 			  "selectedIconPath": "static/"+theme+"/tabbar/stock-active.png",
+			  "visible": this.$hasPermissions('M_stockManage_mobile')
 			})
 			})
 			uni.setTabBarItem({
 			uni.setTabBarItem({
 			  "index": 2,
 			  "index": 2,
 			  "iconPath": "static/"+theme+"/tabbar/shelf.png",
 			  "iconPath": "static/"+theme+"/tabbar/shelf.png",
 			  "selectedIconPath": "static/"+theme+"/tabbar/shelf-active.png",
 			  "selectedIconPath": "static/"+theme+"/tabbar/shelf-active.png",
+			  "visible": this.$hasPermissions('M_shelfManage_mobile')
 			})
 			})
 			uni.setTabBarItem({
 			uni.setTabBarItem({
 			  "index": 3,
 			  "index": 3,
@@ -129,6 +140,7 @@
 		},
 		},
 		onUnload() {
 		onUnload() {
 			uni.$off('refreshSalesHomeBL')
 			uni.$off('refreshSalesHomeBL')
+			uni.$off('toMessage')
 		},
 		},
 		onShow() {
 		onShow() {
 			this.navInd = 0
 			this.navInd = 0
@@ -180,7 +192,13 @@
 <style lang="scss">
 <style lang="scss">
 	.sales-warp{
 	.sales-warp{
 		width: 100%;
 		width: 100%;
-		padding: 20rpx 20upx;
+		height: 100vh;
+		padding: 0 20upx;
+		> view{
+			&:first-child{
+				padding-top: 20upx;
+			}
+		}
 		.color_6{
 		.color_6{
 			color: #666;
 			color: #666;
 		}
 		}
@@ -251,7 +269,6 @@
 		}
 		}
 		.sales-list{
 		.sales-list{
 			.title{
 			.title{
-				margin-bottom: 14upx;
 				display: flex;
 				display: flex;
 				align-items: center;
 				align-items: center;
 				justify-content: space-between;
 				justify-content: space-between;

+ 4 - 3
pages/sales/listComponent.vue

@@ -38,7 +38,7 @@
 					</view> -->
 					</view> -->
 				</view>
 				</view>
 				<view v-if="listData && listData.length == 0 && status!='loading'">
 				<view v-if="listData && listData.length == 0 && status!='loading'">
-					<u-empty :text="noDataText" mode="list" :img-width="200" :margin-top="30"></u-empty>
+					<u-empty :src="`/static/${$config('themePath')}/def_no_data@3x.png`" icon-size="150" :text="noDataText" mode="list" :margin-top="50"></u-empty>
 				</view>
 				</view>
 				<view style="padding-bottom: 20upx;">
 				<view style="padding-bottom: 20upx;">
 					<u-loadmore v-if="totalNum>listData.length || status=='loading'" :status="status" />
 					<u-loadmore v-if="totalNum>listData.length || status=='loading'" :status="status" />
@@ -237,14 +237,14 @@
 						.u-line{
 						.u-line{
 							display: inline-block;
 							display: inline-block;
 							width: 6upx;
 							width: 6upx;
-							height: 30upx;
+							height: 28upx;
 							vertical-align: bottom;
 							vertical-align: bottom;
 							margin: 0 10upx;
 							margin: 0 10upx;
 							border-radius: 5upx;
 							border-radius: 5upx;
 						}
 						}
 						.buyer{
 						.buyer{
 							flex-grow: 1;
 							flex-grow: 1;
-							font-size: 30upx;
+							font-size: 28upx;
 							font-weight: bold;
 							font-weight: bold;
 						}
 						}
 						>view{
 						>view{
@@ -252,6 +252,7 @@
 								width: 150upx;
 								width: 150upx;
 								text-align: right;
 								text-align: right;
 								color: #666;
 								color: #666;
+								font-size: 26upx;
 							}
 							}
 						}
 						}
 					}
 					}

+ 7 - 1
pages/sales/productPricing.vue

@@ -2,7 +2,7 @@
 	<view class="productPricing-content">
 	<view class="productPricing-content">
 		<view class="checkbox-price">
 		<view class="checkbox-price">
 			<u-checkbox-group  placement="row">
 			<u-checkbox-group  placement="row">
-				<u-checkbox v-model="item.checked" activeColor="rgb(4, 133, 246)" v-for="(item,index) in priceList" :key="index" :name="item.val">{{item.name}}</u-checkbox>
+				<u-checkbox v-model="item.checked" activeColor="rgb(4, 133, 246)" v-for="(item,index) in tabList" :key="index" :name="item.val">{{item.name}}</u-checkbox>
 			</u-checkbox-group>
 			</u-checkbox-group>
 		</view>
 		</view>
 		<scroll-view class="product-list" scroll-y @scrolltolower="onreachBottom">
 		<scroll-view class="product-list" scroll-y @scrolltolower="onreachBottom">
@@ -100,6 +100,12 @@
 			selPriceShow() {
 			selPriceShow() {
 				const a = this.priceList.filter(item => item.checked)
 				const a = this.priceList.filter(item => item.checked)
 				return a.length > 0
 				return a.length > 0
+			},
+			tabList(){
+				if(!this.$hasPermissions('M_showCostPrice_mobile')){
+					return this.priceList.slice(1,4)
+				}
+				return this.priceList
 			}
 			}
 		},
 		},
 		onLoad(option) {
 		onLoad(option) {

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików