Flask 与 HTML5 简单功能实现
目录1 实现注册与登陆
- 实现注册与登陆,注册时上传拍照图片,登陆时加载图片。
HBuilder X
- HTML5+ API Reference (html5plus.org)
1.1 前端配置
- 使用
HBuilder X
创建mui项目
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
<h1 class="mui-title">phone page</h1>
</header>
<div class="mui-content">
<form class="mui-input-group">
<div class="mui-input-row">
<label>用户名:</label>
<input type="text" class="mui-input-clear" id='username' value="user01">
</div>
<div class="mui-input-row">
<label>密码:</label>
<input type="password" class="mui-input-clear" id='password' value="1234">
</div>
<div class="mui-input-row">
<label>男:</label>
<input name='gender' type="radio" value="1" checked>
</div>
<div class="mui-input-row">
<label>女:</label>
<input name='gender' type="radio" value="2">
</div>
<button type="button" class="mui-btn mui-btn-red mui-btn-block" id='cmr-btn'>开始拍照</button>
</form>
<form class="mui-input-group">
<div class="mui-input-row">
<label>用户名:</label>
<input type="text" class="mui-input-clear" id='user' value="user01">
</div>
<div class="mui-input-row">
<label>密码:</label>
<input type="password" class="mui-input-clear" id='passwd' value="1234">
</div>
<div class="mui-input-row">
<button type="button" class="mui-btn mui-btn-green mui-btn-block" id='submit'>登录</button>
</div>
</form>
<div class="mui-input-row" style="text-align: center;">
<img id="cmr-pic" style="width: 150px; height: 150px; border-radius: 50%;">
</div>
</div>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 扩展API加载完毕后调用onPlusReady回调函数
document.addEventListener( "plusready", onPlusReady, false );
// 扩展API加载完毕,现在可以正常调用扩展API
function onPlusReady() {
console.log("plusready");
};
mui.init();
mui.back = function(){};
// 拍照
document.getElementById('cmr-btn').addEventListener('tap',function () {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var gender_list = document.getElementsByName('gender');
mui.toast('开启摄像头');
var cmr = plus.camera.getCamera();
var res = cmr.supportedImageResolutions[30];
var fmt = cmr.supportedImageFormats[0];
console.log("Resolution: "+res+", Format: "+fmt);
cmr.captureImage( function( path ){
mui.toast( "Capture image success: " + path );
// console.log(path);
var task = plus.uploader.createUpload( "http://192.168.50.117:5000/upload",
{ method:"POST",priority:100 },
function ( t, status ) {
// 上传完成
if ( status == 200 ) {
alert( "Upload success: " + t.url );
} else {
alert( "Upload failed: " + status );
}
}
);
task.addFile( path, {key:"jpg"} );
task.addData( "username", username );
task.addData( "password", password );
for (var i = 0; i<gender_list.length; i++) {
if (gender_list[i].checked) {
var gender = gender_list[i].value;
}
}
task.addData( "gender", gender );
//task.addEventListener( "statechanged", onStateChanged, false );
task.start();
},
function( error ) {
mui.toast( "Capture image failed: " + error.message );
},
// options
{
filename:'_doc/fcarey/a.jpg',
resolution:res,
format:fmt,
},
);
});
document.getElementById('submit').addEventListener('tap',function () {
var user = document.getElementById('user').value;
var passwd = document.getElementById('passwd').value;
mui.post(
'http://192.168.50.117:5000/login',{
'username':user,
'password':passwd,
},function(data){
console.log(JSON.stringify(data.data.avatar));
document.getElementById("cmr-pic").src = 'http://192.168.50.117:5000/get_avatar/'+data.data.avatar;
alert(data.msg);
},'json'
);
});
</script>
</body>
</html>
1.2 后端配置
from flask import Flask, request, jsonify, send_file
from pymongo import MongoClient
app = Flask(__name__)
app.debug = True
MC = MongoClient(host='127.0.0.1', port=27017)
db = MC['fcarey01']
@app.route('/upload', methods=['post'])
def upload():
user_info = request.form.to_dict()
file = request.files.get('jpg')
file.save(user_info.get('username') + '.jpg')
user_info['avatar'] = user_info.get('username') + '.jpg'
res = db.members.insert_one(user_info)
if res.inserted_id:
return f"恭喜{user_info.get('username')}用户,注册成功!"
else:
return 'out'
@app.route('/login', methods=['post'])
def login():
user_info = request.form.to_dict()
user = db.members.find_one(user_info)
print(user)
if user:
user['_id'] = str(user.get('_id')) # 将ObjectId转换为字符串
return jsonify({"code": 0, "msg": "登录成功", "data": user})
else:
return jsonify({"code": 1, "msg": "登录失败"})
@app.route('/get_avatar/<filename>')
def get_avatar(filename):
return send_file(filename)
if __name__ == '__main__':
app.run(host='192.168.50.117', port=5000)
2 flask 与 html5+
实现:
- 打开展示首页
- 用户注册
- 用户登陆,并跳转至
user_info.html
页面 - 利用html5+操作设备:控制本地/远程音乐播放、震动
1.1 前端配置
- 使用
HBuilder X
创建mui项目
1.1.1index.html
配置
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title">首页</h1>
</header>
<div class="mui-content">
it's index.html.
</div>
<nav class="mui-bar mui-bar-tab">
<a class="mui-tab-item mui-active" id='home'>
<span class="mui-icon mui-icon-home"></span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" id='register'>
<span class="mui-icon mui-icon-phone"></span>
<span class="mui-tab-label">电话</span>
</a>
<a class="mui-tab-item" id="audio">
<span class="mui-icon mui-icon-mic"></span>
<span class="mui-tab-label">语音</span>
</a>
<a class="mui-tab-item" id="login">
<span class="mui-icon mui-icon-gear"></span>
<span class="mui-tab-label">登录</span>
</a>
</nav>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
mui.init({
gestureConfig:{
tap: true, //默认为true
doubletap: true, //默认为false
longtap: true, //默认为false
swipe: true, //默认为true
drag: true, //默认为true
hold:false,//默认为false,不监听
release:false,//默认为false,不监听
},
subpages:[{
url:'main.html',//子页面HTML地址,支持本地地址和网络地址
id:'main.html',//子页面标志
styles:{
top:'0px',//子页面顶部位置
bottom:'50px',//子页面底部位置
},
extras:{}//额外扩展参数
}]
});
document.getElementById('home').addEventListener('tap',function () {
mui.openWindow({
url: 'main.html',
id:'main.html',
styles:{
top:'0px',//子页面顶部位置
bottom:'50px',//子页面底部位置
},
});
var index_webview = plus.webview.currentWebview();
console.log(JSON.stringify(index_webview));
});
document.getElementById('register').addEventListener('tap',function () {
mui.openWindow({
url: 'register.html',
id:'register.html',
styles:{
top:'0px',//新页面顶部位置
bottom:'50px',//新页面底部位置
},
});
});
document.getElementById('audio').addEventListener('tap',function () {
mui.openWindow({
url: 'audio.html',
id:'audio.html',
styles:{
top:'0px',//新页面顶部位置
bottom:'50px',//新页面底部位置
},
extras:{
username:'fcarey',
},
createNew:true,
});
});
document.getElementById('login').addEventListener('tap',function () {
if (plus.storage.getItem('user_id')) {
mui.openWindow({
url: 'user_info.html',
id:'user_info.html',
styles:{
top:'0px',//新页面顶部位置
bottom:'50px',//新页面底部位置
},
});
} else{
mui.openWindow({
url: 'login.html',
id:'login.html',
styles:{
top:'0px',//新页面顶部位置
bottom:'50px',//新页面底部位置
},
});
}
});
</script>
</body>
</html>
1.1.2 main.html
配置
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title">标题</h1>
</header>
<div class="mui-content">
it's main.html
</div>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
mui.init()
</script>
</body>
</html>
1.1.3 register.html
配置
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<a class="mui-action-back mui-icon mui-icon-left-nav mui-pull-left"></a>
<h1 class="mui-title">register</h1>
</header>
<div class="mui-content">
<form class="mui-input-group">
<div class="mui-input-row">
<label>用户名:</label>
<input type="text" class="mui-input-clear" id='username' value="user01">
</div>
<div class="mui-input-row">
<label>密码:</label>
<input type="password" class="mui-input-clear" id='password' value="1234">
</div>
<div class="mui-input-row">
<label>男:</label>
<input name='gender' type="radio" value="1" checked>
</div>
<div class="mui-input-row">
<label>女:</label>
<input name='gender' type="radio" value="2">
</div>
<button type="button" class="mui-btn mui-btn-red mui-btn-block" id='cmr-btn'>开始拍照</button>
</form>
<form class="mui-input-group">
<div class="mui-input-row">
<label>用户名:</label>
<input type="text" class="mui-input-clear" id='user' value="user01">
</div>
<div class="mui-input-row">
<label>密码:</label>
<input type="password" class="mui-input-clear" id='passwd' value="1234">
</div>
<div class="mui-input-row">
<button type="button" class="mui-btn mui-btn-green mui-btn-block" id='submit'>登录</button>
</div>
</form>
<div class="mui-input-row" style="text-align: center;">
<img id="cmr-pic" style="width: 150px; height: 150px; border-radius: 50%;">
</div>
</div>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 扩展API加载完毕后调用onPlusReady回调函数
document.addEventListener( "plusready", onPlusReady, false );
// 扩展API加载完毕,现在可以正常调用扩展API
function onPlusReady() {
console.log("plusready");
};
mui.init();
mui.back = function(){};
// 拍照
document.getElementById('cmr-btn').addEventListener('tap',function () {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
var gender_list = document.getElementsByName('gender');
mui.toast('开启摄像头');
var cmr = plus.camera.getCamera();
var res = cmr.supportedImageResolutions[30];
var fmt = cmr.supportedImageFormats[0];
console.log("Resolution: "+res+", Format: "+fmt);
cmr.captureImage( function( path ){
mui.toast( "Capture image success: " + path );
// console.log(path);
var task = plus.uploader.createUpload( "http://192.168.50.117:5000/upload",
{ method:"POST",priority:100 },
function ( t, status ) {
// 上传完成
if ( status == 200 ) {
alert( "Upload success: " + t.url );
} else {
alert( "Upload failed: " + status );
}
}
);
task.addFile( path, {key:"jpg"} );
task.addData( "username", username );
task.addData( "password", password );
for (var i = 0; i<gender_list.length; i++) {
if (gender_list[i].checked) {
var gender = gender_list[i].value;
}
}
task.addData( "gender", gender );
//task.addEventListener( "statechanged", onStateChanged, false );
task.start();
},
function( error ) {
mui.toast( "Capture image failed: " + error.message );
},
// options
{
filename:'_doc/fcarey/a.jpg',
resolution:res,
format:fmt,
},
);
});
document.getElementById('submit').addEventListener('tap',function () {
var user = document.getElementById('user').value;
var passwd = document.getElementById('passwd').value;
mui.post(
'http://192.168.50.117:5000/login',{
'username':user,
'password':passwd,
},function(data){
console.log(JSON.stringify(data.data.avatar));
document.getElementById("cmr-pic").src = 'http://192.168.50.117:5000/get_avatar/'+data.data.avatar;
alert(data.msg);
},'json'
);
});
</script>
</body>
</html>
1.1.4 login.html
配置
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title">用户登录</h1>
</header>
<div class="mui-content">
<form class="mui-input-group">
<div class="mui-input-row">
<label>用户名</label>
<input type="text" id="username" class="mui-input-clear" value="user01">
</div>
<div class="mui-input-row">
<label>密码</label>
<input type="password" id="password" class="mui-input-password" value="1234">
</div>
<div class="mui-button-row">
<button type="button" class="mui-btn mui-btn-primary" id="loginBtn">登录</button>
<button type="button" class="mui-btn mui-btn-danger" >取消</button>
</div>
</form>
</div>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
mui.init()
document.getElementById('loginBtn').addEventListener('tap',function () {
var username = document.getElementById("username").value;
var password = document.getElementById("password").value;
mui.post("http://192.168.50.117/login",{
'username':username,
'password':password,
},function(data){
console.log(JSON.stringify(data))
if (data.code == 0) {
plus.storage.setItem('user_id',data.data._id);
mui.toast(data.msg);
mui.openWindow({
url:'user_info.html',//子页面HTML地址,支持本地地址和网络地址
id:'user_info.html',//子页面标志
styles:{
top:'0px',//子页面顶部位置
bottom:'50px',//子页面底部位置
},
extras:data.data,//额外扩展参数
createNew:true,
});
} else{
mui.toast(data.msg);
}
},'json'
);
})
document.addEventListener('sayByebye',function(data){
console.log(JSON.stringify(data.detail));
mui.toast("再见"+data.detail.username);
});
</script>
</body>
</html>
1.1.5 user_info.html
配置
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title" id="userinfo">用户详情</h1>
</header>
<div class="mui-content">
用户详情
</div>
<div class="mui-content">
<button type="button" class="mui-btn mui-btn-blue mui-btn-block" id="logout">退出</button>
</div>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
mui.init();
// 扩展API加载完毕后调用onPlusReady回调函数
document.addEventListener( "plusready", onPlusReady, false );
// 扩展API加载完毕,现在可以正常调用扩展API
function onPlusReady() {
var wv = plus.webview.currentWebview();
document.getElementById('userinfo').innerText = wv.username;
var wv_opener = wv.opener();
console.log(wv_opener.id);
if (wv_opener.id == 'login.html') {
var login_wv = plus.webview.getWebviewById('login.html');
login_wv.hide();
login_wv.close();
} else{
}
};
document.getElementById('logout').addEventListener('tap',function () {
plus.storage.removeItem('user_id');
mui.openWindow({
url:'login.html',
id: 'login.html',
styles:{
top:'0px',//子页面顶部位置
bottom:'50px',//子页面底部位置
},
});
var index = plus.webview.getWebviewById("login.html"); // index页面id为HBuilder
mui.fire(index, 'sayByebye',{"username":"fcarey"});
});
</script>
</body>
</html>
1.1.6 audio.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title" id='title'>audio</h1>
</header>
<div class="mui-content">
<button type="button" class="mui-btn mui-btn-blue mui-btn-block" id='player'> 播放</button>
<button type="button" class="mui-btn mui-btn-yellow mui-btn-block" id='player_pause'>暂停</button>
<button type="button" class="mui-btn mui-btn-green mui-btn-block" id='player_resume'>恢复</button>
<button type="button" class="mui-btn mui-btn-red mui-btn-block" id='player_stop'>结束</button>
</div>
<div class="mui-content">
<button type="button" class="mui-btn mui-btn-blue mui-btn-block" id='recoder'>录音</button>
</div>
<div class="mui-content">
<button type="button" class="mui-btn mui-btn-red mui-btn-block" id='vibrate'>震动</button>
</div>
<div class="mui-content">
<audio id="audio_player"></audio>
</div>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
mui.init({
gestureConfig:{
tap: true,
doubletap: true,
longtap: true,
swipe: true,
drag: true,
hold:true,
release:true
},
});
// 扩展API加载完毕后调用onPlusReady回调函数
document.addEventListener( "plusready", onPlusReady, false );
// 扩展API加载完毕,现在可以正常调用扩展API
function onPlusReady() {
var wv = plus.webview.currentWebview();
console.log(JSON.stringify(wv));
document.getElementById("title").innerText=wv.username;
}
var p = null;
document.getElementById('player').addEventListener('tap',function () {
console.log(plus.os.name)
if(plus.os.name == "Android"){
p = plus.audio.createPlayer('https://aod.cos.tx.xmcdn.com/storages/3a46-audiofreehighqps/4F/1D/GKwRIasH-al8ABnBggIIQJ7--aacv2-48K.m4a');
if ( plus.audio == undefined ) {
alert( "Device not ready!" );
}
else {
p.play( function () {
alert( "Audio play success!" );
}, function ( e ) {
alert( "Audio play error: " + e.message );
} );
}
}else{
//解决 iOS 无法远程播放音频
console.log("iOS");
p = document.getElementById("audio_player");
p.src = 'https://aod.cos.tx.xmcdn.com/storages/3a46-audiofreehighqps/4F/1D/GKwRIasH-al8ABnBggIIQJ7--aacv2-48K.m4a';
p.play();
}
});
document.getElementById('player_pause').addEventListener('tap',function () {
p.pause();
});
document.getElementById('player_resume').addEventListener('tap',function () {
p.resume();
});
document.getElementById('player_stop').addEventListener('tap',function () {
p.stop();
});
document.getElementById('player_stop').addEventListener('tap',function () {
p.stop();
});
var r = null;
document.getElementById('recoder').addEventListener('hold',function () {
r = plus.audio.getRecorder();
r.record({filename:'_doc/recoders/'},function (path) {
mui.toast(path+'录音完成');
createUpload(path)
},function (e) {
mui.toast("Audio record failed: " + e.message);
});
});
document.getElementById('recoder').addEventListener('release',function () {
r.stop();
});
// 创建上传任务
function createUpload(path) {
var task = plus.uploader.createUpload( "http://192.168.50.117/uploader",
{ method:"POST",priority:100 },
function ( t, status ) {
// 上传完成
if ( status == 200 ) {
console.log( JSON.stringify(t) );
console.log( t.responseText );
} else {
alert( "Upload failed: " + status );
}
}
);
task.addFile( path, {key:'recoder'} );
task.addData( "name", "recoder01.amr" );
//task.addEventListener( "statechanged", onStateChanged, false );
task.start();
};
document.getElementById('vibrate').addEventListener('tap',function () {
// var v = plus.device.vibrate(500)
});
</script>
</body>
</html>
2.1 后端配置
app.py
from flask import Flask, request, jsonify, send_file
from pymongo import MongoClient
app = Flask(__name__)
app.debug = True
MC = MongoClient(host='127.0.0.1', port=27017)
db = MC['fcarey01']
@app.route('/upload', methods=['post'])
def upload():
user_info = request.form.to_dict()
file = request.files.get('jpg')
file.save(user_info.get('username') + '.jpg')
user_info['avatar'] = user_info.get('username') + '.jpg'
res = db.members.insert_one(user_info)
if res.inserted_id:
return f"恭喜{user_info.get('username')}用户,注册成功!"
else:
return 'out'
@app.route('/login', methods=['post'])
def login():
user_info = request.form.to_dict()
user = db.members.find_one(user_info)
print(user)
if user:
user['_id'] = str(user.get('_id')) # 将ObjectId转换为字符串
return jsonify({"code": 0, "msg": "登录成功", "data": user})
else:
return jsonify({"code": 1, "msg": "登录失败"})
@app.route('/get_avatar/<filename>')
def get_avatar(filename):
return send_file(filename)
if __name__ == '__main__':
app.run(host='192.168.50.117', port=5000)
3 实现语音发送功能
- 用户发送语音
- 接收端接收语音并播放
3.1 前端配置
- 使用
HBuilder X
创建mui项目
3.1.1index.html
配置
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title">首页</h1>
</header>
<div class="mui-content">
it's index.html.
</div>
<nav class="mui-bar mui-bar-tab">
<a class="mui-tab-item mui-active" id='home'>
<span class="mui-icon mui-icon-home"></span>
<span class="mui-tab-label">首页</span>
</a>
<a class="mui-tab-item" id='phone'>
<span class="mui-icon mui-icon-phone"></span>
<span class="mui-tab-label">电话</span>
</a>
<a class="mui-tab-item" id="message">
<span class="mui-icon mui-icon-mic"></span>
<span class="mui-tab-label">语音</span>
</a>
<a class="mui-tab-item" id="login">
<span class="mui-icon mui-icon-gear"></span>
<span class="mui-tab-label">登录</span>
</a>
</nav>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
mui.init();
// 扩展API加载完毕后调用onPlusReady回调函数
document.addEventListener( "plusready", onPlusReady, false );
// 扩展API加载完毕,现在可以正常调用扩展API
function onPlusReady() {
var main_wv = plus.webview.create(
'main.html',
'main.html',
{
top:'0px',//新页面顶部位置
bottom:'50px',//新页面底部位置
});
main_wv.show();
document.addEventListener('app_create_ws',function(data){
ws = new WebSocket(window.ws_serv + data.detail._id);
});
document.addEventListener('ws_send_data',function(data){
var send_data = JSON.stringify(data.detail);
ws.send(send_data);
});
};
document.getElementById('home').addEventListener('tap',function () {
mui.openWindow({
url: 'main.html',
id:'main.html',
styles:{
top:'0px',//新页面顶部位置
bottom:'50px',//新页面底部位置
},
});
});
document.getElementById('message').addEventListener('tap',function () {
mui.openWindow({
url: 'message.html',
id:'message.html',
styles:{
top:'0px',//新页面顶部位置
bottom:'50px',//新页面底部位置
},
});
});
document.getElementById('login').addEventListener('tap',function () {
mui.openWindow({
url: 'login.html',
id:'login.html',
styles:{
top:'0px',//新页面顶部位置
bottom:'50px',//新页面底部位置
},
});
})
</script>
</body>
</html>
3.1.2 main.html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title">标题</h1>
</header>
<div class="mui-content">
<div id="slider" class="mui-slider" >
<div class="mui-slider-group mui-slider-loop">
<!-- 额外增加的一个节点(循环轮播:第一个节点是最后一张轮播) -->
<div class="mui-slider-item mui-slider-item-duplicate">
<a href="#">
<img src="http:\/\/placehold.it\/400x300">
</a>
</div>
<!-- 第一张 -->
<div class="mui-slider-item">
<a href="#">
<img src="http:\/\/placehold.it\/400x300">
</a>
</div>
<!-- 第二张 -->
<div class="mui-slider-item">
<a href="#">
<img src="">
</a>
</div>
<!-- 第三张 -->
<div class="mui-slider-item">
<a href="#">
<img src="">
</a>
</div>
<!-- 第四张 -->
<div class="mui-slider-item">
<a href="#">
<img src="http:\/\/placehold.it\/400x300">
</a>
</div>
<!-- 额外增加的一个节点(循环轮播:最后一个节点是第一张轮播) -->
<div class="mui-slider-item mui-slider-item-duplicate">
<a href="#">
<img src="http:\/\/placehold.it\/400x300">
</a>
</div>
</div>
<div class="mui-slider-indicator">
<div class="mui-indicator mui-active"></div>
<div class="mui-indicator"></div>
<div class="mui-indicator"></div>
<div class="mui-indicator"></div>
</div>
</div>
<ul class="mui-table-view mui-grid-view mui-grid-9">
<li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
<a href="#">
<span class="mui-icon mui-icon-home"></span>
<div class="mui-media-body">Home</div>
</a>
</li>
<li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
<a href="#">
<span class="mui-icon mui-icon-email"><span class="mui-badge mui-badge-red">5</span></span>
<div class="mui-media-body">Email</div>
</a>
</li>
<li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
<a href="#">
<span class="mui-icon mui-icon-chatbubble"></span>
<div class="mui-media-body">Chat</div>
</a>
</li>
<li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
<a href="#">
<span class="mui-icon mui-icon-location"></span>
<div class="mui-media-body">Location</div>
</a>
</li>
<li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
<a href="#">
<span class="mui-icon mui-icon-search"></span>
<div class="mui-media-body">Search</div>
</a>
</li>
<li class="mui-table-view-cell mui-media mui-col-xs-4 mui-col-sm-3">
<a href="#">
<span class="mui-icon mui-icon-phone"></span>
<div class="mui-media-body">Phone</div>
</a>
</li>
</ul>
<ul class="mui-table-view">
<li class="mui-table-view-cell mui-media">
<a href="javascript:;">
<img class="mui-media-object mui-pull-left" src="">
<div class="mui-media-body">
幸福
<p class="mui-ellipsis">能和心爱的人一起睡觉,是件幸福的事情;可是,打呼噜怎么办?</p>
</div>
</a>
</li>
<li class="mui-table-view-cell mui-media">
<a href="javascript:;">
<img class="mui-media-object mui-pull-left" src="">
<div class="mui-media-body">
木屋
<p class="mui-ellipsis">想要这样一间小木屋,夏天挫冰吃瓜,冬天围炉取暖.</p>
</div>
</a>
</li>
<li class="mui-table-view-cell mui-media">
<a href="javascript:;">
<img class="mui-media-object mui-pull-left" src="">
<div class="mui-media-body">
CBD
<p class="mui-ellipsis">烤炉模式的城,到黄昏,如同打翻的调色盘一般.</p>
</div>
</a>
</li>
</ul>
</div>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
mui.init()
</script>
</body>
</html>
3.1.3 message
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Document</title>
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<link rel="stylesheet" type="text/css" href="css/mui.css"/>
</head>
<body>
<header class="mui-bar mui-bar-nav">
<h1 class="mui-title">请说话</h1>
</header>
<div class="mui-content">
</div>
<nav class="mui-bar mui-bar-tab">
<a class="mui-tab-item" id="speech">
<span class="mui-icon mui-icon-speech"></span>
<span class="mui-tab-label">按住说话</span>
</a>
</nav>
<script src="js/mui.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
mui.init({
gestureConfig:{
hold:true,
release:true
}
});
// 扩展API加载完毕后调用onPlusReady回调函数
document.addEventListener( "plusready", onPlusReady, false );
// 扩展API加载完毕,现在可以正常调用扩展API
function onPlusReady() {
};
var reco = null;
document.getElementById('speech').addEventListener('hold',function () {
reco = plus.audio.getRecorder();
reco.record({filename:"_doc/voice/",format:"amr"},function(file_path){
// console.log(file_path);
createUpload(file_path);
});
});
document.getElementById('speech').addEventListener('release',function () {
reco.stop();
})
// 创建上传任务
function createUpload(path) {
var task = plus.uploader.createUpload( window.serv+"uploader",
{ method:"POST",priority:100 },
function ( t, status ) {
var wv = plus.webview.currentWebview();
// 上传完成
if ( status == 200 ) {
ret_json = JSON.parse(t.responseText);//responseText 上完成之后的返回值 String类型 一定要记得转换成Object(json)
filename = ret_json.data.filename;
var ws_send_data = {
msg:filename,
sender:"app",
receiver:"receiver"
}
var index = plus.webview.getWebviewById("HBuilder");
mui.fire(index,'ws_send_data', ws_send_data)
} else {
alert( "Upload failed: " + status );
}
}
);
task.addFile( path, {key:'msg'} );
task.start();
};
</script>
</body>
</html>
3.2 接收端配置
templates/ws_client.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello</title>
</head>
<body>
<audio controls autoplay id="player"></audio>
<script type="application/javascript">
var ws = new WebSocket('ws://172.20.10.3:81/app/receiver')
ws.onmessage = function (data) {
var data_json = JSON.parse(data.data);
// console.log(JSON.stringify(data_json));
document.getElementById('player').src='http://127.0.0.1/get_chat/'+data_json.msg;
}
</script>
</body>
</html>
3.3 后端设置
3.3.1 setting.py
配置
# 数据库配置信息
from pymongo import MongoClient
MC = MongoClient(host='127.0.0.1', port=27017)
MongoDB = MC['fcarey01']
# Return Info 配置
RET = {
"code": 0,
"msg": "",
"data": {}
}
3.3.2 serv/users.py
BluePrint配置
from flask import Blueprint, request, jsonify
from setting import MongoDB, RET
user_bp = Blueprint("user_bp", __name__)
@user_bp.route("/register", methods=["POST"])
def register():
# 获取FormData中的数据
user_info = request.form.to_dict()
# 将数据转换成字典 直接存放在MongoDB中
res = MongoDB.users.insert_one(user_info)
if res.inserted_id:
RET["code"] = 0
RET["msg"] = "注册成功"
RET["data"] = {}
return jsonify(RET)
else:
RET["code"] = 1
RET["msg"] = "注册失败"
RET["data"] = {}
return jsonify(RET)
@user_bp.route("/login", methods=["POST"])
def login():
login_info = request.form.to_dict()
user_info = MongoDB.members.find_one(login_info)
print(login_info)
if not user_info:
# 登录失败
RET["code"] = 1
RET["msg"] = "用户名密码错误"
RET["data"] = {}
return jsonify(RET)
else:
user_info["_id"] = str(user_info.get("_id"))
user_info.pop("password") # 删除敏感字段
RET["code"] = 0
RET["msg"] = "登录成功"
RET["data"] = user_info
return jsonify(RET)
3.3.3 serv/upload.py
BluePrint配置
import os
from flask import Blueprint, request, jsonify, send_file
from setting import MongoDB, RET
upload = Blueprint("upload", __name__)
@upload.route("/uploader", methods=["POST"])
def uploader():
reco = request.files.get("msg") # FileStorage
reco.save(reco.filename)
os.system(f"ffmpeg -i {reco.filename} {reco.filename}.mp3")
RET["code"] = 0
RET["msg"] = "上传成功"
RET["data"] = {"filename": f"{reco.filename}.mp3"}
return jsonify(RET)
@upload.route("/get_chat/<filename>")
def get_chat(filename):
print(filename)
return send_file(filename)
3.3.4 app.py
配置
from flask import Flask, render_template
from serv.users import user_bp
from serv.upload import upload
from flask_cors import CORS
app = Flask(__name__)
CORS(app=app)
app.config['DEBUG'] = True
app.register_blueprint(user_bp)
app.register_blueprint(upload)
# 创建 reciver 页面
@app.route('/')
def index():
# return '200 ok'
return render_template('ws_client.html')
if __name__ == '__main__':
app.run('0.0.0.0', 80)
3.3.5 ws_app.py
import json
from geventwebsocket.websocket import WebSocket
from geventwebsocket.server import WSGIServer
from geventwebsocket.handler import WebSocketHandler
from flask import Flask, request
app = Flask(__name__)
app.debug = True
socket_dict = {}
@app.route('/app/<username>')
def app_ws(username):
sock = request.environ.get('wsgi.websocket', None) # type:WebSocket
if not sock:
return '请使用WS协议连接'
while True:
try:
socket_dict[username] = sock # 将用户名与sock作映射关系
print(socket_dict)
"""获取json序列化后的数据"""
msg = sock.receive()
msg_dict = json.loads(msg) # 反序列化数据为字典
target_user = msg_dict['receiver'] # 取出数据中的目标用户,以获取对应的sock
recv_sock = socket_dict[target_user]
if recv_sock:
print(recv_sock)
recv_sock.send(msg)
else:
print("无客户端。")
except:
"""解决刷新页面时,之前已创建的websocket会话关闭产生的错误"""
break
return 'ok'
if __name__ == '__main__':
ws_server = WSGIServer(listener=('0.0.0.0', 81), application=app, handler_class=WebSocketHandler)
ws_server.serve_forever()
标签:function,Flask,mui,html,user,简单,document,data,HTML5
From: https://www.cnblogs.com/f-carey/p/17300641.html