Browse Source

[dev]
1、websocket功能开发完成待测试
2、通知推送消息功能和跳转逻辑完成待测试
3、已有6个接口完成数据模型对接,等待联调测试
4、复核扫码及其后续逻辑完成待测试

Neo.Sun 2 years ago
parent
commit
67f623e457

+ 52 - 12
App.vue

@@ -5,29 +5,69 @@
 </template> -->
 <script setup>
 import { onShow, onHide, onLaunch } from '@dcloudio/uni-app'
+import websocket from '@/static/websocket.js'
+
+//定义定时器
+let globalTimer = null
+
 onLaunch(async()=> {
 	console.log('App onLaunch')
-	uni.getSystemInfo({
-					success: function(e) {
-						// Vue.prototype.StatusBar = e.statusBarHeight;
-						console.log("e.statusBarHeight", e.statusBarHeight)
-						if (e.platform == 'android') {
-							// Vue.prototype.CustomBar = e.statusBarHeight + 50;
-							console.log('CustomBar', e.statusBarHeight + 50)
-						} else {
-							console.log('CustomBar', e.statusBarHeight + 45)
-						};
-					}
-				})
+	
+	// uni.getSystemInfo({
+	// 	success: function(e) {
+	// 		// Vue.prototype.StatusBar = e.statusBarHeight;
+	// 		console.log("e.statusBarHeight", e.statusBarHeight)
+	// 		if (e.platform == 'android') {
+	// 			// Vue.prototype.CustomBar = e.statusBarHeight + 50;
+	// 			console.log('CustomBar', e.statusBarHeight + 50)
+	// 		} else {
+	// 			console.log('CustomBar', e.statusBarHeight + 45)
+	// 		};
+	// 	}
+	// })
 	
 })
 onShow(()=>{
 	
 	console.log('App Show')
+	uni.$on('login',(data)=>{
+		try {
+			//建立socket连接
+			websocket.connectSocket(`wss://localhost:8005/webSocket/sentMessage${data.userId}`,() => {
+				//如果连接成功则发送心跳检测
+				heartBeatTest()
+			})
+		} catch (error) {
+			console.log('App err:' + error)
+		}
+	})
+	
 })
 onHide(()=>{
 	console.log('App Hide')
+	//关闭socket
+	
+	uni.$off('login', (data)=>{
+			websocket.closeSocket()
+	})
 })
+
+const heartBeatTest=()=> {
+	//清除定时器
+	clearInterval(globalTimer)
+	//开启定时器定时检测心跳
+	globalTimer = setInterval(() => {
+		//发送消息给服务端
+		websocket.sendMessage(
+			JSON.stringify({ action: 'ping'}), //与服务端约定好消息格式
+			null,
+			() => {
+				//如果失败则清除定时器
+				clearInterval(globalTimer)
+			}
+		)
+	}, 10000)
+}
 
 </script>
 

+ 50 - 14
components/nav-bar/nav-bar.vue

@@ -1,13 +1,14 @@
 <template>
   <view class="nav">
 		<view class="navbar">
+			<button class="scanbara" @click="handleScanbara">复核扫码</button>
 			<view class="status">{{props.userInfo.workStatus === '0'?"接单中":"暂停接单"}}</view>
 			<view class="userinfo">
-				<button type="primary" class="lef" @click="handleChange">{{props.userInfo.workStatus === '0'?"暂停接单":"开始接单"}}</button>
+				<button class="lef" @click="handleChange">{{props.userInfo.workStatus === '0'?"暂停接单":"开始接单"}}</button>
 				<image class="mid" aspectFill src="https://qiniu-web-assets.dcloud.net.cn/unidoc/zh/cat-1.png" />
 				<view class="rig">
 					<text class="name">{{props.userInfo.name?props.userInfo.name:"张三三"}}</text>
-					<button size="mini" type="primary" @click="handleLogout"  class="logout">退出</button>
+					<view size="mini" @click="handleLogout" class="logout">退出<uni-icons class="item" type="forward" color="#ff" size="20"></uni-icons></view>
 				</view>
 			</view>
 		</view>
@@ -64,6 +65,21 @@ const handleChange =async()=>{
 	}
 }
 
+const handleScanbara = ()=>{
+	uni.scanCode({
+		scanType: ['barCode'],
+		success: function (res) {
+			console.log('条码类型:' + res.scanType);
+			console.log('条码内容:' + res.result);
+			if(res.result) {
+				uni.navigateTo({
+					url:`/pages/edit/edit?preId=${res.result}&depolyStatus=2`
+				})
+			}
+		}
+	});
+}
+
 const handleLogout = async()=>{
 	console.log("handleLogout", 555)
 	const tokens = uni.getStorageSync('token')
@@ -91,46 +107,66 @@ const handleLogout = async()=>{
 	align-items:flex-end;
 	width: 1200px;
 	
-	background-color: #cfcfcf;
+	background-color: #18C7B0;
 	padding-bottom: 20rpx;
 	// position: fixed;
 	.navbar{
-		width: 440rpx;
+		width: 1200px;
 		display: flex;
 		align-items: center;
 		justify-content: space-between;
+		.scanbara{
+			// display: flex;
+			height: 54px;
+			font-size: 20px;
+			color:#18C7B0;
+			margin: 0 33px;
+		}
 		.status{
 			font-size: 20rpx;
+			color:#fff;
+			margin-left: 200px;
 		}
 		.userinfo{
 			display: flex;
 			justify-content: space-between;
 			align-items: center;
 			.lef{
-				height: 60rpx;
-				width: 60rpx;
-				padding: 14rpx;
+				height: 54px;
+				// width: 60rpx;
+				// padding: 14rpx;
 				margin-right: 30rpx;
-				font-size: 15rpx;
-				line-height: 15rpx;
+				font-size: 20px;
+				color:#18C7B0;
+				margin: 0 20px;
 			}
 			.mid{
 				height: 50rpx;
 				width: 50rpx;
-				margin-right: 30rpx;
+				margin-right: 20px;
+				border-radius: 50%;
 			}
 			.rig{
-				margin-right: 10rpx;
+				margin-right: 40px;
 				display: flex;
 				flex-direction: column;
 				align-items: center;
 				.name{
-					margin-bottom: 10rpx;
-					width: 50rpx;
+					margin-bottom: 10px;
+					// width: 50rpx;
+					font-size: 28px;
+					color: #fff;
 					 text-align: center;
 				}
 				.logout{
-					width: 50rpx;
+					// width: 50rpx;
+					background-color: #18C7B0;
+					font-size: 24px;
+					color: #fff;
+					border: 1px solid #18C7B0;
+					display: flex;
+					align-items: center;
+					justify-content: center;
 				}
 			}
 		}

+ 2 - 2
components/order-card/order-card.vue

@@ -60,11 +60,11 @@ const handleDetail = ()=>{
 	console.log("handleDetail", props.v, props.c)
 	if(props.c===0){
 		uni.navigateTo({
-			url:"/pages/edit/edit"
+			url:`/pages/edit/edit?preId=${props.v.preId}&depolyStatus=1`
 		})
 	} else {
 		uni.navigateTo({
-			url:"/pages/detail/detail"
+			url:`/pages/detail/detail?preId=${props.v.preId}`
 		})
 	}
 	

+ 17 - 0
js_sdk/levine-APPPush/levine-APPPush/main.js

@@ -0,0 +1,17 @@
+import Vue from 'vue'
+import App from './App'
+
+Vue.config.productionTip = false
+
+App.mpType = 'app'
+
+/**
+ * 推送弹框
+ */
+import appPush from '@/plugins/APPPush/index.js'
+Vue.use(appPush)
+
+const app = new Vue({
+    ...App
+})
+app.$mount()

+ 62 - 0
js_sdk/levine-APPPush/levine-APPPush/pages/index/index.vue

@@ -0,0 +1,62 @@
+<template>
+	<view class="content">
+		<button type="default" @click="open">打开自定义推送弹框</button>
+	</view>
+</template>
+
+<script>
+	export default {
+		data() {
+			return {
+				title: 'Hello'
+			}
+		},
+		onLoad() {
+
+		},
+		methods: {
+			open() {
+				let params = {
+					inApp: true, // app内横幅提醒
+					voice: true,	// 声音提醒
+					vibration: true,	// 振动提醒
+					messageType: '消息分类',
+					messageTitle: '通知标题',
+					messageContent: '通知文案通知文案通知文案通知文案通知文案通知文案通知文案通知文案通知文案通知文案',
+					messageImage: 'https://test999.cgc999.com/group1/M00/00/57/CgEKmGAC87eARAQFAANXI1t4oU4904.png'
+				}
+				this.$appPush(params)
+			}
+		}
+	}
+</script>
+
+<style>
+	.content {
+		display: flex;
+		flex-direction: column;
+		align-items: center;
+		justify-content: center;
+		height: 100vh;
+		background: #f4f4f4;
+	}
+
+	.logo {
+		height: 200rpx;
+		width: 200rpx;
+		margin-top: 200rpx;
+		margin-left: auto;
+		margin-right: auto;
+		margin-bottom: 50rpx;
+	}
+
+	.text-area {
+		display: flex;
+		justify-content: center;
+	}
+
+	.title {
+		font-size: 36rpx;
+		color: #8f8f94;
+	}
+</style>

+ 347 - 0
js_sdk/levine-APPPush/levine-APPPush/plugins/APPPush/app_push.js

@@ -0,0 +1,347 @@
+export class appPush{
+	constructor(option = {}) {
+		console.log(option)
+		// app内横幅提醒
+		this.inApp = option.inApp;
+		// 声音提醒
+		this.voice = option.voice;
+		// 振动提醒
+		this.vibration = option.vibration;
+		// 消息分类
+		this.messageType = option.messageType || '';
+		// 通知标题
+		this.messageTitle = option.messageTitle || '';
+		// 时间
+		this.messageTime = option.messageTime || '现在';
+		// 通知文案
+		this.messageContent = option.messageContent || '';
+		// 缩略图
+		this.messageImage = option.messageImage || '';	
+		
+		
+	    this.screenWidth = plus.screen.resolutionWidth;
+	    this.screenHeight = plus.screen.resolutionHeight;
+	    // 比例
+	    this.propotation = this.screenWidth / 750
+	    //弹窗容器宽度
+	    this.popupViewWidth = this.propotation * 710;
+	    // 弹窗容器高度
+	    this.popupViewHeight = this.propotation * 192;
+	    // 弹窗容器的Padding
+	    this.viewContentPadding = this.propotation * 30;
+		// 弹框容器的宽度
+		this.viewContentWidth = parseInt(this.popupViewWidth - (this.viewContentPadding * 2))
+		// 弹框到顶部的距离
+		this.system = uni.getSystemInfoSync()
+		// 过度时间
+		this.duration = 200
+		// 关闭时间
+		this.closeTime = 3000
+		
+		console.log(this.inApp, this.voice, this.vibration)
+		
+		this.top = (this.propotation * 20) + this.system.statusBarHeight;
+		this.initTop = -this.system.statusBarHeight
+		
+		this.body = null;
+		this.bodyBg = null;
+		this.timer = null;
+		
+		this.flag = false
+		this.cur = {
+			x: 0,
+			y: 0,
+			pageX: 0,
+			pageY: 0
+		}
+		
+	}
+	
+	// 生成弹框主体
+	createView() {
+		// console.log((this.propotation * 20) + this.system.statusBarHeight+ '--------------')
+		let view = new plus.nativeObj.View('popupView', {
+			// tag: 'rect',
+			top: (this.propotation * 20) + this.system.statusBarHeight,
+			left: this.propotation * 20,
+			height: this.popupViewHeight,
+			width: this.popupViewWidth
+		})
+		// 绘制白色背景
+		view.drawRect({
+			color:"#fff",
+			radius:"10px"
+		})
+		let viewContentList = [
+			{
+				src: '/static/push/message-icon.png',
+				id: 'icon',
+				tag: 'img',
+				position: {
+					top: this.viewContentPadding + "px",
+					left: this.viewContentPadding + "px",
+					width: (this.propotation * 24) + 'px',
+					height: (this.propotation * 24) + 'px',
+				}
+			},
+			{
+				tag: 'font',
+				id: 'pop-title',
+				text: this.messageType,
+				textStyles: {
+					size: (this.propotation * 24) + 'px',
+					align: "left",
+					color: "#4F555B"
+				},
+				position: {
+					top: this.viewContentPadding + "px",
+					left: (this.propotation * 64) + 'px',
+					height: (this.propotation * 24) + 'px',
+					width: this.viewContentWidth + "px",
+				}
+			},
+			{
+				tag: 'font',
+				id: 'time',
+				text: this.messageTime,
+				textStyles: {
+					size: (this.propotation * 24) + 'px',
+					align: "right",
+					color: "#4F555B"
+				},
+				position: {
+					top: this.viewContentPadding + "px",
+					left: this.viewContentPadding + "px",
+					height: (this.propotation * 24) + 'px',
+					width: this.viewContentWidth + "px",
+				}
+			},
+			{
+				tag: 'font',
+				id: 'push-title',
+				text: this.messageTitle,
+				textStyles: {
+					size: (this.propotation * 30) + 'px',
+					align: "left",
+					color: "#202123",
+					overflow: "ellipsis"
+				},
+				position: {
+					top: (this.propotation * 82) + 'px',
+					left: (this.propotation * 30) + 'px',
+					height: (this.propotation * 30) + 'px',
+					width: (this.propotation * 505) + 'px',
+				}
+			},
+			{
+				tag: 'font',
+				id: 'push-content',
+				text: this.messageContent,
+				textStyles: {
+					size: (this.propotation * 24) + 'px',
+					align: "left",
+					color: "#4F555B",
+					overflow: "ellipsis"
+				},
+				position: {
+					top: (this.propotation * 130) + 'px',
+					left: (this.propotation * 30) + 'px',
+					height: (this.propotation * 24) + 'px',
+					width: (this.propotation * 505) + 'px',
+				}
+			},
+			{
+				src: this.messageImage,
+				id: 'image',
+				tag: 'img',
+				position: {
+					top: (this.propotation * 68) + 'px',
+					// right: "0px",
+					left: (this.propotation * 586) + 'px',
+					width: (this.propotation * 100) + 'px',
+					height: (this.propotation * 100) + 'px',
+				}
+			},
+			{
+				src: '/static/push/img-bg.png',
+				id: 'img-bg',
+				tag: 'img',
+				position: {
+					top: (this.propotation * 68) + 'px',
+					// right: "0px",
+					left: (this.propotation * 586) + 'px',
+					width: (this.propotation * 100) + 'px',
+					height: (this.propotation * 100) + 'px',
+				}
+			},
+		]
+		view.draw(viewContentList)
+		// view.addEventListener("click",(e)=>{
+		// 	console.log('---------------------')
+		// });
+		view.addEventListener("touchstart", (event) => {
+			// console.log(event)
+			this.flag = true;  
+			var touch;  
+			if (event.touches) {  
+				touch = event.touches[0];  
+			} else {  
+				touch = event;  
+			}  
+			this.cur.x = touch.clientX;  
+			this.cur.y = touch.clientY;
+			this.cur.pageX = touch.pageX;
+			this.cur.pageY = touch.pageY;  
+		})
+		view.addEventListener("touchmove", (event) => {
+			// console.log(e)
+			var touch;  
+			if (event.touches) {  
+				touch = event.touches[0];  
+			} else {  
+				touch = event;
+			}  
+			let moveX = touch.pageX - this.cur.x;   
+			let moveY = touch.pageY - this.cur.y;   
+			let x = moveX;  
+			let y = moveY;
+			// console.log(x, y)
+			// console.log(this.cur, touch)
+			if (x < 0) {  
+				// x = 0;  
+			} else if (x > (this.popupViewWidth - this.popupViewWidth)) {  
+				// x = this.screenWidth - 40;  
+			}  
+			if (y < 0) {  
+				// y = 0;  
+			} else if (y >= ((this.propotation * 20) + this.system.statusBarHeight)) {  
+				y = ((this.propotation * 20) + this.system.statusBarHeight);  
+			}  
+			this.body.setStyle({  
+				top: y + 'px',  
+				left: x + 'px'  
+			});
+		})
+		/**
+		 * 这里有一个bug暂时无法解决,当用户快速往左滑时,滑动区域超出屏幕会监听不到touchend事件😂,很难被发现我就不解决了
+		 */
+		view.addEventListener("touchend", (event) => {
+			// console.log(this.cur, event)
+			var touch;
+			if (event.touches) {  
+				touch = event.touches[0];  
+			} else {  
+				touch = event;  
+			}
+			let differX = Math.abs(this.cur.pageX) - Math.abs(touch.pageX)
+			let differY = Math.abs(this.cur.pageY) - Math.abs(touch.pageY)
+			this.flag = false
+			// console.log(differX, differY)
+			if(Math.abs(differX) > 5 || Math.abs(differY) > 5) {	// 上下移动或左右移动超过5px则关闭弹窗
+				this.hide()
+			} else {	// 否则当作单击事件
+				console.log('-------------------')
+				this.hide()
+			}
+		})
+		this.body = view;
+		
+	// 	let bodyBg = new plus.nativeObj.View('bodyBg',{
+	// 		top: (this.propotation * 20) + this.system.statusBarHeight,
+	// 		left: this.propotation * 20,
+	// 		height: this.popupViewHeight,
+	// 		width: this.popupViewWidth,
+	// 		backgroundColor:'rgba(0, 0, 0, 1)',
+	// 	});
+	// 	bodyBg.draw([
+	// 	  {tag:'font',id:'confirm',text:'关闭关闭',textStyles:{color:'red',size:'16px'}},
+	// 	]);
+	
+	// 	bodyBg.addEventListener("click",(e)=>{
+	// 		console.log('---------------------')
+	// 	});
+	// 	this.bodyBg = bodyBg
+	}
+	// 显示/关闭弹框动画
+	modelAnimationOpenOrClose(type) {
+		var options = {type:type,duration:this.duration};
+		plus.nativeObj.View.startAnimation(options,this.body, () => {
+			// 关闭原生动画
+			plus.nativeObj.View.clearAnimation();
+		});
+	}
+	bgAnimationOpenOrClose(type) {
+		var options = {type:type,duration:this.duration};
+		plus.nativeObj.View.startAnimation(options,this.bodyBg, () => {
+			// 关闭原生动画
+			plus.nativeObj.View.clearAnimation();
+		});
+	}
+	// closeAnimation() {
+	// 	// push弹框距离最顶部的距离
+	// 	let top = (this.propotation * 20) + this.system.statusBarHeight
+	// 	// 完全隐藏时的顶部距离
+	// 	let hideTop = -this.system.statusBarHeight
+	// 	this.timer = setInterval(() => {
+	// 		this.top = this.top - 2
+	// 		if(this.top < hideTop * 2) {
+	// 			clearInterval(this.timer)
+	// 			this.timer = null
+	// 		}
+	// 		this.body.setStyle({
+	// 			top:this.top
+	// 		})
+	// 	}, 1)
+	// }
+	// 显示弹框
+	show() {
+		this.tips()
+		if(this.inApp) {
+			this.createView()
+			// this.modelAnimationOpenOrClose('slide-in-right')
+			this.body.show()
+			// this.bodyBg.show()
+			setTimeout(() => {
+				if(this.body) {
+					this.hide()
+				}
+			}, this.closeTime)
+		}
+	}
+	// 关闭弹框
+	hide() {
+		this.modelAnimationOpenOrClose('slide-out-right')
+		this.body.hide()
+		setTimeout(() => {
+			plus.nativeObj.View.clearAnimation();
+			this.body = null
+		}, this.duration)
+		// this.bgAnimationOpenOrClose('slide-out-right')
+		// this.bodyBg.hide()
+	}
+	// 调用系统提示音和振动
+	tips() {
+		if(this.voice) {
+			let system = uni.getSystemInfoSync().platform
+			if(system == 'ios') {
+				let player = plus.audio.createPlayer( "/static/audio/ios.mp3" );
+				player.play()
+			} else {
+				let main = plus.android.runtimeMainActivity();
+				let RingtoneManager = plus.android.importClass("android.media.RingtoneManager");
+				let uri = RingtoneManager.getActualDefaultRingtoneUri(main, RingtoneManager.TYPE_NOTIFICATION);
+				console.log(uri)
+				let MediaPlayer = plus.android.importClass("android.media.MediaPlayer");  
+				let player = MediaPlayer.create(main, uri);  
+				player.setLooping(false);  
+				player.prepare();  
+				player.start();
+			}
+		}
+		if(this.vibration) {
+			plus.device.vibrate()
+		}
+	}
+}
+
+export default appPush

+ 209 - 0
js_sdk/levine-APPPush/levine-APPPush/plugins/APPPush/h5_push.vue

@@ -0,0 +1,209 @@
+<template>
+	<view>
+		<transition name="slide-fade">
+			<view class="h5_push" @touchstart.stop.prevent="touchstart" @touchmove.stop.prevent="touchmove" @touchend.stop.prevent="touchend" v-if="show" :style="style">
+				<view class="push-title">
+					<view class="push-type">
+						<image src="/static/push/message-icon.png"></image>
+						{{messageType}}
+					</view>
+					{{messageTime}}
+				</view>
+				<view class="push-body">
+					<view class="push-content">
+						<view class="push-content-title">{{messageTitle}}</view>
+						<view class="push-content-text">{{messageContent}}</view>
+					</view>
+					<image :src="messageImage" class="push-img" mode="aspectFill"></image>
+				</view>
+			</view>
+		</transition>
+	</view>
+</template>
+
+<script>
+	export default{
+		data() {
+			return {
+				show: false,
+				// 关闭时间
+				closeTime: 3000,
+				// app内横幅提醒
+				inApp: false,
+				// 声音提醒
+				voice: true,
+				// 振动提醒
+				vibration: false,
+				// 消息分类
+				messageType: '',
+				// 通知标题
+				messageTitle: '',
+				// 时间
+				messageTime: '现在',
+				// 通知文案
+				messageContent: '',
+				// 缩略图
+				messageImage: '',
+				
+				top: 20,
+				left: 20,
+				cur: {
+					x: 0,
+					y: 0,
+					pageX: 0,
+					pageY: 0
+				}
+			}
+		},
+		computed:{
+			style() {
+				let system = uni.getSystemInfoSync()
+				let statusBarHeight = system.statusBarHeight
+				return `top: calc(${statusBarHeight}px + ${this.top}rpx);left: ${this.left}rpx`
+			}
+		},
+		created() {
+			setTimeout(() => {
+				this.show = false
+			}, this.closeTime)
+		},
+		methods:{
+			touchstart(event) {
+				console.log(event)
+				var touch;  
+				if (event.touches) {
+					touch = event.touches[0];  
+				} else {  
+					touch = event;  
+				}  
+				this.cur.x = touch.clientX;  
+				this.cur.y = touch.clientY;
+				this.cur.pageX = touch.pageX;
+				this.cur.pageY = touch.pageY;  
+				console.log(this.cur)
+			},
+			touchmove(event) {
+				var touch;
+				if (event.touches) {  
+					touch = event.touches[0];  
+				} else {  
+					touch = event;
+				}  
+				let moveX = touch.pageX - this.cur.x;   
+				let moveY = touch.pageY - this.cur.y;   
+				let x = moveX;  
+				let y = moveY;
+				// console.log(x, y)
+				// console.log(this.cur, touch)
+				let system = uni.getSystemInfoSync()
+				if (y >= (uni.upx2px(20) + system.statusBarHeight)) {  
+					y = (uni.upx2px(20) + system.statusBarHeight);  
+				}
+				this.top = y / (uni.upx2px(y) / y)
+				this.left = x / (uni.upx2px(x) / x)
+				
+				// this.body.setStyle({  
+				// 	top: y + 'px',  
+				// 	left: x + 'px'  
+				// });
+			},
+			touchend(event) {
+				console.log(event)
+				var touch;
+				if (event.touches.length) {  
+					touch = event.touches[0];  
+				} else {  
+					touch = event.changedTouches[0];  
+				}
+				console.log(this.cur, touch)
+				let differX = Math.abs(this.cur.pageX) - Math.abs(touch.pageX)
+				let differY = Math.abs(this.cur.pageY) - Math.abs(touch.pageY)
+				// console.log(differX, differY)
+				if(Math.abs(differX) > 5 || Math.abs(differY) > 5) {	// 上下移动或左右移动超过5px则关闭弹窗
+					this.show = false
+				} else {	// 否则当作单击事件
+					console.log('-------------------')
+					this.show = false
+				}
+			}
+		}
+	}
+</script>
+
+<style lang="scss" scoped>
+	.h5_push{
+		width: 710rpx;
+		height: 192rpx;
+		background: #FFFFFF;
+		box-shadow: 0px 3rpx 18rpx 0px rgba(54, 58, 68, 0.08);
+		border-radius: 20rpx;
+		position: fixed;
+		z-index: 9999999;
+		.push-title{
+			padding: 30rpx 30rpx 15rpx;
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			font-size: 24rpx;
+			font-weight: 400;
+			color: #4F555B;
+			.push-type{
+				display: flex;
+				align-items: center;
+				font-size: 24rpx;
+				font-weight: 400;
+				color: #4F555B;
+				image{
+					width: 24rpx;
+					height: 24rpx;
+					margin-right: 10rpx;
+				}
+			}
+		}
+		.push-body{
+			display: flex;
+			align-items: center;
+			justify-content: space-between;
+			padding: 0 24rpx 0 30rpx;
+			.push-content{
+				width: calc(100% - 150rpx);
+				.push-content-title{
+					font-size: 30rpx;
+					font-weight: 500;
+					color: #202123;
+					margin-bottom: 20rpx;
+					overflow: hidden;
+					text-overflow: ellipsis;
+					white-space: nowrap;
+				}
+				.push-content-text{
+					font-size: 24rpx;
+					font-weight: 400;
+					color: #4F555B;
+					overflow: hidden;
+					text-overflow: ellipsis;
+					white-space: nowrap;
+				}
+			}
+			.push-img{
+				width: 100rpx;
+				height: 100rpx;
+				background: #F2F2F3;
+				border: 0.5px solid #E9E9E9;
+				border-radius: 10rpx;
+				margin-left: 50rpx;
+			}
+		}
+	}
+	.slide-fade-enter-active {
+	  transition: all .3s ease;
+	}
+	.slide-fade-leave-active {
+	  transition: all .3s cubic-bezier(1.0, 0.5, 0.8, 1.0);
+	}
+	.slide-fade-enter, .slide-fade-leave-to
+	/* .slide-fade-leave-active for below version 2.1.8 */ {
+	  transform: translateX(10px);
+	  opacity: 0;
+	}
+</style>

+ 29 - 0
js_sdk/levine-APPPush/levine-APPPush/plugins/APPPush/index.js

@@ -0,0 +1,29 @@
+import app_push from './app_push.js'
+import h5Push from './h5_push.vue'
+
+const appPush = {
+	install: function(Vue) {
+		Vue.prototype.$appPush = function(op = {}) {
+			// #ifdef APP-PLUS
+			new app_push({
+				...op
+			}).show();
+			// #endif
+			// #ifdef H5
+			// Vue.component('h5Push', h5Push)
+			// 创建构造器
+			const H5PushInstance = Vue.extend(h5Push)
+			let instance = new H5PushInstance({
+				data: op
+			})
+			instance.$mount()
+			document.body.appendChild(instance.$el)
+			Vue.nextTick(() => {
+				instance.show = true
+			})
+			// #endif
+		}
+	}
+}
+
+export default appPush

BIN
js_sdk/levine-APPPush/levine-APPPush/static/audio/ios.mp3


BIN
js_sdk/levine-APPPush/levine-APPPush/static/logo.png


BIN
js_sdk/levine-APPPush/levine-APPPush/static/push/activity.png


BIN
js_sdk/levine-APPPush/levine-APPPush/static/push/img-bg.png


BIN
js_sdk/levine-APPPush/levine-APPPush/static/push/message-icon.png


+ 13 - 0
js_sdk/levine-APPPush/package.json

@@ -0,0 +1,13 @@
+{
+    "id": "levine-APPPush",
+    "name": "自定义推送弹框,App,h5站内信弹框",
+    "version": "1.0.0",
+    "description": "自定义的推送弹框,非调用系统弹框,只支持app和h5,app端支持振动,系统提示音",
+    "keywords": [
+        "推送",
+        "自定义推送",
+        "push",
+        "native.js",
+        "通知"
+    ]
+}

+ 5 - 1
main.js

@@ -1,5 +1,5 @@
 import App from './App'
-
+import appPush from '@/js_sdk/levine-APPPush/levine-APPPush/plugins/APPPush/index.js'
 import Print from 'vue3-print-nb'
 // #ifndef VUE3
 import Vue from 'vue'
@@ -12,6 +12,7 @@ const app = new Vue({
 app.$mount()
 // #endif
 
+
 // 封装弹框的方法
 uni.$showMsg = (title = '数据请求失败!', duration = 1500) => {
 	uni.showToast({
@@ -20,12 +21,15 @@ uni.$showMsg = (title = '数据请求失败!', duration = 1500) => {
 		icon: 'none'
 	})
 }
+uni.$appPush = appPush
+
 
 // #ifdef VUE3
 import { createSSRApp } from 'vue'
 export function createApp() {
   const app = createSSRApp(App)
 	app.use(Print)
+	// app.use(appPush)
   return {
     app
   }

+ 44 - 18
pages/detail/detail.vue

@@ -16,7 +16,7 @@
 					<view class="mid">
 						<text class="title">中药处方笺</text>	
 					</view>
-					<view class="rig"><text class="title">{{v.pres_type}}</text></view>
+					<view class="rig"><text class="title">{{v.presType}}</text></view>
 				</view>
 				<view class="patiinfo">
 					<view class="r1">
@@ -24,11 +24,11 @@
 						<view class="row">性别:{{v.sex}}</view>
 						<view class="row">年龄:{{v.age}}岁</view>
 						<view class="row">电话:{{v.tel}}</view>
-						<view class="row">当前处方状态:{{v.pres_status}}</view>
+						<view class="row">当前处方状态:{{v.status}}</view>
 					</view>
 					<view class="r2">
-						<view class="row">就诊科室:{{v.office}}</view>
-						<view class="row">临床诊断:{{v.dis_name}}—{{v.sym_name}}</view>
+						<view class="row">就诊科室:{{v.department}}</view>
+						<view class="row">临床诊断:{{v.disName}}—{{v.symName}}</view>
 						<view class="row">开方时间:{{v.prescriptionTime}}</view>
 					</view>
 					<view class="r3">联系地址:{{v.addr}}</view>
@@ -65,14 +65,14 @@
 			<view class="amountarea">
 				<view class="amount">
 					<view class="r1">
-						<view class="pijw">药品金额:{{v.money.drugs_amount}}</view>
+						<view class="pijw">药品金额:{{v.prescriptionSum}}</view>
 					</view>
 					<view class="r2">
-						<view class="jyf">煎药费:{{v.money.cook_fee}}</view>
-						<view class="psf">配送费:{{v.money.delie_fee}}</view>
+						<view class="jyf">煎药费:{{v.daijianCost}}</view>
+						<view class="psf">配送费:{{v.distributionCost}}</view>
 					</view>
 					<view class="r3">
-						总金额:{{v.money.summary}}
+						总金额:{{v.prescriptionTotleSum}}
 						<!-- <view class="zjw"></view> -->
 					</view>
 				</view>
@@ -106,6 +106,7 @@ import { onMounted, ref } from 'vue'
 import { selectOrderDetail } from "@/static/api.js"
 import { onLoad } from '@dcloudio/uni-app'
 
+const preseId = ref(11220822134401)
 const preseObj = ref({
 		code: '11220822134401',
 		color:['#000'], // 条形码的颜色
@@ -119,16 +120,16 @@ const barOpations = ref({
 })
 
 const v=ref({
-	pres_id:11220822134401,
-	pres_type:'普通处方',
+	preNo:11220822134401,
+	presType:'普通处方',
 	name:'李某',
 	sex:'男',
 	age:35,
 	tel:'13888888888',
 	pres_status: '发药',
 	office:'中医内科',
-	dis_name:'胃脘痛病',
-	sym_name:'脾胃虚寒证',
+	disName:'胃脘痛病',
+	symName:'脾胃虚寒证',
 	prescriptionTime:'2023-06-01 15:58',
 	addr:'浙江省某某事某某去某某事中医院门诊楼三楼302是',
 	rp:[
@@ -207,11 +208,15 @@ onMounted(() => {
 
 })
 
-onLoad(async() => {
+onLoad(async(options) => {
+	console.log('options', options)
+	const token = uni.getStorageSync('token')
+	const userId = uni.getStorageSync('userId')
 	const params = {
 		token: token,
 		data: {
-			id: userId,
+			preId: options.preId,
+			userId: userId,
 		}
 	}
 	const {data:res } = selectOrderDetail(params)
@@ -220,7 +225,7 @@ onLoad(async() => {
 		v.value.name = res.data.name,
 		v.value.sex = res.data.sex,
 		v.value.age = res.data.age,
-		v.value.deployState = res.data.deployState,
+		
 		v.value.disName = res.data.disName,
 		v.value.symName = res.data.symName,
 		v.value.preNo = res.data.preNo,
@@ -234,8 +239,29 @@ onLoad(async() => {
 		v.value.entrust = res.data.entrust,
 		v.value.rp = res.data.detailList
 		
-		
-		preseObj.value.code = res.data.preNo,
+		// v.value.status = res.data.status,
+		switch (res.data.status) {
+			case '1':
+				v.value.status = '配药'
+				break
+			case '2':
+				v.value.status = '煎药'
+				break
+			case '3':
+				v.value.status = '发药'
+				break
+			case '4':
+				v.value.status = '配送'
+				break
+			case '5':
+				v.value.status = '已分配'
+				break
+			case '6':
+				v.value.status = '已传送'
+				break
+			default:
+				v.value.status = '配药'
+		}
 	}
 })
 
@@ -252,7 +278,7 @@ const handleBack =()=>{
 	display: flex;
 	flex-direction:column;
 	justify-content:flex-start;
-	height: 2000px;
+
 	width: 1200px;
 	.content{
 		margin: 10px;

+ 64 - 19
pages/edit/edit.vue

@@ -10,13 +10,13 @@
 					<view class="left">
 						<view class="baracode">
 							<w-barcode :options="preseObj"></w-barcode>
-							<view class="barnum">{{v.pres_id}}</view>
+							<view class="barnum">{{v.preNo}}</view>
 						</view>
 					</view>
 					<view class="mid">
 						<text class="title">中药处方笺</text>	
 					</view>
-					<view class="rig"><text class="title">{{v.pres_type}}</text></view>
+					<view class="rig"><text class="title">{{v.presType}}</text></view>
 				</view>
 				<view class="patiinfo">
 					<view class="r1">
@@ -24,12 +24,12 @@
 						<view class="row">性别:{{v.sex}}</view>
 						<view class="row">年龄:{{v.age}}岁</view>
 						<view class="row">电话:{{v.tel}}</view>
-						<view class="row status">当前处方状态:{{v.pres_status}}</view>
+						<view class="row status">当前处方状态:{{v.status}}</view>
 					</view>
 					<view class="r2">
-						<view class="row">就诊科室:{{v.office}}</view>
-						<view class="row">临床诊断:{{v.dis_name}}—{{v.sym_name}}</view>
-						<view class="row">开方时间:{{v.create_at}}</view>
+						<view class="row">就诊科室:{{v.department}}</view>
+						<view class="row">临床诊断:{{v.disName}}—{{v.symName}}</view>
+						<view class="row">开方时间:{{v.prescriptionTime}}</view>
 					</view>
 					<view class="r3">联系地址:{{v.addr}}</view>
 				</view>
@@ -67,14 +67,14 @@
 			<view class="amountarea">
 				<view class="amount">
 					<view class="r1">
-						<view class="pijw">药品金额:{{v.money.drugs_amount}}</view>
+						<view class="pijw">药品金额:{{v.prescriptionSum}}</view>
 					</view>
 					<view class="r2">
-						<view class="jyf">煎药费:{{v.money.cook_fee}}</view>
-						<view class="psf">配送费:{{v.money.delie_fee}}</view>
+						<view class="jyf">煎药费:{{v.daijianCost}}</view>
+						<view class="psf">配送费:{{v.distributionCost}}</view>
 					</view>
 					<view class="r3">
-						总金额:{{v.money.summary}}
+						总金额:{{v.prescriptionTotleSum}}
 						<!-- <view class="zjw"></view> -->
 					</view>
 				</view>
@@ -156,7 +156,6 @@
 import { onMounted, ref, getCurrentInstance } from 'vue'
 import { selectOrderDetail } from "@/static/api.js"
 import { onLoad } from '@dcloudio/uni-app'
-
 const preseId = ref(11220822134401)
 const preseObj = ref({
 		code: '11220822134401',
@@ -197,17 +196,17 @@ const bindTextInput = (e)=>{
 	console.log(e.detail.value)
 }
 const v=ref({
-	pres_id:11220822134401,
-	pres_type:'普通处方',
+	preNo:11220822134401,
+	presType:'普通处方',
 	name:'李某',
 	sex:'男',
 	age:35,
 	tel:'13888888888',
 	pres_status: '发药',
 	office:'中医内科',
-	dis_name:'胃脘痛病',
-	sym_name:'脾胃虚寒证',
-	create_at:'2023-06-01 15:58',
+	disName:'胃脘痛病',
+	symName:'脾胃虚寒证',
+	prescriptionTime:'2023-06-01 15:58',
 	addr:'浙江省某某事某某去某某事中医院门诊楼三楼302是',
 	rp:[
 		{name:'车前子',num:'6g',tips:'包煎',sign:'医生签名'},
@@ -285,15 +284,61 @@ onMounted(() => {
 
 })
 
-
-onLoad(async() => {
+onLoad(async(options) => {
+	console.log('options', options)
+	const token = uni.getStorageSync('token')
+	const userId = uni.getStorageSync('userId')
 	const params = {
 		token: token,
 		data: {
-			id: userId,
+			preId: options.preId,
+			userId: userId,
 		}
 	}
 	const {data:res } = selectOrderDetail(params)
+	if (res.code === 200) {
+		v.prescriptionTime = res.data.prescriptionTime,
+		v.value.name = res.data.name,
+		v.value.sex = res.data.sex,
+		v.value.age = res.data.age,
+		
+		v.value.disName = res.data.disName,
+		v.value.symName = res.data.symName,
+		v.value.preNo = res.data.preNo,
+		v.value.department = res.data.department,
+		v.value.dosageForm = res.data.dosageForm,
+		v.value.number = res.data.number,
+		v.value.prescriptionSum = res.data.prescriptionSum,
+		v.value.prescriptionTotalSum = res.data.prescriptionTotalSum,
+		v.value.daijianCost = res.data.daijianCost,
+		v.value.distributionCost = res.data.distributionCost,
+		v.value.entrust = res.data.entrust,
+		v.value.rp = res.data.detailList
+		
+		// v.value.status = res.data.status,
+		switch (res.data.status) {
+			case '1':
+				v.value.status = '配药'
+				break
+			case '2':
+				v.value.status = '煎药'
+				break
+			case '3':
+				v.value.status = '发药'
+				break
+			case '4':
+				v.value.status = '配送'
+				break
+			case '5':
+				v.value.status = '已分配'
+				break
+			case '6':
+				v.value.status = '已传送'
+				break
+			default:
+				v.value.status = '配药'
+		}
+	}
 })
 
 const handleGetRps = (v)=>{

+ 1 - 0
pages/login/login.vue

@@ -71,6 +71,7 @@ const submit = async ()=> {
 	if (res.code === 200 && res.token) {
 		uni.setStorageSync('token', res.token)
 		uni.setStorageSync('userId', res.userId)
+		uni.$emit('login',{userId:res.userId})
 		const tokens = uni.getStorageSync('token')
 		const userId = uni.getStorageSync('userId')
 		const params = {

+ 9 - 0
static/api.js

@@ -53,3 +53,12 @@ export const releaseOrder = (data) => {
 		data: data.data
 	})
 }
+
+// 通知
+// export const notice = (data) => {
+// 	return service({
+// 		url: '/webSocket/sentMessage',
+// 		method: 'POST',
+// 		data: data.data
+// 	})
+// }

+ 90 - 0
static/websocket.js

@@ -0,0 +1,90 @@
+const _WEBSOCKET = {
+  //是否打开连接
+  isOpen: false,
+  //连接socket
+  connectSocket(url,successFunc = null, errorFunc = null) {
+    try {
+      //连接socket
+      uni.connectSocket({
+        url,
+        success() {
+          console.log('websocket连接成功!')
+        }
+      })
+      //监听socket连接
+      uni.onSocketOpen((res) => {
+        this.isOpen = true
+        console.log('WebSocket连接已打开!')
+        if (successFunc) {
+          successFunc(res)
+        }
+      })
+      //监听socket连接失败
+      uni.onSocketError((res) => {
+        this.isOpen = false
+        console.log('WebSocket连接打开失败,请检查!')
+        if (errorFunc) {
+          errorFunc(res)
+        }
+      })
+      //监听收到消息
+      uni.onSocketMessage((res) => {
+        console.log('收到服务器内容:' + res.data)
+				params = {
+					inApp: true, // app内横幅提醒
+					voice: true,    // 声音提醒
+					vibration: true,    // 振动提醒
+					messageType: '', //消息分类
+					messageTitle: '', //通知标题
+					messageContent: '中药煎配溯源管理来新处方啦!',
+					messageImage: ''
+				}
+				uni.$appPush(params)
+				uni.redirectTo({
+					url:"/pages/index/index"
+				})
+      })
+      //监听socket关闭
+      uni.onSocketClose((res) => {
+        console.log('WebSocket 已关闭!')
+        this.isOpen = false
+      })
+    } catch (error) {
+      console.log('err:' + error)
+    }
+  },
+  //发送消息
+  sendMessage(msg = '', successFunc = null, errorFunc = null) {
+    if (!this.isOpen || !msg) {
+      if (errorFunc) {
+        errorFunc('未传消息内容或连接未打开!')
+      }
+      return
+    }
+    uni.sendSocketMessage({
+      data: msg,
+      success(res) {
+        console.log('消息发送成功!')
+        if (successFunc) {
+          successFunc(res)
+        }
+      },
+      fail(err) {
+        console.log('消息发送失败!')
+        if (errorFunc) {
+          errorFunc(err)
+        }
+      }
+    })
+  },
+  //关闭连接
+  closeSocket() {
+    if (!this.isOpen) {
+      return
+    }
+    //关闭socket连接
+    uni.closeSocket()
+  }
+}
+
+export default _WEBSOCKET