Commit 6dfc9a88 authored by hbcui1984's avatar hbcui1984

更新login工程模板

parent ac5bdc6b
# 概述
## 简单概述
这是带登录和设置功能的mui模板项目,主要为了演示登录流程及设置界面div窗口切换效果;
## 核心功能
1.启动App后校验登录状态,若已登录,直接跳转应用首页;否则,显示登录页面;
2.支持本地注册;
3.支持设置手势密码,登录时可使用手势密码代替账号、密码;
4.支持评分、分享、拨打客服电话
1. 启动App后校验登录状态,若已登录,直接跳转应用首页;否则,显示登录页面;
2. 支持本地注册;
3. 支持设置手势密码,登录时可使用手势密码代替账号、密码;
4. 支持评分、分享、拨打客服电话
.feedback body {
background-color: #EFEFF4;
}
.feedback input,
.feedback textarea {
border: none !important;
}
.feedback textarea {
height: 100px;
margin-bottom: 0 !important;
padding-bottom: 0 !important;
}
.feedback .row {
width: 100%;
background-color: #fff;
}
.feedback p {
padding: 10px 15px 0;
}
.feedback button#submit {
width: 90%;
height: 46px;
left: 50%;
-webkit-transform: translate(-50%);
}
.feedback .hidden {
display: none;
}
.feedback .image-list {
width: 100%;
height: 85px;
background-size: cover;
padding: 10px 10px;
overflow: hidden;
}
.feedback .image-item {
width: 65px;
height: 65px;
background-image: url(../images/iconfont-tianjia.png);
background-size: 100% 100%;
display: inline-block;
position: relative;
border-radius: 5px;
margin-right: 10px;
margin-bottom: 10px;
border: solid 1px #e8e8e8;
}
.feedback .image-item input[type="file"] {
position: absolute;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
z-index: 0;
}
.feedback .image-item.space {
border: none;
}
.feedback .image-item .image-close {
position: absolute;
display: inline-block;
right: -6px;
top: -6px;
width: 20px;
height: 20px;
text-align: center;
line-height: 20px;
border-radius: 12px;
background-color: #FF5053;
color: #f3f3f3;
border: solid 1px #FF5053;
font-size: 9px;
font-weight: 200;
z-index: 1;
}
.feedback .image-item.space .image-close {
display: none;
}
\ No newline at end of file
(function(mui, window, document, undefined) {
mui.init();
var get = function(id) {
return document.getElementById(id);
};
var qsa = function(sel) {
return [].slice.call(document.querySelectorAll(sel));
};
var ui = {
question: get('question'),
contact: get('contact'),
imageList: get('image-list'),
submit: get('submit')
};
ui.clearForm = function() {
ui.question.value = '';
ui.contact.value = '';
ui.imageList.innerHTML = '';
ui.newPlaceholder();
};
ui.getFileInputArray = function() {
return [].slice.call(ui.imageList.querySelectorAll('input[type="file"]'));
};
ui.getFileInputIdArray = function() {
var fileInputArray = ui.getFileInputArray();
var idArray = [];
fileInputArray.forEach(function(fileInput) {
if (fileInput.value != '') {
idArray.push(fileInput.getAttribute('id'));
}
});
return idArray;
};
var imageIndexIdNum = 0;
ui.newPlaceholder = function() {
var fileInputArray = ui.getFileInputArray();
if (fileInputArray &&
fileInputArray.length > 0 &&
fileInputArray[fileInputArray.length - 1].parentNode.classList.contains('space')) {
return;
}
imageIndexIdNum++;
var placeholder = document.createElement('div');
placeholder.setAttribute('class', 'image-item space');
var closeButton = document.createElement('div');
closeButton.setAttribute('class', 'image-close');
closeButton.innerHTML = 'X';
closeButton.addEventListener('click', function(event) {
event.stopPropagation();
event.cancelBubble = true;
setTimeout(function() {
ui.imageList.removeChild(placeholder);
}, 0);
return false;
}, false);
var fileInput = document.createElement('input');
fileInput.setAttribute('type', 'file');
fileInput.setAttribute('accept', 'image/*');
fileInput.setAttribute('id', 'image-' + imageIndexIdNum);
fileInput.addEventListener('change', function(event) {
var file = fileInput.files[0];
if (file) {
var reader = new FileReader();
reader.onload = function() {
//处理 android 4.1 兼容问题
var base64 = reader.result.split(',')[1];
var dataUrl = 'data:image/png;base64,' + base64;
//
placeholder.style.backgroundImage = 'url(' + dataUrl + ')';
}
reader.readAsDataURL(file);
placeholder.classList.remove('space');
ui.newPlaceholder();
}
}, false);
placeholder.appendChild(closeButton);
placeholder.appendChild(fileInput);
ui.imageList.appendChild(placeholder);
};
ui.newPlaceholder();
ui.submit.addEventListener('tap', function(event) {
if (ui.question.value == '' ||
(ui.contact.value != '' &&
ui.contact.value.search(/^(\w+((-\w+)|(\.\w+))*\@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+)|([1-9]\d{4,9})$/) != 0)) {
return mui.toast('信息填写不符合规范');
}
plus.nativeUI.showWaiting();
feedback.send({
question: ui.question.value,
contact: ui.contact.value,
images: ui.getFileInputIdArray()
}, function() {
plus.nativeUI.closeWaiting();
mui.toast('感谢您的建议~');
ui.clearForm();
mui.back();
});
}, false);
})(mui, window, document, undefined);
\ No newline at end of file
(function($, feedback, window, document) {
/*************** 环信配置开始 ****************/
//以后信息更改后,需卸载 “调试 app” 重新调用运行
var APP_KEY = 'dcloudio#mui';
var CUSTOM_ID = 'customer';
/*************** 环信配置结束 ****************/
//一组 “常量”
var PASSWORD = 'pass01!';
var LOCAL_STORE_KEY = 'mui://user';
var USER_PREFIX = 'mui-user-';
/**
* 生成一个 IM 用户名
**/
var createUsername = function() {
return USER_PREFIX + (new Date()).getTime();
};
/**
* 获取用户,如果在本地存储中已有用户则直接返回。
* 否则,注册新的用户
**/
feedback.getUser = function(callback) {
var storeUserText = localStorage.getItem(LOCAL_STORE_KEY);
if (storeUserText) {
if (callback) callback(JSON.parse(storeUserText));
return;
}
var newUsername = createUsername();
Easemob.im.Helper.registerUser({
username: newUsername,
password: PASSWORD,
appKey: APP_KEY,
success: function(result) {
var userInfo = {
username: newUsername,
password: PASSWORD
};
localStorage.setItem(LOCAL_STORE_KEY, JSON.stringify(userInfo));
if (callback) callback(userInfo);
},
error: function(e) {
plus.nativeUI.toast(e.message);
}
});
};
/**
* 登录环信息服务器
**/
feedback.login = function(callback) {
feedback.getUser(function(user) {
var conn = new Easemob.im.Connection();
conn.init({
onOpened: function() {
//alert("成功登录");
conn.setPresence();
if (callback) callback(user, conn);
}
});
conn.open({
user: user.username,
pwd: user.password,
appKey: APP_KEY
});
});
};
/**
* 发送反馈信息
**/
feedback.send = function(content, callback) {
feedback.login(function(user, conn) {
//发送文本消息
var msgText = '问题:' + content.question;
if (content.contact) {
msgText += '; 联系方式:' + content.contact + ';'
}
conn.sendTextMessage({
to: CUSTOM_ID,
msg: msgText,
type: "chat"
});
//如果没有截图
if (!content.images || content.images.length < 1) {
if (callback) callback();
return;
}
//如果有截图
var sendImageCount = 0;
var hasError = false;
content.images.forEach(function(fileInputId) {
//alert(fileInputId)
conn.sendPicture({
fileInputId: fileInputId,
to: CUSTOM_ID,
onFileUploadError: function(error) {
//处理图片上传失败
alert(JSON.stringify(error));
hasError = true;
},
onFileUploadComplete: function(data) {
//处理图片上传成功,如本地消息显示
sendImageCount++;
if (!hasError && sendImageCount >= content.images.length) {
if (callback) callback();
}
}
});
});
//--
});
};
})(mui, window.feedback = {}, window, document);
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
json2.js
2014-02-04
Public Domain.
NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.
See http://www.JSON.org/js.html
This code should be minified before deployment.
See http://javascript.crockford.com/jsmin.html
USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
NOT CONTROL.
This file creates a global JSON object containing two methods: stringify
and parse.
JSON.stringify(value, replacer, space)
value any JavaScript value, usually an object or array.
replacer an optional parameter that determines how object
values are stringified for objects. It can be a
function or an array of strings.
space an optional parameter that specifies the indentation
of nested structures. If it is omitted, the text will
be packed without extra whitespace. If it is a number,
it will specify the number of spaces to indent at each
level. If it is a string (such as '\t' or '&nbsp;'),
it contains the characters used to indent at each level.
This method produces a JSON text from a JavaScript value.
When an object value is found, if the object contains a toJSON
method, its toJSON method will be called and the result will be
stringified. A toJSON method does not serialize: it returns the
value represented by the name/value pair that should be serialized,
or undefined if nothing should be serialized. The toJSON method
will be passed the key associated with the value, and this will be
bound to the value
For example, this would serialize Dates as ISO strings.
Date.prototype.toJSON = function (key) {
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
return this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z';
};
You can provide an optional replacer method. It will be passed the
key and value of each member, with this bound to the containing
object. The value that is returned from your method will be
serialized. If your method returns undefined, then the member will
be excluded from the serialization.
If the replacer parameter is an array of strings, then it will be
used to select the members to be serialized. It filters the results
such that only members with keys listed in the replacer array are
stringified.
Values that do not have JSON representations, such as undefined or
functions, will not be serialized. Such values in objects will be
dropped; in arrays they will be replaced with null. You can use
a replacer function to replace those with JSON values.
JSON.stringify(undefined) returns undefined.
The optional space parameter produces a stringification of the
value that is filled with line breaks and indentation to make it
easier to read.
If the space parameter is a non-empty string, then that string will
be used for indentation. If the space parameter is a number, then
the indentation will be that many spaces.
Example:
text = JSON.stringify(['e', {pluribus: 'unum'}]);
// text is '["e",{"pluribus":"unum"}]'
text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
// text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'
text = JSON.stringify([new Date()], function (key, value) {
return this[key] instanceof Date ?
'Date(' + this[key] + ')' : value;
});
// text is '["Date(---current time---)"]'
JSON.parse(text, reviver)
This method parses a JSON text to produce an object or array.
It can throw a SyntaxError exception.
The optional reviver parameter is a function that can filter and
transform the results. It receives each of the keys and values,
and its return value is used instead of the original value.
If it returns what it received, then the structure is not modified.
If it returns undefined then the member is deleted.
Example:
// Parse the text. Values that look like ISO date strings will
// be converted to Date objects.
myData = JSON.parse(text, function (key, value) {
var a;
if (typeof value === 'string') {
a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
if (a) {
return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
+a[5], +a[6]));
}
}
return value;
});
myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
var d;
if (typeof value === 'string' &&
value.slice(0, 5) === 'Date(' &&
value.slice(-1) === ')') {
d = new Date(value.slice(5, -1));
if (d) {
return d;
}
}
return value;
});
This is a reference implementation. You are free to copy, modify, or
redistribute.
*/
/*jslint evil: true, regexp: true */
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
lastIndex, length, parse, prototype, push, replace, slice, stringify,
test, toJSON, toString, valueOf
*/
// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.
if (typeof JSON !== 'object') {
JSON = {};
}
(function () {
'use strict';
function f(n) {
// Format integers to have at least two digits.
return n < 10 ? '0' + n : n;
}
if (typeof Date.prototype.toJSON !== 'function') {
Date.prototype.toJSON = function () {
return isFinite(this.valueOf())
? this.getUTCFullYear() + '-' +
f(this.getUTCMonth() + 1) + '-' +
f(this.getUTCDate()) + 'T' +
f(this.getUTCHours()) + ':' +
f(this.getUTCMinutes()) + ':' +
f(this.getUTCSeconds()) + 'Z'
: null;
};
String.prototype.toJSON =
Number.prototype.toJSON =
Boolean.prototype.toJSON = function () {
return this.valueOf();
};
}
var cx,
escapable,
gap,
indent,
meta,
rep;
function quote(string) {
// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.
escapable.lastIndex = 0;
return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
var c = meta[a];
return typeof c === 'string'
? c
: '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
}) + '"' : '"' + string + '"';
}
function str(key, holder) {
// Produce a string from holder[key].
var i, // The loop counter.
k, // The member key.
v, // The member value.
length,
mind = gap,
partial,
value = holder[key];
// If the value has a toJSON method, call it to obtain a replacement value.
if (value && typeof value === 'object' &&
typeof value.toJSON === 'function') {
value = value.toJSON(key);
}
// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.
if (typeof rep === 'function') {
value = rep.call(holder, key, value);
}
// What happens next depends on the value's type.
switch (typeof value) {
case 'string':
return quote(value);
case 'number':
// JSON numbers must be finite. Encode non-finite numbers as null.
return isFinite(value) ? String(value) : 'null';
case 'boolean':
case 'null':
// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.
return String(value);
// If the type is 'object', we might be dealing with an object or an array or
// null.
case 'object':
// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.
if (!value) {
return 'null';
}
// Make an array to hold the partial results of stringifying this object value.
gap += indent;
partial = [];
// Is the value an array?
if (Object.prototype.toString.apply(value) === '[object Array]') {
// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.
length = value.length;
for (i = 0; i < length; i += 1) {
partial[i] = str(i, value) || 'null';
}
// Join all of the elements together, separated with commas, and wrap them in
// brackets.
v = partial.length === 0
? '[]'
: gap
? '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']'
: '[' + partial.join(',') + ']';
gap = mind;
return v;
}
// If the replacer is an array, use it to select the members to be stringified.
if (rep && typeof rep === 'object') {
length = rep.length;
for (i = 0; i < length; i += 1) {
if (typeof rep[i] === 'string') {
k = rep[i];
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
} else {
// Otherwise, iterate through all of the keys in the object.
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = str(k, value);
if (v) {
partial.push(quote(k) + (gap ? ': ' : ':') + v);
}
}
}
}
// Join all of the member texts together, separated with commas,
// and wrap them in braces.
v = partial.length === 0
? '{}'
: gap
? '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}'
: '{' + partial.join(',') + '}';
gap = mind;
return v;
}
}
// If the JSON object does not yet have a stringify method, give it one.
if (typeof JSON.stringify !== 'function') {
escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
meta = { // table of character substitutions
'\b': '\\b',
'\t': '\\t',
'\n': '\\n',
'\f': '\\f',
'\r': '\\r',
'"' : '\\"',
'\\': '\\\\'
};
JSON.stringify = function (value, replacer, space) {
// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.
var i;
gap = '';
indent = '';
// If the space parameter is a number, make an indent string containing that
// many spaces.
if (typeof space === 'number') {
for (i = 0; i < space; i += 1) {
indent += ' ';
}
// If the space parameter is a string, it will be used as the indent string.
} else if (typeof space === 'string') {
indent = space;
}
// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.
rep = replacer;
if (replacer && typeof replacer !== 'function' &&
(typeof replacer !== 'object' ||
typeof replacer.length !== 'number')) {
throw new Error('JSON.stringify');
}
// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.
return str('', {'': value});
};
}
// If the JSON object does not yet have a parse method, give it one.
if (typeof JSON.parse !== 'function') {
cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
JSON.parse = function (text, reviver) {
// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.
var j;
function walk(holder, key) {
// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.
var k, v, value = holder[key];
if (value && typeof value === 'object') {
for (k in value) {
if (Object.prototype.hasOwnProperty.call(value, k)) {
v = walk(value, k);
if (v !== undefined) {
value[k] = v;
} else {
delete value[k];
}
}
}
}
return reviver.call(holder, key, value);
}
// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.
text = String(text);
cx.lastIndex = 0;
if (cx.test(text)) {
text = text.replace(cx, function (a) {
return '\\u' +
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
});
}
// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.
// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
if (/^[\],:{}\s]*$/
.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
.replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.
j = eval('(' + text + ')');
// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.
return typeof reviver === 'function'
? walk({'': j}, '')
: j;
}
// If the text is not JSON parseable, then a SyntaxError is thrown.
throw new SyntaxError('JSON.parse');
};
}
}());
---
title: WebIM 开发指南
sidebar: webimsidebar
secondnavwebim: true
---
# 快速入门
## 初始化
### 创建连接{#conn_new}
<pre class="hll"><code class="language-javascript">
var conn = new Easemob.im.Connection();
</code></pre>
### 初始化连接{#conn_init}
<pre class="hll"><code class="language-javascript">
conn.init({
https : true,//非必填,url值未设置时有效,优先采用url配置的参数。默认采用http连接,地址为‘http://im-api.easemob.com/http-bind/’,启用https时传递此值,地址为:‘https://im-api.easemob.com/http-bind/’
url : 'http://im-api.easemob.com/http-bind/',//非必填,默认聊天服务器地址,
domain : 'aa.com',//非必填,默认:‘easemob.com’
wait : '60',//非必填,连接超时,默认:60,单位seconds
onOpened : function() {
curUserId = conn.context.userId;
//查询好友列表
conn.getRoster(....);
},
onClosed : function() {
//处理登出事件
},
onTextMessage : function(message) {
/**处理文本消息,消息格式为:
{ type :'chat',//群聊为“groupchat”
from : from,
to : too,
data : { "type":"txt",
"msg":"hello from test2"
}
}
*/
handleTextMessage(message);
},
onEmotionMessage : function(message) {
/*处理表情消息,消息格式为:
{ type :'chat',//群聊为“groupchat”
from : from,
to : too,
data : [{ "type":"txt",
"msg":"hello from test2"
},
{ "type":"emotion",
"msg":"data:image/png;base64, ……"//图片的base64编码
}]
}
*/
handleEmotion(message);
},
onPictureMessage : function(message) {
/**处理图片消息,消息格式为:
{ type :'chat',//群聊为“groupchat”
from : "test1",
to : "test2",
url : "http://s1.easemob.com/weiquan2/a2/chatfiles/0c0f5f3a-e66b-11e3-8863-f1c202c2b3ae",
secret : "NSgGYPCxEeOou00jZasg9e-GqKUZGdph96EFxJ4WxW-qkxV4",
filename : "logo.png",
thumb : "http://s1.easemob.com/weiquan2/a2/chatfiles/0c0f5f3a-e66b-11e3-8863-f1c202c2b3ae",
thumb_secret : "0595b06a-ed8b-11e3-9b85-93fade9c198c",
file_length : 42394,
width : 280,
height : 160,
filetype : "image/png",
accessToken :"YWMtjPPoovCqEeOQs7myPqqaOwAAAUaqNH0a8rRj4PwJLQju6-S47ZO6wYs3Lwo"
}
*/
handlePictureMessage(message);
},
onAudioMessage : function(message) {
/**处理音频消息,消息格式为:
{ type :'chat',//群聊为“groupchat”
from : "test1",
to : "test2",
url : "http://s1.easemob.com/weiquan2/a2/chatfiles/0c0f5f3a-e66b-11e3-8863-f1c202c2b3ae",
secret :"NSgGYPCxEeOou00jZasg9e-GqKUZGdph96EFxJ4WxW-qkxV4",
filename : "风雨无阻.mp3",
length :45223,
file_length : 304,
filetype : "mp3",
accessToken :"YWMtjPPoovCqEeOQs7myPqqaOwAAAUaqNH0a8rRj4PwJLQju6-S47ZO6wYs3Lwo"
}
*/
handleAudioMessage(message);
},
//收到联系人订阅请求的回调方法
onPresence : function (message){
/**
{
from: "l2",
fromJid: "easemob-demo#chatdemoui_l2@easemob.com",
status: "下午11:44:47",
to: "test1",
toJid: "easemob-demo#chatdemoui_test1@easemob.com/13856640471403797405809685",
type: "subscribed"
}
*/
handlePresence(message);
},
//收到联系人信息的回调方法
onRoster : function (message){
/**
[{
groups: [{0: "default",
length: 1}],
jid: "easemob-demo#chatdemoui_l2@easemob.com",
name: "l2",
subscription: "to"
}]
*/
handleRoster(message);
},
onError : function(e) {
//异常处理
alert(e.msg);
}
});
</code></pre>
### 打开连接{#conn_open}
支持username/password和username/token登录两种方式,sdk中会根据传入的参数进行自动选择是否登录usergrid,获取登录成功的token后再进行登录聊天,如果使用token的打开连接将跳过登录usergird,直接登录IM服务器。
<pre class="hll"><code class="language-javascript">
//用户名
var user = $("#username").val();
//密码
var pass = $("#password").val();
if (user == '' || pass == '') {
alert("请输入用户名和密码");
return;
}
conn.open({
user : user,
pwd : pass,
appKey : 'easemob-demo#chatdemoui'//开发者APPKey
//accessToken : 'YWMt8bfZfFk5EeSiAzsQ0OXu4QAAAUpoZFOMJ66ic5m2LOZRhYUsRKZWINA06HI'
});
</code></pre>
## 单聊{#single_chat}
### 查询好友列表{#getRoster}
查询好友列表时,要注意susciption(both,to,from)为不同值得处理,此处默认both和to的为好友,开发者自定义处理,保持跟APP端处理一致即可。
<pre class="hll"><code class="language-javascript">
conn.getRoster({
success : function(roster) {
//获取好友列表,并进行好友列表渲染,roster格式为:
/** [
{
jid:"asemoemo#chatdemoui_test1@easemob.com",
name:"test1",
subscription: "both"
},
{
jid:"asemoemo#chatdemoui_test2@easemob.com",
name:"test2",
subscription: "from"
}
]
*/
for(var i in roster){
var ros = roster[i];
//ros.subscriptio值为both/to为要显示的联系人,此处与APP需保持一致,才能保证两个客户端登录后的好友列表一致
if(ros.subscription =='both' || ros.subscription=='to'){
newroster.push(ros);
}
}
if (newroster.length >=0) {
buildContactDiv("contractlist", newroster);//页面处理
if (newroster.length > 0) {
setCurrentContact(newroster[0].name);//页面处理将第一个联系人作为当前聊天div
}
}
//conn.setPresence();
},
});
</code></pre>
### 添加好友{#subscribe}
通过sdk的subscribe和unsubcribe进行添加或者删除好友操作,登录用户通过注册onPresence,监听对方的添加或者删除好友请求,并做相应的处理。
<pre class="hll"><code class="language-javascript">
//easemobwebim-sdk中收到联系人订阅请求的处理方法,具体的type值所对应的值请参考xmpp协议规范
var handlePresence = function (e){
//(发送者希望订阅接收者的出席信息),即别人申请加你为好友
if (e.type == 'subscribe') {
//若e.status中含有[resp:true],则表示为对方同意好友后反向添加自己为好友的消息,demo中发现此类消息,默认同意操作,完成双方互为好友;如果不含有[resp:true],则表示为正常的对方请求添加自己为好友的申请消息。
......
}
//(发送者允许接收者接收他们的出席信息),即别人同意你加他为好友
if (e.type == 'subscribed') {
......
}
//(发送者取消订阅另一个实体的出席信息),即删除现有好友
if (e.type == 'unsubscribe') {
.......
}
//(订阅者的请求被拒绝或以前的订阅被取消),即对方单向的删除了好友
if (e.type == 'unsubscribed') {
.......
}
};
</code></pre>
#### 申请添加对方为好友{#addFriend}
<pre class="hll"><code class="language-javascript">
//主动申请添加对方为好友
var startAddFriend = function startAddFriend(){
//对方用户账号
var user = $("addfridentId").val();
//请求添加对方为好友
conn.subscribe({
to : user,
message : "加个好友呗-" + getLoacalTimeString()
});
return;
};
var getLoacalTimeString = function getLoacalTimeString() {
var date = new Date();
var time = date.getHours() + ":" + date.getMinutes() + ":"
+ date.getSeconds();
return time;
}
</code></pre>
#### 对方收到请求,同意或者拒绝{#agreed_reject}
<pre class="hll"><code class="language-javascript">
//对方收到请求加为好友,接受请求
$('#confirm-block-footer-confirmButton').click(function() {
//同意好友请求
agreeAddFriend(e.from);//e.from用户名
//反向添加对方好友
conn.subscribe({
to : e.from,
message : "[resp:true]"
});
}
//同意
var agreeAddFriend = function agreeAddFriend(connection,who,jid){
conn.subscribed({
to : user,
message : "[resp:true]"//同意后发送反加对方为好友的消息,反加消息标识[resp:true]
});
};
//对方收到请求加为好友,拒绝请求
$('#confirm-block-footer-cancelButton').click(function() {
rejectAddFriend(e.from);//拒绝加为好友
});
//拒绝
var rejectAddFriend = function(user) {
conn.unsubscribed({
to : user,
message : getLoacalTimeString()
});
};
</code></pre>
对于好友的分组,添加好友时在addroster可以指定group属性(默认为:default组),添加好友成功后,好友列表渲染时,根据好友的group属性进行分组渲染,实现类似其他聊天工具的自定义好友分组管理的功能。
#### 删除好友{#delfriend}
取消订阅,同时将对方从自己的好友列表上删除掉。
<pre class="hll"><code class="language-javascript">
var delFriend = function(user) {
conn.removeRoster({
to : user,
groups : [ 'default' ],
success : function() {
conn.**unsubscribed**({
to : user
});
}
});
};
</code></pre>
### 发送文本(表情)聊天消息{#sendTextMessage}
<pre class="hll"><code class="language-javascript">
//发送文本消息
conn.sendTextMessage({
to : to,//用户登录名,sd根据appkey和domain组织jid,如easemob-demo#chatdemoui_**TEST**@easemob.com,中"to:TEST",下同
msg :'hello world!' //文本消息
});
//发送表情消息,调用接口同文本消息
conn.sendTextMessage({
to : to,
msg :'hello world![(*)][(#)]' //文本消息+表情
});
</code></pre>
### 发送图片消息{#sendPic}
发送图片消息sdk自动分两步完成:<br>
1)上传图片文件到服务器,并得到服务返回的图片信息等<br>
2)发送图片消息,消息体包含图片的基本信息、服务器路径、secret等,接收方初始化连接中的onPictureMessage的格式,根据图片消息内容到服务器下载图片,并进行显示
<pre class="hll"><code class="language-javascript">
function sendPic() {
//图片接收者,如“test1”
var to = curChatUserId;
if (to == null) {
alert("请选择联系人");
return;
}
//fileInputId:文件选择输入框的Id,sdk自动根据id自动获取文件对象(含图片,或者其他类型文件)
var fileObj = Easemob.im.Helper.getFileUrl(fileInputId);
if (fileObj.url == null || fileObj.url == '') {
alert("请选择发送图片");
return;
}
var filetype = fileObj.filetype;
var filename = fileObj.filename;
if (filetype in {
"jpg" : true,
"gif" : true,
"png" : true,
"bmp" : true
}) {
var opt = {
fileInputId : fileInputId,
to : to,
onFileUploadError : function(error) {
//处理图片上传失败
},
onFileUploadComplete : function(data) {
//处理图片上传成功,如本地消息显示
}
};
conn.sendPicture(opt);
return;
}
alert("不支持此图片类型" + filetype);
};
</code></pre>
### 发送音频消息{#sendAudio}
sdk处理同发送图片消息,分两步:
1. 上传音频文件到服务器,得到音频文件的信息;
2. 发送音频消息给接收方,消息体包含音频的基本信息、下载路径和secret信息等,接收方收到消息后,根据消息体内部的音频下载路径和secret路径,下载音频并进行显示。
<pre class="hll"><code class="language-javascript">
function sendAudio () {
var to = curChatUserId;
if (to == null) {
alert("请选择联系人");
return;
}
var fileObj = Easemob.im.Helper.getFileUrl(fileInputId);
if (fileObj.url == null || fileObj.url == '') {
alert("请选择发送音频");
return;
}
var filetype = fileObj.filetype;
var filename = fileObj.filename;
if (filetype in {
"mp3" : true,
"wma" : true,
"wav" : true,
"avi" : true
})
{
var opt = {
fileInputId : fileInputId,
to : to,
onFileUploadError : function(error) {
//处理上传音频失败
},
onFileUploadComplete : function(data) {
//处理上传音频成功,如本地消息提示发送成功
}
};
conn.sendAudio(opt);
return;
}
alert("不支持此音频类型" + filetype);
};
</code></pre>
### 接收消息
#### 注册接收消息 {#onmessage}
<pre class="hll"><code class="language-javascript">
conn.init({
onTextMessage : function(message) { },//收到文本消息处理动作
onEmotionMessage : function(message) { },//收到表情消息处理动作
onPictureMessage : function(message) { },//收到图片消息处理动作
onAudioMessage : function(message) { }, //收到语音消息处理动作
...
});
</code></pre>
#### 处理消息{#options}
conn.init()中注册不同消息接收handler之后,可自行解析消息体,定位聊天好友,并追加到与其聊天窗口。具体参考webim.easemob.com效果,消息体格式参见前章节:初始化连接。<br>
注:对于图片、语音消息需要先进行下载,然后进行显示或者播放处理。如下(下载图片,音频同):
<pre class="hll"><code class="language-javascript">
var handlePictureMessage = function(message) {
var filename = message.filename;//文件名称,带文件扩展名
var from = message.from;//文件的发送者
var mestype = message.type;//消息发送的类型是群组消息还是个人消息
......
...
var options = message;
// 图片消息下载成功后的处理逻辑
options.onFileDownloadComplete = function(response, xhr) {
var objectURL = window.URL.createObjectURL(response);
img = document.createElement("img");
img.onload = function(e) {
img.onload = null;
window.URL.revokeObjectURL(img.src);
};
img.onerror = function() {
img.onerror = null;
if (typeof FileReader == 'undefined') {
img.alter = "当前浏览器不支持blob方式";
return;
}
img.onerror = function() {
img.alter = "当前浏览器不支持blob方式";
};
var reader = new FileReader();
reader.onload = function(event) {
img.src = this.result;
};
reader.readAsDataURL(response);
}
img.src = objectURL;
var pic_real_width = options.width;
......
...
};
options.onFileDownloadError = function(e) {
appendMsg(from, contactDivId, e.msg + ",下载图片" + filename + "失败");
};
Easemob.im.Helper.download(options);
</code></pre>
#### 历史消息{#history_message}
sdk暂不具有缓存历史消息功能,demo中聊天窗口只能显示,当前登录后会话实时在聊天信息,不能查看历史消息,可以对登录后的聊天信息进行清除操作。
#### 新消息提示{#new_message}
sdk在收到新消息是会直接转发给登录用户,接收到消息后,demo中会在好友或者群组的后面显示红色消息数,具体样式开发者可自行处理。
## 群聊{#group_chat}
### 查询群组成员{#queryOccupants}
<pre class="hll"><code class="language-javascript">
//根据roomId查询room成员列表
var queryOccupants = function queryOccupants(roomId) {
var occupants = [];//存放成员容器
//查询获取room信息
conn.queryRoomInfo({
roomId : roomId,
success : function(occs) {
if (occs) {
for ( var i = 0; i < occs.length; i++) {
occupants.push(occs[i]);
}
}
//查询获取room成员信息
conn.queryRoomMember({
roomId : roomId,
success : function(members) {
if (members) {
for ( var i = 0; i < members.length; i++) {
occupants.push(members[i]);
}
}
}
});
}
});
};
</code></pre>
### 发送文本(表情)聊天消息{#group_sendTextMessage}
<pre class="hll"><code class="language-javascript">
//发送文本消息
conn.sendTextMessage({
to : to,
type : 'groupchat',
msg :'hello world!' //文本消息
});
//发送表情消息,调用接口同文本消息
conn.sendTextMessage({
to : to,
type : 'groupchat',
msg :'hello world![(*)][(#)]' //文本消息+表情
});
</code></pre>
### 发送图片消息{#group_sendPic}
发送图片消息sdk自动分两步完成
1. 上传图片文件
2. 发送图片消息初始化连接中的onPictureMessage的格式
<pre class="hll"><code class="language-javascript">
//发送图片消息时调用方法
var sendPic = function() {
var to = curChatUserId;
if (to == null) {
return;
}
// Easemob.im.Helper.getFileUrl为easemobwebim-sdk获取发送文件对象的方法,fileInputId为 input 标签的id值
var fileObj = Easemob.im.Helper.getFileUrl(fileInputId);
if (fileObj.url == null || fileObj.url == '') {
alert("请选择发送图片");
return;
}
var filetype = fileObj.filetype;
var filename = fileObj.filename;
if (filetype in pictype) {
document.getElementById("fileSend").disabled = true;
document.getElementById("cancelfileSend").disabled = true;
var opt = {
type:'chat',
fileInputId : fileInputId,
to : to,
onFileUploadError : function(error) {
//处理图片上传失败
},
onFileUploadComplete : function(data) {
//关闭文件选择窗口
$('#fileModal').modal('hide');
//本地缩略图
var file = document.getElementById(fileInputId);
if (file && file.files) {
var objUrl = getObjectURL(file.files[0]);
if (objUrl) {
var img = document.createElement("img");
img.src = objUrl;
img.width = maxWidth;
}
}
}
};
//判断是否为群组标识
if (curChatUserId.indexOf(groupFlagMark) >= 0) {
opt.type = 'groupchat';//群组标识符
opt.to = curRoomId;
}
conn.sendPicture(opt);
return;
}
alert("不支持此图片类型" + filetype);
};
</code></pre>
### 发送音频消息{#group_sendAudio}
sdk处理同群发送图片消息,分两步
1. 上传音频
2. 发送消息
<pre class="hll"><code class="language-javascript">
//发送音频消息时调用的方法
var sendAudio = function() {
var to = curChatUserId;
if (to == null) {
alert("请选择联系人");
return;
}
//利用easemobwebim-sdk提供的方法来构造一个file对象
var fileObj = Easemob.im.Helper.getFileUrl(fileInputId);
if (fileObj.url == null || fileObj.url == '') {
alert("请选择发送音频");
return;
}
var filetype = fileObj.filetype;
var filename = fileObj.filename;
if (filetype in audtype) {
document.getElementById("fileSend").disabled = true;
document.getElementById("cancelfileSend").disabled = true;
var opt = {
type:"chat",
fileInputId : fileInputId,
to : to,//发给谁
onFileUploadError : function(error) {
//处理上传音频失败
},
onFileUploadComplete : function(data) {
//处理上传音频成功,如本地消息提示发送成功
}
};
//构造完opt对象后调用easemobwebim-sdk中发送音频的方法
if (curChatUserId.indexOf(groupFlagMark) >= 0) {
opt.type = 'groupchat';
opt.to = curRoomId;
}
conn.sendAudio(opt);
return;
}
alert("不支持此音频类型" + filetype);
};
</code></pre>
### 接收及处理消息{#messageType}
群聊接收及处理消息同单聊,消息体与单聊消息根据message的type进行区分,单聊为:“chat”,群聊为:“groupchat”。根据消息的类型进行不同处理即可。
## 退出{#quit}
### 关闭连接{#conn_close}
//sdk关闭连接并处理连接状态为CLOSED
<pre class="hll"><code class="language-javascript">
conn.close();
</code></pre>
## 工具类说明{#sdk_tools}
### 表情工具类{#emotion}
<pre class="hll"><code class="language-javascript">
//返回表情JSON object,格式为:
{
"[):]" : "data:image/png;base64,iVBORw0K....==",
"[:D]" : "data:image/png;base64,iVBORw0KGgoAAAANSUh....=="
}
var emotion_json = Easemob.im.Helper.EmotionPicData;
</code></pre>
### Base64工具类{#base64}
<pre class="hll"><code class="language-javascript">
var base64 = Easemob.im.Helper.Base64;
var srcstr="ssss";
var base64str = base64.encode(srcstr);
var orgstr = base64.decode(srcstr);
</code></pre>
### 文件上传工具类{#fileupload}
<pre class="hll"><code class="language-javascript">
//是否能上传file
var canupload = Easemob.im.Helper.isCanUploadFile;
//是否能下载file
var candownload = Easemob.im.Helper.isCanDownLoadFile ;
//是否设置header
var hasheader = Easemob.im.Helper.hasSetRequestHeader;
//是否设置mimetype
var hasmimetype = Easemob.im.Helper.hasOverrideMimeType;
</code></pre>
### 表情解析工具类{#handleMotion}
<pre class="hll"><code class="language-javascript">
//返回表情JSON,格式为:
{
isemotion:true;
body:[{
type:txt,
msg:ssss
},
{
type:emotion,
msg:imgdata
}]
}
var emotionMsg = Easemob.im.Helper.parseTextMessage(message);
</code></pre>
### 文件上传工具类{#fileupdate}
<pre class="hll"><code class="language-javascript">
//返回fileinfo对象,格式为:
{
url : '',
filename : '',
filetype : ''
}
var fileInfo = Easemob.im.Helper.getFileUrl(fileInputId);
//上传
var options={
appName = 'chatdemoui',
orgName = 'easemob-demo',
accessToken = 'YWMtjPPoovCqEeOQs7myPqqaOwAAAUaqNH0a8rRj4PwJLQju6-S47ZO6wYs3Lwo',
onFileUploadComplete:function(data){//upload file success },
onFileUploadError:function(e){//upload file error },
width:100,//only for pic
heght:100//only for pic
}
Easemob.im.Helper.upload(options);
//下载
var options = {
method:'GET',//default GET
responseType:'blob',//default blob
mimeType:'text/plain; charset=x-user-defined',//default
url:'http://s1.easemob.com/weiquan2/a2/chatfiles/0c0f5f3a-e66b-11e3-8863-f1c202c2b3ae',
secret = 'NSgGYPCxEeOou00jZasg9e-GqKUZGdph96EFxJ4WxW-qkxV4',
accessToken = 'YWMtjPPoovCqEeOQs7myPqqaOwAAAUaqNH0a8rRj4PwJLQju6-S47ZO6wYs3Lwo',
onFileUploadComplete:function(data){//upload file success },
onFileUploadError:function(e){//upload file error },
}
Easemob.im.Helper.download(options);
//文件大小
var options={
fileInputId:'uploadfileinput'//文件输入框id
};
var fileSize = getFileSize(options.fileInputId);;
</code></pre>
### 发送Ajax请求{#ajaxresquest}
<pre class="hll"><code class="language-javascript">
var options = {
dataType:'text',//default
success:function(){//handle request success},
error :function(){//handle request error},
type : 'post',//default 'post'
url : 'http://s1.easemob.com/weiquan2/a2/chatfiles/0c0f5f3a-e66b-11e3-8863-f1c202c2b3ae',
headers:'',//default {}
data : '';//default null
};
Easemob.im.Helper.xhr(options);
</code></pre>
### 登录{#sdk_login}
<pre class="hll"><code class="language-javascript">
var options = {
appKey:'easemob-demo#chatdemoui',//default ''
success:function(data){ //login success },//default emptyFn
error : cunction(error){ //login error }, //default emptyFn
user : 'test1', //default ''
pwd : '123456' //default ''
};
Easemob.im.Helper.login2UserGrid(options);
</code></pre>
### 注册{#sdk_regist}
<pre class="hll"><code class="language-javascript">
vvar options = {
username : 'zjj8',
password : '123456',
appKey : 'easemob-demo#chatdemoui',
success : function(result) {
//注册成功
},
error : function(e) {
//注册失败
}
};
Easemob.im.Helper.registerUser(options);
</code></pre>
### 内置空函数{#null_function}
当所有需要回调的地方接受到函数时,默认采用此函数
<pre class="hll"><code class="language-javascript">
var emptyFn = function() {};
</code></pre>
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -175,7 +175,7 @@
plus.nativeUI.toast("登录认证成功");
//alert(JSON.stringify(auth.authResult));
auth.getUserInfo(function() {
plus.nativeUI.toast("获取用户信息成功");
plus.nativeUI.toast("获取用户信息成功");
//alert(JSON.stringify(auth.userInfo));
var name = auth.userInfo.nickname || auth.userInfo.name;
app.createState(name, function() {
......
......@@ -77,6 +77,7 @@
}
.mui-navbar .mui-bar .mui-title {
display: inline-block;
position: static;
width: auto;
}
.mui-page-shadow {
......@@ -134,6 +135,7 @@
display: none;
}
</style>
<link rel="stylesheet" type="text/css" href="./css/feedback-page.css" />
</head>
<body>
......@@ -171,6 +173,9 @@
<li class="mui-table-view-cell">
<a id="tel" class="mui-navigate-right">客服电话</a>
</li>
<li class="mui-table-view-cell">
<a id="feedback-btn" href="#feedback" class="mui-navigate-right">问题反馈</a>
</li>
</ul>
<ul class="mui-table-view mui-table-view-chevron">
<li class="mui-table-view-cell">
......@@ -235,11 +240,42 @@
</div>
</div>
</div>
<div id="feedback" class="mui-page feedback">
<div class="mui-navbar-inner mui-bar mui-bar-nav">
<button type="button" class="mui-left mui-action-back mui-btn mui-btn-link mui-btn-nav mui-pull-left">
<span class="mui-icon mui-icon-left-nav"></span>设置
</button>
<h1 class="mui-center mui-title">问题反馈</h1>
</div>
<div class="mui-page-content">
<p>问题和意见</p>
<div class="row mui-input-row">
<textarea id='question' class="mui-input-clear question" placeholder="请详细描述你的问题和意见..."></textarea>
</div>
<p>图片(选填,提供问题截图)</p>
<div id='image-list' class="row image-list">
</div>
<p>QQ/邮箱</p>
<div class="mui-input-row">
<input id='contact' type="text" class="mui-input-clear contact" placeholder="(选填,方便我们联系你 )" />
</div>
<button id='submit' type="button" class="mui-btn mui-btn-green">提交</button>
</div>
<p>此示例基于环信 “WebIM SDK” + 环信 “移动客服” 实现,在环信 “移动客服面板” 能够查阅反馈信息。</p>
</div>
</body>
<script src="./js/mui.min.js "></script>
<script src="./js/mui.view.js "></script>
<script src="js/mui.locker.js"></script>
<script src="js/app.js"></script>
<script src='./libs/easymob-webim-sdk/jquery-1.11.1.js'></script>
<script src='./libs/easymob-webim-sdk/strophe-custom-2.0.0.js'></script>
<script src='./libs/easymob-webim-sdk/json2.js'></script>
<script src="./libs/easymob-webim-sdk/easemob.im-1.0.5.js"></script>
<script src='./js/feedback.js'></script>
<script src="./js/feedback-page.js"></script>
<script src="./js/mui.locker.js"></script>
<script src="./js/app.js"></script>
<script>
mui.init();
//初始化单页view
......@@ -274,6 +310,8 @@
id: "sinaweibo"
}, {
id: "tencentweibo"
}, {
id: "qq"
}],
bts = [{
title: "发送给微信好友"
......@@ -283,15 +321,9 @@
title: "分享到新浪微博"
}, {
title: "分享到腾讯微博"
}];
if (plus.os.name == "iOS") {
ids.push({
id: "qq"
});
bts.push({
}, {
title: "分享到QQ"
});
}
}];
plus.nativeUI.actionSheet({
cancel: "取消",
buttons: bts
......@@ -337,11 +369,11 @@
if (mui.os.ios) {
location.href = 'https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewContentsUserReviews?id=682211190&pageNumber=0&sortOrdering=2&type=&mt=8';
} else if (mui.os.android) {
plus.runtime.openURL( "market://details?id=io.dcloud.HelloMUI", function(e){
plus.runtime.openURL( "market://details?id=io.dcloud.HelloMUI", function(e){
plus.runtime.openURL("market://details?id=io.dcloud.HelloMUI", function(e) {
plus.runtime.openURL("market://details?id=io.dcloud.HelloMUI", function(e) {
mui.alert("360手机助手和应用宝,你一个都没装,暂时无法评分,感谢支持");
}, "com.qihoo.appstore" );
}, "com.tencent.android.qqdownloader" );
}, "com.qihoo.appstore");
}, "com.tencent.android.qqdownloader");
}
});
//客服电话
......@@ -350,7 +382,7 @@
});
//退出操作******************
document.getElementById('exit').addEventListener('tap', function() {
if(mui.os.ios){
if (mui.os.ios) {
app.setState({});
mui.openWindow({
url: 'login.html',
......@@ -408,6 +440,7 @@
var isActive = event.detail.isActive;
locker.style.display = isActive ? 'block' : 'none';
if (!isActive) {
// alert(0);
settings.gestures = '';
app.setSettings(settings);
}
......
......@@ -42,6 +42,24 @@
(function($, doc) {
$.init();
$.plusReady(function() {
var mainPage = $.preload({
"id": 'main',
"url": 'main.html'
});
var toMain = function() {
$.fire(mainPage, 'show', null);
setTimeout(function() {
$.openWindow({
id: 'main',
show: {
aniShow: 'pop-in'
},
waiting: {
autoShow: false
}
});
}, 0);
};
var settings = app.getSettings();
var forgetButton = doc.getElementById("forget");
var locker = doc.querySelector('.mui-locker');
......@@ -70,16 +88,7 @@
locker.addEventListener('done', function(event) {
var rs = event.detail;
if (settings.gestures == rs.points.join('')) {
$.openWindow({
url: 'main.html',
id: 'main',
show: {
aniShow: 'pop-in'
},
waiting: {
autoShow: false
}
});
toMain()
rs.sender.clear();
} else {
tryNumber--;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment