H5+MUI+Node.js+Socket.io群组即时聊天+发送图片+图片压缩

Posted 云上人间钦自赏

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了H5+MUI+Node.js+Socket.io群组即时聊天+发送图片+图片压缩相关的知识,希望对你有一定的参考价值。

<!DOCTYPE html>
<html>
	<head>
		<meta charset="utf-8">
		<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
		<title></title>
		<link href="css/mui.min.css" rel="stylesheet" />
		<!--<link rel="stylesheet" type="text/css" href="css/app.css" />-->
		<link href="css/mui.imageviewer.css" rel="stylesheet" />
		<link rel="stylesheet" href="css/iconfont.css">
			
		<!–[if lt IE 8]><script src="js/json3.js"></script><![endif]–> 
		<style type="text/css">
			.mui-bar-nav {
				background-color: #00abed;
				-webkit-box-shadow: none;
				box-shadow: none;
			}
			.mui-bar {
				height: 80px;
				line-height: 80px;
			}
			.mui-title {
				color: #fff;
				font-weight: bold;
			}
			.msg-my-img{
				float: right;
				width: 38px;
				height: 38px;
				border-radius: 3px;
				color: #ddd;
				vertical-align: top;
				text-align: center;
			}
		</style>
		<style>
			html,
			body {
				height: 100%;
				margin: 0px;
				padding: 0px;
				overflow: hidden;
				-webkit-touch-callout: none;
				-webkit-user-select: none;
			}
			footer {
				position: fixed;
				width: 100%;
				height: 50px;
				min-height: 50px;
				border-top: solid 1px #bbb;
				left: 0px;
				bottom: 0px;
				overflow: hidden;
				padding: 0px 50px;
				background-color: #fafafa;
			}
			.footer-left {
				position: absolute;
				width: 50px;
				height: 50px;
				left: 0px;
				bottom: 0px;
				text-align: center;
				vertical-align: middle;
				line-height: 100%;
				padding: 12px 4px;
			}
			.footer-right {
				position: absolute;
				width: 50px;
				height: 50px;
				right: 0px;
				bottom: 0px;
				text-align: center;
				vertical-align: middle;
				line-height: 100%;
				padding: 12px 5px;
				padding-top:15px;
				display: inline-block;
			}
			.footer-center {
				height: 100%;
				padding: 5px 0px;
				position: absolute;
				left:50px;
				right: 50px;
			}
			.footer-center [class*=input] {
				width: 100%;
				height: 100%;
				border-radius: 5px;
			}
			.footer-center .input-text {
				background: #fff;
				border: solid 1px #ddd;
				padding: 10px !important;
				font-size: 16px !important;
				line-height: 18px !important;
				font-family: verdana !important;
				overflow: hidden;
			}
			.footer-center .input-sound {
				background-color: #eee;
			}
			.mui-content {
				height: 100%;
				padding: 44px 0px 50px 0px;
				overflow: auto;
				background-color: #eaeaea;
			}
			#msg-list {
				height: 100%;
				overflow: auto;
				-webkit-overflow-scrolling: touch;
			}
			.msg-item {
				padding: 8px;
				clear: both;
			}
			.msg-item .mui-item-clear {
				clear: both;
			}
			.msg-item .msg-user {
				width: 38px;
				height: 38px;
				border: solid 1px #d3d3d3;
				display: inline-block;
				background: #fff;
				border-radius: 3px;
				vertical-align: top;
				text-align: center;
				float: left;
				padding: 3px;
				color: #ddd;
			}
			
			.msg-item .msg-user-img{
				width: 38px;
				height: 38px;
				display: inline-block;
				border-radius: 3px;
				vertical-align: top;
				text-align: center;
				float: left;
				color: #ddd;
			}
			
			.msg-item .msg-content {
				display: inline-block;
				border-radius: 5px;
				border: solid 1px #d3d3d3;
				background-color: #FFFFFF;
				color: #333;
				padding: 8px;
				vertical-align: top;
				font-size: 15px;
				position: relative;
				margin: 0px 8px;
				max-width: 75%;
				min-width: 35px;
				float: left;
				word-break:break-all;
			}
			.msg-item .msg-content .msg-content-inner {
				overflow-x: hidden;
			}
			.msg-item .msg-content .msg-content-arrow {
				position: absolute;
				border: solid 1px #d3d3d3;
				border-right: none;
				border-top: none;
				background-color: #FFFFFF;
				width: 10px;
				height: 10px;
				left: -5px;
				top: 12px;
				-webkit-transform: rotateZ(45deg);
				transform: rotateZ(45deg);
			}
			.msg-item-self .msg-user,
			.msg-item-self .msg-content {
				float: right;
			}
			.msg-item-self .msg-content .msg-content-arrow {
				left: auto;
				right: -5px;
				-webkit-transform: rotateZ(225deg);
				transform: rotateZ(225deg);
			}
			.msg-item-self .msg-content,
			.msg-item-self .msg-content .msg-content-arrow {
				background-color: #4CD964;
				color: #fff;
				border-color: #2AC845;
				word-break:break-all;
			}
			footer .mui-icon {
				color: #000;
			}
			footer .mui-icon:active {
				color: #007AFF !important;
			}
			footer .mui-icon-paperplane:before {
				content: "发送";
			}
			footer .mui-icon-paperplane {
				/*-webkit-transform: rotateZ(45deg);
				transform: rotateZ(45deg);*/
				
				font-size: 16px;
				word-break: keep-all;
				line-height: 100%;
				padding-top: 6px;
				color: rgba(0, 135, 250, 1);
				font-style: normal;
			}
			#msg-sound {
				-webkit-user-select: none !important;
				user-select: none !important;
			}
			.rprogress {
				position: absolute;
				left: 50%;
				top: 50%;
				width: 140px;
				height: 140px;
				margin-left: -70px;
				margin-top: -70px;
				background-image: url(../images/arecord.png);
				background-repeat: no-repeat;
				background-position: center center;
				background-size: 30px 30px;
				background-color: rgba(0, 0, 0, 0.7);
				border-radius: 5px;
				display: none;
				-webkit-transition: .15s;
			}
			.rschedule {
				background-color: rgba(0, 0, 0, 0);
				border: 5px solid rgba(0, 183, 229, 0.9);
				opacity: .9;
				border-left: 5px solid rgba(0, 0, 0, 0);
				border-right: 5px solid rgba(0, 0, 0, 0);
				border-radius: 50px;
				box-shadow: 0 0 15px #2187e7;
				width: 46px;
				height: 46px;
				position: absolute;
				left: 50%;
				top: 50%;
				margin-left: -23px;
				margin-top: -23px;
				-webkit-animation: spin 1s infinite linear;
				animation: spin 1s infinite linear;
			}
			.r-sigh{
				display: none;
				border-radius: 50px;
				box-shadow: 0 0 15px #2187e7;
				width: 46px;
				height: 46px;
				position: absolute;
				left: 50%;
				top: 50%;
				margin-left: -23px;
				margin-top: -23px;
				text-align: center;
				line-height: 46px;
				font-size: 40px;
				font-weight: bold;
				color: #2187e7;
			}
			.rprogress-sigh{
				background-image: none !important;
			}
			.rprogress-sigh .rschedule{
				display: none !important;
			}
			.rprogress-sigh .r-sigh{
				display: block !important;
			}
			.rsalert {
				font-size: 12px;
				color: #bbb;
				text-align: center;
				position: absolute;
				border-radius: 5px;
				width: 130px;
				margin: 5px 5px;
				padding: 5px;
				left: 0px;
				bottom: 0px;
			}
			@-webkit-keyframes spin {
				0% {
					-webkit-transform: rotate(0deg);
				}
				100% {
					-webkit-transform: rotate(360deg);
				}
			}
			@keyframes spin {
				0% {
					transform: rotate(0deg);
				}
				100% {
					transform: rotate(360deg);
				}
			}
			#h {
				background: #fff;
				border: solid 1px #ddd;
				padding: 10px !important;
				font-size: 16px !important;
				font-family: verdana !important;
				line-height: 18px !important;
				overflow: visible;
				position: absolute;
				left: -1000px;
				right: 0px;
				word-break: break-all;
				word-wrap: break-word;
			}
			.cancel {
				background-color: darkred;
			}
			.send_title{font-size: small;}
		</style>
	</head>

	<body contextmenu="return false;">
		<header class="mui-bar mui-bar-nav">
			<div style="margin-top:30px;">
			<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left" style="color: #fff;font-size: 26px;"></a>
			<h1 class="mui-title"><span id="name"></span></h1>
			</div>
		</header>
		<pre id='h'></pre>
		<script id='msg-template' type="text/template">
			<% for(var i in record){ var item=record[i]; %>
				<div class="msg-item <%= (item.sender=='self'?' msg-item-self':'') %>" msg-type='<%=(item.type)%>' msg-content='<%=(item.content)%>'>
					<div style="height: 30px;text-align: center;font-size: small;color: #a6a6a6;"><%=item.addtime %></div>
					<% if(item.sender=='self' ) { %>
						<!--<i class="msg-user mui-icon mui-icon-person"></i>-->
						<img class="msg-my-img" src="<%=(item.upic)%>" alt="" />
					<% } else { %>
						<img class="msg-user-img"  src="<%=item.upic%>" alt="" />
						
						<span class="send_title" style="margin-left: 4px;"><%=item.uname%></span><br/>
						
					<% } %>
					<div class="msg-content">
						<div class="msg-content-inner">
							<% if(item.type=='text' ) { %>
								<%=( item.content|| '  ') %>
							<% } else if(item.type=='image' ) { %>
								<img class="msg-content-image" src="<%=(item.content)%>" style="max-width: 100px;" />
							<% } else if(item.type=='sound' ) { %>
								<span class="mui-icon iconfont icon-yuyin" style="font-size: 18px;font-weight: bold;"></span>
								<span class="play-state">点击播放</span>
							<% } %>
						</div>
						<div class="msg-content-arrow"></div>
					</div>
					<div class="mui-item-clear"></div>
				</div>
			<% } %>
		</script>
		<div class="mui-content" style="padding-top:70px;">
			<div id='msg-list'>
			</div>
		</div>
		<footer>
			<div class="footer-left">
				<i id='msg-image' class="mui-icon iconfont icon-paizhao" style="font-size: 28px;"></i>
			</div> 
			<div class="footer-center">
				<textarea id='msg-text' type="text" class='input-text'></textarea>
				<button id='msg-sound' type="button" class='input-sound' style="display: none;">按住说话</button>
			</div>
			<label for="" class="footer-right">
				<i id='msg-type' class="mui-icon-paperplane"></i>
				<!--<i id='msg-type' class="mui-icon mui-icon-mic"></i>-->
			</label>
		</footer>
		<div id='sound-alert' class="rprogress">
			<div class="rschedule"></div>
			<div class="r-sigh">!</div>
			<div id="audio_tips" class="rsalert">手指上滑,取消发送</div>
		</div>
		<input type="hidden" id="hdgroupid" />
		<script src="js/mui.min.js"></script>
		<script src="js/jquery-1.7.js" type="text/javascript" charset="utf-8"></script>
		<script src="js/mui.imageViewer.js"></script>
		<script src="js/arttmpl.js"></script>
		<script src="js/db.js"></script>
		<script src="js/login.js" type="text/javascript" charset="utf-8"></script>
		<script src="http://121.40.205.128:3000/socket.io/socket.io.js"></script>
		<script type="text/javascript" charset="utf-8">
			document.addEventListener("plusready", plusReady, false);

			function plusReady() {
				document.getElementById("hdgroupid").value=plus.webview.currentWebview().groupid;
			}
			mui.init({
				beforeback:function(){
					localStorage.chartitem="none";
				}
			})
		
		
			//var bindMsgList;
			(function($, doc) {
				var MIN_SOUND_TIME = 800;
				$.init({
					gestureConfig: {
						tap: true, //默认为true
						doubletap: true, //默认为false
						longtap: true, //默认为false
						swipe: true, //默认为true
						drag: true, //默认为true
						hold: true, //默认为false,不监听
						release: true //默认为false,不监听
					}
				});
				template.config('escape', false);
				$.plusReady(function() {
					
					localStorage.chartitem="show";
					
					document.getElementById("name").innerText=plus.webview.currentWebview().name;
					plus.webview.currentWebview().setStyle({
						softinputMode: "adjustResize"
					});
					var showKeyboard = function() {
						if ($.os.ios) {
							var webView = plus.webview.currentWebview().nativeInstanceObject();
							webView.plusCallMethod({
								"setKeyboardDisplayRequiresUserAction": false
							});
						} else {
							var Context = plus.android.importClass("android.content.Context");
							var InputMethodManager = plus.android.importClass("android.view.inputmethod.InputMethodManager");
							var main = plus.android.runtimeMainActivity();
							var imm = main.getSystemService(Context.INPUT_METHOD_SERVICE);
							imm.toggleSoftInput(0, InputMethodManager.SHOW_FORCED);
							//var view = ((ViewGroup)main.findViewById(android.R.id.content)).getChildAt(0);
							imm.showSoftInput(main.getWindow().getDecorView(), InputMethodManager.SHOW_IMPLICIT);
						}
					};
					var record = [];
					var ui = {
						body: doc.querySelector('body'),
						footer: doc.querySelector('footer'),
						footerRight: doc.querySelector('.footer-right'),
						footerLeft: doc.querySelector('.footer-left'),
						btnMsgType: doc.querySelector('#msg-type'),
						boxMsgText: doc.querySelector('#msg-text'),
						boxMsgSound: doc.querySelector('#msg-sound'),
						btnMsgImage: doc.querySelector('#msg-image'),
						areaMsgList: doc.querySelector('#msg-list'),
						boxSoundAlert: doc.querySelector('#sound-alert'),
						h: doc.querySelector('#h'),
						content: doc.querySelector('.mui-content')
					};
					ui.h.style.width = ui.boxMsgText.offsetWidth + 'px';
					//alert(ui.boxMsgText.offsetWidth );
					var footerPadding = ui.footer.offsetHeight - ui.boxMsgText.offsetHeight;
					var msgItemTap = function(msgItem, event) {
						var msgType = msgItem.getAttribute('msg-type');
						var msgContent = msgItem.getAttribute('msg-content')
						if (msgType == 'sound') {
							player = plus.audio.createPlayer(msgContent);
							var playState = msgItem.querySelector('.play-state');
							playState.innerText = '正在播放...';
							player.play(function() {
								playState.innerText = '点击播放';
							}, function(e) {
								playState.innerText = '点击播放';
							});
						}
					};
					var imageViewer = new $.ImageViewer('.msg-content-image', {
						dbl: false
					});
					var bindMsgList = function() {
						//绑定数据:
						ui.areaMsgList.innerHTML = template('msg-template', {
							"record": record
						});
						var msgItems = ui.areaMsgList.querySelectorAll('.msg-item');
						[].forEach.call(msgItems, function(item, index) {
							item.addEventListener('tap', function(event) {
								msgItemTap(item, event);
							}, false);
						});
						imageViewer.findAllImage();
						setTimeout(function(){
							ui.areaMsgList.scrollTop = ui.areaMsgList.scrollHeight + ui.areaMsgList.offsetHeight;	
						},500);
						
//						ui.areaMsgList.scrollToBottom(200);
					};
					
					bindMsgList();
					window.addEventListener('resize', function() {
						ui.areaMsgList.scrollTop = ui.areaMsgList.scrollHeight + ui.areaMsgList.offsetHeight;
					}, false);
					var send = function(msg) {
						record.push(msg);
						bindMsgList();
					};
					var toRobot = function(info) {
						bindMsgList();
					};

					function msgTextFocus() {
							ui.boxMsgText.focus();
							setTimeout(function() {
								ui.boxMsgText.focus();
							}, 150);
						}
						//解决长按“发送”按钮,导致键盘关闭的问题;
					ui.footerRight.addEventListener('touchstart', function(event) {
						
						if (ui.btnMsgType.classList.contains('mui-icon-paperplane')) {
							msgTextFocus();
							event.preventDefault();
						}
					});
					//解决长按“发送”按钮,导致键盘关闭的问题;
					ui.footerRight.addEventListener('touchmove', function(event) {
						if (ui.btnMsgType.classList.contains('mui-icon-paperplane')) {
							msgTextFocus();
							event.preventDefault();
						}
					});
					ui.footerRight.addEventListener('release', function(event) {
						//
						if(ui.boxMsgText.value.length<1){
							
							return;
						}
						
						if (ui.btnMsgType.classList.contains('mui-icon-paperplane')) {
							//showKeyboard();
							ui.boxMsgText.focus();
							setTimeout(function() {
								ui.boxMsgText.focus();
							}, 150);
							//							event.detail.gesture.preventDefault();
							
							//接收服务器端显示,取代本地显示
							/*send({
								sender: 'self',
								type: 'text',
								content: ui.boxMsgText.value.replace(new RegExp('\\n', 'gm'), '<br/>')
							});*/
							var content=ui.boxMsgText.value.replace(new RegExp('\\n', 'gm'), '<br/>');
							ui.boxMsgText.value = '';
							$.trigger(ui.boxMsgText, 'input', null);
							
							//alert(plus.webview.currentWebview().account+"ee");
							//同步内容
							CHAT.submit(content,plus.webview.currentWebview().account);//接收者
							
						} else if (ui.btnMsgType.classList.contains('icon-yuyin')) {
							ui.btnMsgType.classList.add('icon-xiepinglun');
							ui.btnMsgType.classList.remove('icon-yuyin');
							ui.boxMsgText.style.display = 'none';
							ui.boxMsgSound.style.display = 'block';
							ui.boxMsgText.blur();
							document.body.focus();
						} else if (ui.btnMsgType.classList.contains('icon-xiepinglun')) {
							ui.btnMsgType.classList.add('icon-yuyin');
							ui.btnMsgType.classList.remove('icon-xiepinglun');
							ui.boxMsgSound.style.display = 'none';
							ui.boxMsgText.style.display = 'block';
							//--
							//showKeyboard();
							ui.boxMsgText.focus();
							setTimeout(function() {
								ui.boxMsgText.focus();
							}, 150);
						}
					}, false);
					ui.footerLeft.addEventListener('tap', function(event) {
//						console.log("暂不支持此功能");
//						return;
						var btnArray = [{
							title: "拍照"
						}, {
							title: "从相册选择"
						}];
						plus.nativeUI.actionSheet({
							title: "选择照片",
							cancel: "取消",
							buttons: btnArray
						}, function(e) {
							var index = e.index;
							switch (index) {
								case 0:
									break;
								case 1:
									var cmr = plus.camera.getCamera();
									cmr.captureImage(function(path) {
										var dstname = "_downloads/" + getUid() + ".jpg";
										compressImage(path, dstname);
										getNewUrl();
//										send({
//											sender: 'self',
//											type: 'image',
//											content: "file://" + plus.io.convertLocalFileSystemURL(path)
//										});
									}, function(err) {});
									break;
								case 2:
									plus.gallery.pick(function(path) {
										var dstname = "_downloads/" + getUid() + ".jpg";
										compressImage(path, dstname);
										plus.nativeUI.showWaiting( "正在压缩图片" );
										getNewUrl();
//										
									}, function(err) {
										
									}, {
										filter: "image"
									});
									break;
							}
						});
					}, false); 
					var files = [];
					var newUrlAfterCompress;
					//var currentUserImg=plus.storage.getItem("userimg");
					//console.log(currentUserImg);
					function getNewUrl(){
						if(newUrlAfterCompress!=undefined){
							console.log("转换后图片:"+newUrlAfterCompress);
							appendFile(newUrlAfterCompress);
							plus.nativeUI.showWaiting( "正在上传图片" );
							upload();
						}
						else{
							setTimeout(getNewUrl,300);
						}
					}
					// 上传文件
					function upload() {
						//var wt = plus.nativeUI.showWaiting();
						var task = plus.uploader.createUpload(server + "?action=testupload", {
								method: "POST"
							},
							function(t, status) { //上传完成
								if (status == 200) {
									//mui.toast("图片上传成功");
									var imgurl=t.responseText; 
									//console.log("图片路径:"+imgurl);
									var userimg=plus.storage.getItem("userimg");
									console.log(userimg);
									if(userimg.length>10){
										
									}
									else{
										userimg="img/logo.png";
									}
									var obj = { 
						                send: plus.storage.getItem("loginname"),//this.userid, 
						                username: plus.storage.getItem("loginname"),//this.username, 
						                content: imgurl,
						                contentType:'image',
						                receive:plus.storage.getItem("loginname"),
						                groupid:''+plus.webview.currentWebview().groupid,
						                uname:plus.storage.getItem("realname"),
						                upic:userimg,
						                type:'self'
						            };
						            //plus.webview.currentWebview().groupid
						            files = [];
						            newUrlAfterCompress=undefined;
						            this.socket = io.connect('ws://121.40.205.128:3000');
						            this.socket.emit('message', obj);
						            plus.nativeUI.closeWaiting();
									//wt.close();
								} else {
									console.log("上传失败:" + status);

								}
							}
						);
						for (var i = 0; i < files.length; i++) {
							var f = files[i];
//							console.log("准备上传的图片路径:"+i+f.path);
							task.addFile(f.path, {
								key: f.name
							});
						}
						task.start();
					}
					function appendFile(p) {
						files.push({
							name: "uploadkey",
							path: p
						});
					}
					// 产生一个随机数
					function getUid() {
						return Math.floor(Math.random() * 100000000 + 10000000+new Date().getMilliseconds()).toString();
					}
					//压缩图片
					function compressImage(src, dstname) {
						//var dstname="_downloads/"+getUid()+".jpg";
						plus.zip.compressImage({
								src: src,
								dst: dstname,
								overwrite: true,
								quality: 20
							},
							function(event) {
								//console.log("Compress success:"+event.target);
								newUrlAfterCompress=event.target;
								return event.target;
							},
							function(error) {
								console.log(error);
								return src;
								//console.log("Compress error!");
							});
					}
					var setSoundAlertVisable=function(show){
						if(show){
							ui.boxSoundAlert.style.display = 'block';
							ui.boxSoundAlert.style.opacity = 1;
						}else{
							ui.boxSoundAlert.style.opacity = 0;
							//fadeOut 完成再真正隐藏
							setTimeout(function(){
								ui.boxSoundAlert.style.display = 'none';
							},200);
						}
					};
					var recordCancel = false;
					var recorder = null;
					var audio_tips = document.getElementById("audio_tips");
					var startTimestamp = null;
					var stopTimestamp = null;
					var stopTimer = null;
					ui.boxMsgSound.addEventListener('hold', function(event) {
						recordCancel = false;
						if(stopTimer)clearTimeout(stopTimer);
						audio_tips.innerHTML = "手指上划,取消发送";
						ui.boxSoundAlert.classList.remove('rprogress-sigh');
						setSoundAlertVisable(true);
						recorder = plus.audio.getRecorder();
						if (recorder == null) {
							plus.nativeUI.toast("不能获取录音对象");
							return;
						}
						startTimestamp = (new Date()).getTime();
						recorder.record({
							filename: "_doc/audio/"
						}, function(path) {
							if (recordCancel) return;
							send({
								sender: 'self',
								type: 'sound',
								content: path
							});
						}, function(e) {
							plus.nativeUI.toast("录音时出现异常: " + e.message);
						});
					}, false);
					ui.body.addEventListener('drag', function(event) {
						//console.log('drag');
						if (Math.abs(event.detail.deltaY) > 50) {
							if (!recordCancel) {
								recordCancel = true;
								if (!audio_tips.classList.contains("cancel")) {
									audio_tips.classList.add("cancel");
								}
								audio_tips.innerHTML = "松开手指,取消发送";
							}
						} else {
							if (recordCancel) {
								recordCancel = false;
								if (audio_tips.classList.contains("cancel")) {
									audio_tips.classList.remove("cancel");
								}
								audio_tips.innerHTML = "手指上划,取消发送";
							}
						}
					}, false);
					ui.boxMsgSound.addEventListener('release', function(event) {
						//console.log('release');
						if (audio_tips.classList.contains("cancel")) {
							audio_tips.classList.remove("cancel");
							audio_tips.innerHTML = "手指上划,取消发送";
						}
						//
						stopTimestamp = (new Date()).getTime();
						if (stopTimestamp - startTimestamp < MIN_SOUND_TIME) {
							audio_tips.innerHTML = "录音时间太短";
							ui.boxSoundAlert.classList.add('rprogress-sigh');
							recordCancel = true;
							stopTimer=setTimeout(function(){
								setSoundAlertVisable(false);
							},800);
						}else{
							setSoundAlertVisable(false);
						}
						recorder.stop();
					}, false);
					ui.boxMsgSound.addEventListener("touchstart", function(e) {
						//console.log("start....");
						e.preventDefault();
					});
					ui.boxMsgText.addEventListener('input', function(event) {
						ui.btnMsgType.classList['add']('mui-icon-paperplane');
						ui.btnMsgType.setAttribute("for", ui.boxMsgText.value == '' ? '' : 'msg-text');
						ui.h.innerText = ui.boxMsgText.value.replace(new RegExp('\\n', 'gm'), '\\n-') || '-';
						ui.footer.style.height = (ui.h.offsetHeight + footerPadding) + 'px';
						ui.content.style.paddingBottom = ui.footer.style.height;
					});
					ui.boxMsgText.addEventListener('tap', function(event) {
						ui.boxMsgText.focus();
						setTimeout(function() {
							ui.boxMsgText.focus();
						}, 0);
					}, false);
				var conn=new DBConn();
				//保存联系人表
				function insertData(send,receive,content,groupid){
					var sql="";
					conn.executeScarl("select * from chart_list where send='"+send+"' and receive='"+receive+"'",
						function(tx,result){
							if(result.rows.length>0){
								//存在最近记录
								sql="update chart_list set content='"+content+"' where send='"+send+"' and receive='"+receive+"'";
								conn.executeSqlDefault(sql,
									[],
									function (tx, result) {
										//保存成功
									},
									function (tx, error) {
										console.log('记录保存失败: ' + error.message); 
										
									}
								);
							}else{
								conn.executeScarl("select * from chart_list order by addtime desc limit 0,1",
									function(tx,result){
										var id=0;
										if(result.rows.length>0){
											id=parseInt(result.rows.item(0)["id"])+1;
										}else{
											id=1;
										}
										//添加最近记录,判断是否存在记录,无责为1,否则为最大值+1
										var da=new Date();
										var adddate=da.getFullYear()+"-"+(da.getMonth()+1)+"-"+da.getDay()+" "+da.getHours()+":"+da.getMinutes()+":"+da.getSeconds();
										sql="insert into chart_list (id,send,receive,addtime,content,groupid) values('"+id+"','"+send+"','"+receive+"','"+adddate+"','"+content+"','"+groupid+"')";
										//console.log(sql);   
										conn.executeSqlDefault(sql,
											[],
											function (tx, result) {
												//保存成功
											},
											function (tx, error) {
												console.log('记录保存失败: ' + error.message); 
											}
										);
									}
								)
							}
						}
					);
				}
				//保存聊天内容表
				function insertDataContent(id,send,receive,adddate,content,type){
					conn.executeScarl("select * from chart_list_content order by addtime desc limit 0,1",
						function(tx,result){
							var type="";
							if(plus.storage.getItem("loginname")==send){
								type='self';
							}else{
								type='send';
							}
							//添加最近记录,判断是否存在记录,无责为1,否则为最大值+1
							var sql="insert into chart_list_content (id,send,receive,addtime,content,type,isread) values('"+id+"','"+send+"','"+receive+"','"+adddate+"','"+content+"','"+type+"',1)";
							//console.log(sql);
							//console.log(sql+"ee");
							conn.executeSqlDefault(sql,
								[],
								function (tx, result) {
									//保存成功
									record.push({
										sender: type,
										type: 'text',
										content: content
									});
									bindMsgList();
									
								},
								function (tx, error) {
									console.log('记录保存失败: ' + error.message); 
								}
							);
						}
					)
				}
				//群组--------------------------
				//保存联系人表
				function insertGroupData(send,receive,content,contentType,groupid,uname){
					var sql="";
					conn.executeScarl("select * from chart_list where groupid='"+groupid+"'",
						function(tx,result){
//							console.log("=========="+result.rows.length);
							if(result.rows.length>0){
								//存在最近记录
								sql="update chart_list set content='"+content+"',contentType='"+contentType+"',uname='"+uname+"' where groupid='"+groupid+"'";
								conn.executeSqlDefault(sql,
									[],
									function (tx, result) {
										//保存成功
									},
									function (tx, error) {
										console.log('记录保存失败: ' + error.message); 
									}
								);
							}else{
//								console.log("需要新建组记录");
								conn.executeScarl("select * from chart_list order by id desc limit 0,1",
									function(tx,result){
										var id=0;
										if(result.rows.length>0){
											id=parseInt(result.rows.item(0)["id"])+1;
										}else{
											id=1;
										}
										//添加最近记录,判断是否存在记录,无责为1,否则为最大值+1
										var da=new Date();
										var adddate=da.getFullYear()+"-"+(da.getMonth()+1)+"-"+da.getDay()+" "+da.getHours()+":"+da.getMinutes()+":"+da.getSeconds();
										var uname=plus.storage.getItem("realname");
										var upic=plus.storage.getItem("userimg");
										sql="insert into chart_list (id,send,receive,addtime,content,contentType,groupid,uname) ";
										sql+=" values('"+id+"','','','"+adddate+"','"+content+"','"+contentType+"','"+groupid+"','"+uname+"')";
										//console.log(sql);   
										conn.executeSqlDefault(sql,
											[],
											function (tx, result) {
												//保存成功
//												var recently=plus.webview.getWebviewById("recently.html");
//												mui.fire(recently,"refresh",{});
											},
											function (tx, error) {
												console.log('记录保存失败: ' + error.message); 
											}
										);
									},function(tx,error){
										console.log(error);
									}
									
								)
							}
						}
					);
				}
				//保存群组聊天内容表
				function insertDataGroupContent(id,send,receive,addtime,content,contentType,type,groupid,uname,upic){
					conn.executeScarl("select * from chart_group_list_content order by addtime desc limit 0,1",
						function(tx,result){
							var sender="";
							if(plus.storage.getItem("loginname")==send){
								sender='self';
							}else{
								sender='send';
							}
							//添加最近记录,判断是否存在记录,无责为1,否则为最大值+1
							var sql="insert into chart_group_list_content (id,send,content,contentType,addtime,type,groupid,uname,upic) values('"+id+"','"+send+"','"+content+"','"+contentType+"','"+addtime+"','"+type+"','"+groupid+"','"+uname+"','"+upic+"')";
//							console.log(sql);
							conn.executeSqlDefault(sql,
								[],
								function (tx, result) {
									//保存成功
									//initList();
									
									if(groupid==plus.webview.currentWebview().groupid){
										record.push({
											sender: sender,
											type: contentType,
											content: content,
											uname:uname,
											upic:upic,
											sendcode:send,
											addtime:addtime
										});
										bindMsgList();
										var recently=plus.webview.getWebviewById("recently.html");
										mui.fire(recently,'rebindList',{});
									}
									
								},
								function (tx, error) {
									console.log('记录保存失败: ' + error.message); 
								}
							);
						},function(tx,error){
							console.log(error);
						}
					)
				} 
				//获取本组服务器端最新消息 
				function getGroupMsgFromServer(groupid){
					conn.executeScarl("select addtime from chart_group_list_content where groupid='"+groupid+"' order by addtime desc limit 0,1",  
						function(tx,result){
							var last="2016-01-01 12:12:12";
							if(result.rows.length>0){
								last=result.rows.item(0)["addtime"];
							}
							console.log("last:"+last);
							var url=server+"?action=getgroupmsg&last="+last+"&groupid="+groupid;
							console.log(url); 
							$.getJSON(url,function(data){
//								console.log(JSON.stringify(data));
								if(data.length>0){
									for(var p=0;p<data.length;p++){
//										console.log(p+"--"+data.length);
										var sql="insert into chart_group_list_content (send,content,contentType,addtime,type,groupid,uname,upic)";
										sql+="values('"+data[p].send+"','"+data[p].content+"','"+data[p].contentType+"','"+data[p].addtime+"','other','"+data[p].groupid+"','"+data[p].uname+"','"+data[p].upic+"')";
										conn.executeSqlDefault(sql,
											[],
											function (tx, result) {
												
											},function(tx,error){
												
											});
									}
									initData();
								}
							});
						},function(tx,error){
							
						});
				}
				//显示本地聊天信息
				function initData(){
					var groupid=plus.webview.currentWebview().groupid;
					getGroupMsgFromServer(groupid);
					console.log("初始化群组数据");
					conn.executeScarl("select * from chart_group_list_content where groupid='"+groupid+"' order by id asc limit 0,100",  
					function(tx,result){
						if(result.rows.length>0){
							for(var i=0;i<result.rows.length;i++){ 
								record.push({//contentType:'image',
									sendcode: result.rows.item(i)["send"],
									sender: result.rows.item(i)["type"],
									type: result.rows.item(i)["contentType"],
									content: result.rows.item(i)["content"],
									uname:result.rows.item(i)["uname"],
									upic:result.rows.item(i)["upic"],
									addtime:result.rows.item(i)["addtime"]
								});
								bindMsgList();
								
							}
						}
						else{
							console.log("没有数据");
						}
					},function(tx,error){
						console.log(error.message);
					});
				};
				initData();
				
					
				var d = document,
				w = window, 
				p = parseInt, 
				dd = d.documentElement, 
				db = d.body, 
				dc = d.compatMode == 'CSS1Compat', 
				dx = dc ? dd: db, 
				ec = encodeURIComponent;
				
				w.CHAT = { 
				    msgObj:d.getElementById("message"), 
				    screenheight:w.innerHeight ? w.innerHeight : dx.clientHeight, 
				    username:null,
				    userid:null,
				    socket:null,
				    reivice:null,
				    //让浏览器滚动条保持在最低部 
				    scrollToBottom:function(){ 
				        //w.scrollTo(0, this.msgObj.clientHeight); 
				    },
				    //退出,本例只是一个简单的刷新 
				    logout:function(){ 
				        //this.socket.disconnect(); 
				        //location.reload(); 
				    }, 
				    //提交聊天消息内容 
				    submit:function(content,reivicer){ 
				        var content = content;
				        var userimg=plus.storage.getItem("userimg");
				        if(userimg.length<1){
				        	userimg="img/logo.png";
				        }
				        console.log("头像:"+userimg);
//				        console.log("groupid:"+plus.webview.currentWebview().groupid);
				        if(content != ''){ 
				            var obj = { 
				                send: plus.storage.getItem("loginname"),//this.userid, 
				                username: plus.storage.getItem("loginname"),//this.username, 
				                content: content,
				                contentType:'text',
				                receive:reivicer,
				                groupid:''+plus.webview.currentWebview().groupid,
				                uname:plus.storage.getItem("realname"),
				                upic:userimg,
				                type:'self'
				            }; 
				            //plus.webview.currentWebview().groupid
				            this.socket = io.connect('ws://121.40.205.128:3000');
				            this.socket.emit('message', obj);
				        } 
				        return false; 
				    }, 
				    genUid:function(){ 
				        return new Date().getTime()+""+Math.floor(Math.random()*899+100); 
				    }, 
				    //更新系统消息,本例中在用户加入、退出的时候调用 
				    updateSysMsg:function(o, action){ 
				        //当前在线用户列表 
				        var onlineUsers = o.onlineUsers; 
				        //当前在线人数 
				        var onlineCount = o.onlineCount; 
				        //新加入用户的信息 
				        var user = o.user; 
				            
				        //更新在线人数 
				        var userhtml = ''; 
				        var separator = ''; 
				        for(key in onlineUsers) { 
				            if(onlineUsers.hasOwnProperty(key)){ 
				                userhtml += separator+onlineUsers[key]; 
				                separator = '、'; 
				            } 
				        } 
				    }, 
				    //第一个界面用户提交用户名 
				    usernameSubmit:function(){
				        return false; 
				    },
				    init:function(){
				        /* 
				        客户端根据时间和随机数生成uid,这样使得聊天室用户名称可以重复。 
				        实际项目中,如果是需要用户登录,那么直接采用用户的uid来做标识就可以 
				        */
				        this.userid = plus.storage.getItem("loginname"); 
				        this.username = plus.storage.getItem("loginname"); 
				        
				        //连接websocket后端服务器 
				        this.socket = io.connect('ws://121.40.205.128:3000'); 
				        
				        //告诉服务器端有用户登录 
				        this.socket.emit('login', {userid:this.userid, username:this.username}); 
				        
				        //监听新用户登录 
				        this.socket.on('login', function(o){ 
				            CHAT.updateSysMsg(o, 'login'); 
				        }); 
				        
				        //监听用户退出 
				        this.socket.on('logout', function(o){ 
				            CHAT.updateSysMsg(o, 'logout'); 
				        });
				        //监听消息发送 
				        this.socket.on('message', function(obj){
				        	//监听服务器发送的消息,保存到本地,然后展示
				        	
				        	if(obj.groupid==0){
				        		//单人聊天监听保存
				        		conn.executeScarl("select * from chart_list_content where id='"+obj.id+"'",  
								function(tx,result){
									if(result.rows.length==0){
										var send="";
										if(obj.send==plus.storage.getItem("loginname")){
											send=obj.receive;
										}else{
											send=obj.send;
											var ring=plus.audio.createPlayer("ring/ring_msg.mp3");
				        					ring.play();
										}
										insertData(send,plus.storage.getItem("loginname"),obj.content,0);
					        			insertDataContent(obj.id,obj.send,obj.receive,obj.addtime,obj.content,obj.type);
									}
								});
				        	}
				        	else{
				        		//console.log('群组');
				        		//群组聊天监听保存
				        		conn.executeScarl("select * from chart_group_list_content where id='"+obj.id+"'",  
								function(tx,result){
									if(result.rows.length==0){
										var send="";
										if(obj.send==plus.storage.getItem("loginname")){
											send=obj.receive;
										}else{
											send=obj.send;
											var ring=plus.audio.createPlayer("ring/ring_msg.mp3");
				        					ring.play();
										}
										//insertGroupData(send,receive,content,contentType,groupid,uname)
										insertGroupData(send,plus.storage.getItem("loginname"),obj.content,obj.contentType,obj.groupid,obj.uname);
					        			insertDataGroupContent(obj.id,obj.send,obj.receive,obj.addtime,obj.content,obj.contentType,obj.type,obj.groupid,obj.uname,obj.upic);
									}
								});
				        	}
			            });
			            this.socket.on('notline', function(obj){
			            	//mui.toast("对方不在线");
			            });
			        } 
			    };
				CHAT.init();
			});
			}(mui, document));
		</script>
	</body>
</html>

更详细的说明移步到个人聊天,原理是一样的, 点击打开链接




以上是关于H5+MUI+Node.js+Socket.io群组即时聊天+发送图片+图片压缩的主要内容,如果未能解决你的问题,请参考以下文章

node.js + socket.io 聊天群聊系统

未找到 Socket.io.js(node.js + express + socket.io)

Node.js - Socket.io:socket.request 未定义

HTTP 状态代码 200 但页面未加载 Node.js Socket.io -- 使用 Socket.io 的 Node.js 教程,Daniel Nill,fs.readFile(),socket

Node.js 和 socket.io 的混淆

Node.js socket.io.js 未找到或 io 未定义