This commit is contained in:
Eason010212
2024-10-16 00:34:22 +08:00
parent d4d9911b5d
commit b1b32b6e4a
14 changed files with 1956 additions and 416 deletions

View File

@@ -3,15 +3,15 @@
<img src="img/shortcut.png" width="100" alt="MixIO">
</a>
</p>
<h2 align="center">MixIO</h2>
<h2 align="center">MixIO 2</h2>
<p align="center">
面向自主可控信息科技教育的开源物联网服务器
面向自主可控信息科技教育的高性能开源物联网服务器
</p>
<div align="center">
<img src="https://img.shields.io/badge/license-MPL-red">
<img src="https://img.shields.io/badge/version-1.10.0-green">
<img src="https://img.shields.io/badge/nodejs-16.17.0-blue">
<img src="https://img.shields.io/badge/version-2.0.0-green">
<img src="https://img.shields.io/badge/nodejs-22.9.0-blue">
</div>
---
@@ -20,90 +20,6 @@
https://mixio.mixly.cn
## 私有部署发行版-latest
## MixIO 2.0
### Windows-x64发行版win10及以上
https://gitee.com/bnu_mixly/mixio-win32-x86-dist/blob/master/mixio.exe
### Windows-x64发行版win7
https://gitee.com/bnu_mixly/mixio-win32-x86-dist/blob/win7/mixio.exe
### Linux-x64发行版
https://gitee.com/bnu_mixly/mixio-linux-x86-dist/blob/master/mixio
### Linux-arm64发行版
https://gitee.com/bnu_mixly/mixio-linux-arm64-dist/blob/master/mixio
### MacOS-x64发行版
https://gitee.com/bnu_mixly/mixio-linux-x86-dist/blob/darwin/mixio
## 指令说明
1. mixio start 启动服务器默认在8080端口
2. mixio stop 关闭服务器
3. mixio help 查看更多指令
4. Windows版可直接双击mixio.exe查看更多选项
5. Linux/MacOS版 可mixio install将mixio添加到systemctl中
## 不同版本间数据迁移
1. 复制服务器目录下的reserve文件夹进行替换即可完成数据迁移
2. 复制服务器目录下的config文件夹进行替换即可完成配置选项迁移新老版本间的配置文件可能存在差异建议手动配置
## 从源码运行debug模式
1. git clone https://gitee.com/mixly2/mixio.git
2. node mixio.js debug
## 从源码构建
1. 编译脚本见pkg_tools/
2. 基本环境node20(windows7为node12), python3, cmake, pkg.
## 安卓端运行服务器experimental
1. 安装termuxhttps://termux.dev/en/
2. apt update
3. apt upgrade
4. pkg install nodejs-lts
5. pkg install python
6. pkg install binutils
7. pkg install git
8. git clone https://gitee.com/mixly2/mixio.git
9. cd mixio
10. export GYP_DEFINES="android_ndk_path=''"
11. npm i
12. node mixio.js debug
13. 设置termux应用 - 允许自启动,无省电策略
## 服务器配置文件config/config.json
1. 首次运行服务器后会在相对应位置的config文件夹生成config.json
2. config.json内容可修改重启服务器后生效
3. MIXIO_HTTP_PORT - intHTTP端口默认为8080
4. MIXIO_HTTPS_PORT - intHTTP端口默认为8443
5. MIXIO_MQTT_PORT - int, MQTT端口, 默认为1883
6. MIXIO_WS_PORT - int, MQTT over WebSocket端口, 默认为8083
7. MIXIO_WSS_PORT - int, MQTT over WebSocketS端口, 默认为8084
8. MAX_PROJECT_NUM_PER_USER - int每个用户的最大项目数默认为20
9. MAX_MESSAGE_PER_USER - int每个用户的最大离线消息存储数默认为1000
10. MAX_MESSAGE_PER_SECOND - int每个用户每秒的最大消息数默认为5
11. ALLOW_REGISTER - bool是否允许自主注册默认为true
12. ALLOW_HOOK - bool是否允许离线存储消息默认为true
13. OFFLINE_MODE - bool是否禁用天气/地图数据默认为true
14. BAIDU_MAP_AK - string百度地图客户端应用AKOFFLINE_MODE=false时必须配置默认为""
15. BAIDU_MAP_SERVER_AK - string百度地图服务端应用AKOFFLINE_MODE=false时必须配置默认为""
16. ADMIN_USERNAME - string管理后台用户名默认为"admin"
17. ADMIN_PASSWORD - string管理后台密码默认为"public"
18. STORAGE_ENGINE - string数据库引擎默认为"sqlite"
19. MYSQL_HOST - stringMySQL地址STORAGE_ENGINE="mysql"时必须配置),默认为"localhost"
20. MYSQL_PORT - intMySQL地址STORAGE_ENGINE="mysql"时必须配置默认为3306
21. MYSQL_USER - stringMySQL用户名STORAGE_ENGINE="mysql"时必须配置),默认为""
22. MYSQL_PASS - stringMySQL密码STORAGE_ENGINE="mysql"时必须配置),默认为""
23. MYSQL_DB - stringMySQL数据库名STORAGE_ENGINE="mysql"时必须配置),默认为"mixio",
24. FOOTER - string显示在首页的备案信息公网部署时请务必配置此项支持HTML语言请注意为双引号添加转义字符\\),默认为""
*正在开发中...*

File diff suppressed because one or more lines are too long

View File

@@ -3,12 +3,11 @@
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<meta name="description" content="">
<meta name="author" content="">
<title>MixIO</title>
<link rel="shortcut icon" href="img/shortcut.png"/>
<link rel="stylesheet" href="css/all.css">
<!--
<script src="js/codemirror.min.js"></script>
<script src="js/jquery.min.js"></script>
<script src="js/tf.min.js"></script>
@@ -35,7 +34,6 @@
<script src="blockly/iot/IOT_Blocks.js?v=13"></script>
<script src="blockly/iot/IOT_Generate.js?v=13"></script>
<script src="blockly/msg/js/zh-hans.js?v=9"></script>
<script>var OFFLINE_MODE = <%=configs['OFFLINE_MODE']%></script>
<script>var MAX_PROJECT_NUM_PER_USER = <%=configs['MAX_PROJECT_NUM_PER_USER']%></script>
<script>var BAIDU_MAP_AK = '<%=configs['BAIDU_MAP_AK']%>'</script>
@@ -43,11 +41,15 @@
<script>var MIXIO_WSS_PORT = '<%=configs['MIXIO_WSS_PORT']%>'</script>
<script src="js/projects.js?v=273"></script>
<script src="js/MixIO.js?v=30"></script>
<style>
.custom2{
color:#4e73df
<script src="js/sb-admin-2.min.js?v=2"></script>
<script>var prjid = '<%=prjid%>'</script>
<script>
if(prjid!="no")
{
view_project(prjid,0)
}
</style>
</script>
-->
</head>
<body id="page-top" class="sidebar-toggled" style="position:relative;overflow-x:hidden">
@@ -191,15 +193,14 @@
<div id="trashbin" style="width:0;height:0;overflow:hidden">
</div>
<script src="js/sb-admin-2.min.js?v=2"></script>
<script>var prjid = '<%=prjid%>'</script>
<script src="js/sea.js"></script>
<script>
if(prjid!="no")
{
view_project(prjid,0)
}
seajs.config({
base: "lib/"
})
seajs.use("main")
</script>
<xml id="toolbox" style="display:none">
<category name="控制" colour="120" toolboxitemid="catControl" css-icon="blocklyTreeIcon">

View File

@@ -0,0 +1,93 @@
// artDialog - 默认配置
define({
/* -----已注释的配置继承自 popup.js仍可以再这里重新定义它----- */
// 对齐方式
//align: 'bottom left',
// 是否固定定位
//fixed: false,
// 对话框叠加高度值(重要:此值不能超过浏览器最大限制)
//zIndex: 1024,
// 设置遮罩背景颜色
backdropBackground: '#000',
// 设置遮罩透明度
backdropOpacity: 0.7,
// 消息内容
content: '<span class="ui-dialog-loading">Loading..</span>',
// 标题
title: '',
// 对话框状态栏区域 HTML 代码
statusbar: '',
// 自定义按钮
button: null,
// 确定按钮回调函数
ok: null,
// 取消按钮回调函数
cancel: null,
// 确定按钮文本
okValue: 'ok',
// 取消按钮文本
cancelValue: 'cancel',
cancelDisplay: true,
// 内容宽度
width: '',
// 内容高度
height: '',
// 内容与边界填充距离
padding: '',
// 对话框自定义 className
skin: '',
// 是否支持快捷关闭(点击遮罩层自动关闭)
quickClose: false,
// css 文件路径,留空则不会使用 js 自动加载样式
// 注意css 只允许加载一个
cssUri: '../css/ui-dialog.css',
// 模板(使用 table 解决 IE7 宽度自适应的 BUG
// js 使用 i="***" 属性识别结构,其余的均可自定义
innerHTML:
'<div i="dialog" class="ui-dialog">'
+ '<div class="ui-dialog-arrow-a"></div>'
+ '<div class="ui-dialog-arrow-b"></div>'
+ '<table class="ui-dialog-grid">'
+ '<tr>'
+ '<td i="header" class="ui-dialog-header">'
+ '<button i="close" class="ui-dialog-close">&#215;</button>'
+ '<div i="title" class="ui-dialog-title"></div>'
+ '</td>'
+ '</tr>'
+ '<tr>'
+ '<td i="body" class="ui-dialog-body">'
+ '<div i="content" class="ui-dialog-content"></div>'
+ '</td>'
+ '</tr>'
+ '<tr>'
+ '<td i="footer" class="ui-dialog-footer">'
+ '<div i="statusbar" class="ui-dialog-statusbar"></div>'
+ '<div i="button" class="ui-dialog-button"></div>'
+ '</td>'
+ '</tr>'
+ '</table>'
+'</div>'
});

View File

@@ -0,0 +1,488 @@
/*!
* artDialog
* Date: 2014-11-09
* https://github.com/aui/artDialog
* (c) 2009-2014 TangBin, http://www.planeArt.cn
*
* This is licensed under the GNU LGPL, version 2.1 or later.
* For details, see: http://www.gnu.org/licenses/lgpl-2.1.html
*/
define(function (require) {
var $ = require('jquery');
var Popup = require('./popup');
var defaults = require('./dialog-config');
var css = defaults.cssUri;
var _count = 0;
var _expando = new Date() - 0; // Date.now()
var _isIE6 = !('minWidth' in $('html')[0].style);
var _isMobile = 'createTouch' in document && !('onmousemove' in document)
|| /(iPhone|iPad|iPod)/i.test(navigator.userAgent);
var _isFixed = !_isIE6 && !_isMobile;
var artDialog = function (options, ok, cancel) {
var originalOptions = options = options || {};
if (typeof options === 'string' || options.nodeType === 1) {
options = {content: options, fixed: !_isMobile};
}
options = $.extend(true, {}, artDialog.defaults, options);
options.original = originalOptions;
var id = options.id = options.id || _expando + _count;
var api = artDialog.get(id);
// 如果存在同名的对话框对象,则直接返回
if (api) {
return api.focus();
}
// 目前主流移动设备对fixed支持不好禁用此特性
if (!_isFixed) {
options.fixed = false;
}
// 快捷关闭支持:点击对话框外快速关闭对话框
if (options.quickClose) {
options.modal = true;
options.backdropOpacity = 0;
}
// 按钮组
if (!$.isArray(options.button)) {
options.button = [];
}
// 取消按钮
if (cancel !== undefined) {
options.cancel = cancel;
}
if (options.cancel) {
options.button.push({
id: 'cancel',
value: options.cancelValue,
callback: options.cancel,
display: options.cancelDisplay
});
}
// 确定按钮
if (ok !== undefined) {
options.ok = ok;
}
if (options.ok) {
options.button.push({
id: 'ok',
value: options.okValue,
callback: options.ok,
autofocus: true
});
}
return artDialog.list[id] = new artDialog.create(options);
};
var popup = function () {};
popup.prototype = Popup.prototype;
var prototype = artDialog.prototype = new popup();
artDialog.create = function (options) {
var that = this;
$.extend(this, new Popup());
var originalOptions = options.original;
var $popup = $(this.node).html(options.innerHTML);
var $backdrop = $(this.backdrop);
this.options = options;
this._popup = $popup;
$.each(options, function (name, value) {
if (typeof that[name] === 'function') {
that[name](value);
} else {
that[name] = value;
}
});
// 更新 zIndex 全局配置
if (options.zIndex) {
Popup.zIndex = options.zIndex;
}
// 设置 ARIA 信息
$popup.attr({
'aria-labelledby': this._$('title')
.attr('id', 'title:' + this.id).attr('id'),
'aria-describedby': this._$('content')
.attr('id', 'content:' + this.id).attr('id')
});
// 关闭按钮
this._$('close')
.css('display', this.cancel === false ? 'none' : '')
.attr('title', this.cancelValue)
.on('click', function (event) {
that._trigger('cancel');
event.preventDefault();
});
// 添加视觉参数
this._$('dialog').addClass(this.skin);
this._$('body').css('padding', this.padding);
// 点击任意空白处关闭对话框
if (options.quickClose) {
$backdrop
.on(
'onmousedown' in document ? 'mousedown' : 'click',
function () {
that._trigger('cancel');
return false;// 阻止抢夺焦点
});
}
// 遮罩设置
this.addEventListener('show', function () {
$backdrop.css({
opacity: 0,
background: options.backdropBackground
}).animate(
{opacity: options.backdropOpacity}
, 150);
});
// ESC 快捷键关闭对话框
this._esc = function (event) {
var target = event.target;
var nodeName = target.nodeName;
var rinput = /^input|textarea$/i;
var isTop = Popup.current === that;
var keyCode = event.keyCode;
// 避免输入状态中 ESC 误操作关闭
if (!isTop || rinput.test(nodeName) && target.type !== 'button') {
return;
}
if (keyCode === 27) {
that._trigger('cancel');
}
};
$(document).on('keydown', this._esc);
this.addEventListener('remove', function () {
$(document).off('keydown', this._esc);
delete artDialog.list[this.id];
});
_count ++;
artDialog.oncreate(this);
return this;
};
artDialog.create.prototype = prototype;
$.extend(prototype, {
/**
* 显示对话框
* @name artDialog.prototype.show
* @param {HTMLElement Object, Event Object} 指定位置(可选)
*/
/**
* 显示对话框(模态)
* @name artDialog.prototype.showModal
* @param {HTMLElement Object, Event Object} 指定位置(可选)
*/
/**
* 关闭对话框
* @name artDialog.prototype.close
* @param {String, Number} 返回值,可被 onclose 事件收取(可选)
*/
/**
* 销毁对话框
* @name artDialog.prototype.remove
*/
/**
* 重置对话框位置
* @name artDialog.prototype.reset
*/
/**
* 让对话框聚焦(同时置顶)
* @name artDialog.prototype.focus
*/
/**
* 让对话框失焦(同时置顶)
* @name artDialog.prototype.blur
*/
/**
* 添加事件
* @param {String} 事件类型
* @param {Function} 监听函数
* @name artDialog.prototype.addEventListener
*/
/**
* 删除事件
* @param {String} 事件类型
* @param {Function} 监听函数
* @name artDialog.prototype.removeEventListener
*/
/**
* 对话框显示事件,在 show()、showModal() 执行
* @name artDialog.prototype.onshow
* @event
*/
/**
* 关闭事件,在 close() 执行
* @name artDialog.prototype.onclose
* @event
*/
/**
* 销毁前事件,在 remove() 前执行
* @name artDialog.prototype.onbeforeremove
* @event
*/
/**
* 销毁事件,在 remove() 执行
* @name artDialog.prototype.onremove
* @event
*/
/**
* 重置事件,在 reset() 执行
* @name artDialog.prototype.onreset
* @event
*/
/**
* 焦点事件,在 foucs() 执行
* @name artDialog.prototype.onfocus
* @event
*/
/**
* 失焦事件,在 blur() 执行
* @name artDialog.prototype.onblur
* @event
*/
/**
* 设置内容
* @param {String, HTMLElement} 内容
*/
content: function (html) {
var $content = this._$('content');
// HTMLElement
if (typeof html === 'object') {
html = $(html);
$content.empty('').append(html.show());
this.addEventListener('beforeremove', function () {
$('body').append(html.hide());
});
// String
} else {
$content.html(html);
}
return this.reset();
},
/**
* 设置标题
* @param {String} 标题内容
*/
title: function (text) {
this._$('title').text(text);
this._$('header')[text ? 'show' : 'hide']();
return this;
},
/** 设置宽度 */
width: function (value) {
this._$('content').css('width', value);
return this.reset();
},
/** 设置高度 */
height: function (value) {
this._$('content').css('height', value);
return this.reset();
},
/**
* 设置按钮组
* @param {Array, String}
* Options: value, callback, autofocus, disabled
*/
button: function (args) {
args = args || [];
var that = this;
var html = '';
var number = 0;
this.callbacks = {};
if (typeof args === 'string') {
html = args;
number ++;
} else {
$.each(args, function (i, val) {
var id = val.id = val.id || val.value;
var style = '';
that.callbacks[id] = val.callback;
if (val.display === false) {
style = ' style="display:none"';
} else {
number ++;
}
html +=
'<button'
+ ' type="button"'
+ ' i-id="' + id + '"'
+ style
+ (val.disabled ? ' disabled' : '')
+ (val.autofocus ? ' autofocus class="ui-dialog-autofocus"' : '')
+ '>'
+ val.value
+ '</button>';
that._$('button')
.on('click', '[i-id=' + id +']', function (event) {
var $this = $(this);
if (!$this.attr('disabled')) {// IE BUG
that._trigger(id);
}
event.preventDefault();
});
});
}
this._$('button').html(html);
this._$('footer')[number ? 'show' : 'hide']();
return this;
},
statusbar: function (html) {
this._$('statusbar')
.html(html)[html ? 'show' : 'hide']();
return this;
},
_$: function (i) {
return this._popup.find('[i=' + i + ']');
},
// 触发按钮回调函数
_trigger: function (id) {
var fn = this.callbacks[id];
return typeof fn !== 'function' || fn.call(this) !== false ?
this.close().remove() : this;
}
});
artDialog.oncreate = $.noop;
/** 获取最顶层的对话框API */
artDialog.getCurrent = function () {
return Popup.current;
};
/**
* 根据 ID 获取某对话框 API
* @param {String} 对话框 ID
* @return {Object} 对话框 API (实例)
*/
artDialog.get = function (id) {
return id === undefined
? artDialog.list
: artDialog.list[id];
};
artDialog.list = {};
/**
* 默认配置
*/
artDialog.defaults = defaults;
return artDialog;
});

View File

@@ -0,0 +1,639 @@
/*!
* PopupJS
* Date: 2014-11-09
* https://github.com/aui/popupjs
* (c) 2009-2014 TangBin, http://www.planeArt.cn
*
* This is licensed under the GNU LGPL, version 2.1 or later.
* For details, see: http://www.gnu.org/licenses/lgpl-2.1.html
*/
define(function (require) {
var $ = require('jquery');
var _count = 0;
var _isIE6 = !('minWidth' in $('html')[0].style);
var _isFixed = !_isIE6;
function Popup () {
this.destroyed = false;
this.__popup = $('<div />')
/*使用 <dialog /> 元素可能导致 z-index 永远置顶的问题(chrome)*/
.css({
display: 'none',
position: 'absolute',
/*
left: 0,
top: 0,
bottom: 'auto',
right: 'auto',
margin: 0,
padding: 0,
border: '0 none',
background: 'transparent'
*/
outline: 0
})
.attr('tabindex', '-1')
.html(this.innerHTML)
.appendTo('body');
this.__backdrop = this.__mask = $('<div />')
.css({
opacity: .7,
background: '#000'
});
// 使用 HTMLElement 作为外部接口使用,而不是 jquery 对象
// 统一的接口利于未来 Popup 移植到其他 DOM 库中
this.node = this.__popup[0];
this.backdrop = this.__backdrop[0];
_count ++;
}
$.extend(Popup.prototype, {
/**
* 初始化完毕事件,在 show()、showModal() 执行
* @name Popup.prototype.onshow
* @event
*/
/**
* 关闭事件,在 close() 执行
* @name Popup.prototype.onclose
* @event
*/
/**
* 销毁前事件,在 remove() 前执行
* @name Popup.prototype.onbeforeremove
* @event
*/
/**
* 销毁事件,在 remove() 执行
* @name Popup.prototype.onremove
* @event
*/
/**
* 重置事件,在 reset() 执行
* @name Popup.prototype.onreset
* @event
*/
/**
* 焦点事件,在 foucs() 执行
* @name Popup.prototype.onfocus
* @event
*/
/**
* 失焦事件,在 blur() 执行
* @name Popup.prototype.onblur
* @event
*/
/** 浮层 DOM 素节点[*] */
node: null,
/** 遮罩 DOM 节点[*] */
backdrop: null,
/** 是否开启固定定位[*] */
fixed: false,
/** 判断对话框是否删除[*] */
destroyed: true,
/** 判断对话框是否显示 */
open: false,
/** close 返回值 */
returnValue: '',
/** 是否自动聚焦 */
autofocus: true,
/** 对齐方式[*] */
align: 'bottom left',
/** 内部的 HTML 字符串 */
innerHTML: '',
/** CSS 类名 */
className: 'ui-popup',
/**
* 显示浮层
* @param {HTMLElement, Event} 指定位置(可选)
*/
show: function (anchor) {
if (this.destroyed) {
return this;
}
var that = this;
var popup = this.__popup;
var backdrop = this.__backdrop;
this.__activeElement = this.__getActive();
this.open = true;
this.follow = anchor || this.follow;
// 初始化 show 方法
if (!this.__ready) {
popup
.addClass(this.className)
.attr('role', this.modal ? 'alertdialog' : 'dialog')
.css('position', this.fixed ? 'fixed' : 'absolute');
if (!_isIE6) {
$(window).on('resize', $.proxy(this.reset, this));
}
// 模态浮层的遮罩
if (this.modal) {
var backdropCss = {
position: 'fixed',
left: 0,
top: 0,
width: '100%',
height: '100%',
overflow: 'hidden',
userSelect: 'none',
zIndex: this.zIndex || Popup.zIndex
};
popup.addClass(this.className + '-modal');
if (!_isFixed) {
$.extend(backdropCss, {
position: 'absolute',
width: $(window).width() + 'px',
height: $(document).height() + 'px'
});
}
backdrop
.css(backdropCss)
.attr({tabindex: '0'})
.on('focus', $.proxy(this.focus, this));
// 锁定 tab 的焦点操作
this.__mask = backdrop
.clone(true)
.attr('style', '')
.insertAfter(popup);
backdrop
.addClass(this.className + '-backdrop')
.insertBefore(popup);
this.__ready = true;
}
if (!popup.html()) {
popup.html(this.innerHTML);
}
}
popup
.addClass(this.className + '-show')
.show();
backdrop.show();
this.reset().focus();
this.__dispatchEvent('show');
return this;
},
/** 显示模态浮层。参数参见 show() */
showModal: function () {
this.modal = true;
return this.show.apply(this, arguments);
},
/** 关闭浮层 */
close: function (result) {
if (!this.destroyed && this.open) {
if (result !== undefined) {
this.returnValue = result;
}
this.__popup.hide().removeClass(this.className + '-show');
this.__backdrop.hide();
this.open = false;
this.blur();// 恢复焦点,照顾键盘操作的用户
this.__dispatchEvent('close');
}
return this;
},
/** 销毁浮层 */
remove: function () {
if (this.destroyed) {
return this;
}
this.__dispatchEvent('beforeremove');
if (Popup.current === this) {
Popup.current = null;
}
// 从 DOM 中移除节点
this.__popup.remove();
this.__backdrop.remove();
this.__mask.remove();
if (!_isIE6) {
$(window).off('resize', this.reset);
}
this.__dispatchEvent('remove');
for (var i in this) {
delete this[i];
}
return this;
},
/** 重置位置 */
reset: function () {
var elem = this.follow;
if (elem) {
this.__follow(elem);
} else {
this.__center();
}
this.__dispatchEvent('reset');
return this;
},
/** 让浮层获取焦点 */
focus: function () {
var node = this.node;
var popup = this.__popup;
var current = Popup.current;
var index = this.zIndex = Popup.zIndex ++;
if (current && current !== this) {
current.blur(false);
}
// 检查焦点是否在浮层里面
if (!$.contains(node, this.__getActive())) {
var autofocus = popup.find('[autofocus]')[0];
if (!this._autofocus && autofocus) {
this._autofocus = true;
} else {
autofocus = node;
}
this.__focus(autofocus);
}
// 设置叠加高度
popup.css('zIndex', index);
//this.__backdrop.css('zIndex', index);
Popup.current = this;
popup.addClass(this.className + '-focus');
this.__dispatchEvent('focus');
return this;
},
/** 让浮层失去焦点。将焦点退还给之前的元素,照顾视力障碍用户 */
blur: function () {
var activeElement = this.__activeElement;
var isBlur = arguments[0];
if (isBlur !== false) {
this.__focus(activeElement);
}
this._autofocus = false;
this.__popup.removeClass(this.className + '-focus');
this.__dispatchEvent('blur');
return this;
},
/**
* 添加事件
* @param {String} 事件类型
* @param {Function} 监听函数
*/
addEventListener: function (type, callback) {
this.__getEventListener(type).push(callback);
return this;
},
/**
* 删除事件
* @param {String} 事件类型
* @param {Function} 监听函数
*/
removeEventListener: function (type, callback) {
var listeners = this.__getEventListener(type);
for (var i = 0; i < listeners.length; i ++) {
if (callback === listeners[i]) {
listeners.splice(i--, 1);
}
}
return this;
},
// 获取事件缓存
__getEventListener: function (type) {
var listener = this.__listener;
if (!listener) {
listener = this.__listener = {};
}
if (!listener[type]) {
listener[type] = [];
}
return listener[type];
},
// 派发事件
__dispatchEvent: function (type) {
var listeners = this.__getEventListener(type);
if (this['on' + type]) {
this['on' + type]();
}
for (var i = 0; i < listeners.length; i ++) {
listeners[i].call(this);
}
},
// 对元素安全聚焦
__focus: function (elem) {
// 防止 iframe 跨域无权限报错
// 防止 IE 不可见元素报错
try {
// ie11 bug: iframe 页面点击会跳到顶部
if (this.autofocus && !/^iframe$/i.test(elem.nodeName)) {
elem.focus();
}
} catch (e) {}
},
// 获取当前焦点的元素
__getActive: function () {
try {// try: ie8~9, iframe #26
var activeElement = document.activeElement;
var contentDocument = activeElement.contentDocument;
var elem = contentDocument && contentDocument.activeElement || activeElement;
return elem;
} catch (e) {}
},
// 居中浮层
__center: function () {
var popup = this.__popup;
var $window = $(window);
var $document = $(document);
var fixed = this.fixed;
var dl = fixed ? 0 : $document.scrollLeft();
var dt = fixed ? 0 : $document.scrollTop();
var ww = $window.width();
var wh = $window.height();
var ow = popup.width();
var oh = popup.height();
var left = (ww - ow) / 2 + dl;
var top = (wh - oh) * 382 / 1000 + dt;// 黄金比例
var style = popup[0].style;
style.left = Math.max(parseInt(left), dl) + 'px';
style.top = Math.max(parseInt(top), dt) + 'px';
},
// 指定位置 @param {HTMLElement, Event} anchor
__follow: function (anchor) {
var $elem = anchor.parentNode && $(anchor);
var popup = this.__popup;
if (this.__followSkin) {
popup.removeClass(this.__followSkin);
}
// 隐藏元素不可用
if ($elem) {
var o = $elem.offset();
if (o.left * o.top < 0) {
return this.__center();
}
}
var that = this;
var fixed = this.fixed;
var $window = $(window);
var $document = $(document);
var winWidth = $window.width();
var winHeight = $window.height();
var docLeft = $document.scrollLeft();
var docTop = $document.scrollTop();
var popupWidth = popup.width();
var popupHeight = popup.height();
var width = $elem ? $elem.outerWidth() : 0;
var height = $elem ? $elem.outerHeight() : 0;
var offset = this.__offset(anchor);
var x = offset.left;
var y = offset.top;
var left = fixed ? x - docLeft : x;
var top = fixed ? y - docTop : y;
var minLeft = fixed ? 0 : docLeft;
var minTop = fixed ? 0 : docTop;
var maxLeft = minLeft + winWidth - popupWidth;
var maxTop = minTop + winHeight - popupHeight;
var css = {};
var align = this.align.split(' ');
var className = this.className + '-';
var reverse = {top: 'bottom', bottom: 'top', left: 'right', right: 'left'};
var name = {top: 'top', bottom: 'top', left: 'left', right: 'left'};
var temp = [{
top: top - popupHeight,
bottom: top + height,
left: left - popupWidth,
right: left + width
}, {
top: top,
bottom: top - popupHeight + height,
left: left,
right: left - popupWidth + width
}];
var center = {
left: left + width / 2 - popupWidth / 2,
top: top + height / 2 - popupHeight / 2
};
var range = {
left: [minLeft, maxLeft],
top: [minTop, maxTop]
};
// 超出可视区域重新适应位置
$.each(align, function (i, val) {
// 超出右或下边界:使用左或者上边对齐
if (temp[i][val] > range[name[val]][1]) {
val = align[i] = reverse[val];
}
// 超出左或右边界:使用右或者下边对齐
if (temp[i][val] < range[name[val]][0]) {
align[i] = reverse[val];
}
});
// 一个参数的情况
if (!align[1]) {
name[align[1]] = name[align[0]] === 'left' ? 'top' : 'left';
temp[1][align[1]] = center[name[align[1]]];
}
//添加follow的css, 为了给css使用
className += align.join('-') + ' '+ this.className+ '-follow';
that.__followSkin = className;
if ($elem) {
popup.addClass(className);
}
css[name[align[0]]] = parseInt(temp[0][align[0]]);
css[name[align[1]]] = parseInt(temp[1][align[1]]);
popup.css(css);
},
// 获取元素相对于页面的位置包括iframe内的元素
// 暂时不支持两层以上的 iframe 套嵌
__offset: function (anchor) {
var isNode = anchor.parentNode;
var offset = isNode ? $(anchor).offset() : {
left: anchor.pageX,
top: anchor.pageY
};
anchor = isNode ? anchor : anchor.target;
var ownerDocument = anchor.ownerDocument;
var defaultView = ownerDocument.defaultView || ownerDocument.parentWindow;
if (defaultView == window) {// IE <= 8 只能使用两个等于号
return offset;
}
// {Element: Ifarme}
var frameElement = defaultView.frameElement;
var $ownerDocument = $(ownerDocument);
var docLeft = $ownerDocument.scrollLeft();
var docTop = $ownerDocument.scrollTop();
var frameOffset = $(frameElement).offset();
var frameLeft = frameOffset.left;
var frameTop = frameOffset.top;
return {
left: offset.left + frameLeft - docLeft,
top: offset.top + frameTop - docTop
};
}
});
/** 当前叠加高度 */
Popup.zIndex = 1024;
/** 顶层浮层的实例 */
Popup.current = null;
return Popup;
});

File diff suppressed because one or more lines are too long

21
js/lib/main.js Normal file
View File

@@ -0,0 +1,21 @@
define(function(require, exports, module) {
// 通过 require 引入依赖
var $ = require('jquery');
var tools = require('tools');
$("#copypass").click(function(){
projectPass = $("#prjpass").text()
var input = document.createElement('input');
document.body.appendChild(input);
input.setAttribute('value', projectPass);
input.select();
if (document.execCommand('copy')) {
document.execCommand('copy');
}
document.body.removeChild(input);
tools.showtext("密钥信息已复制到剪贴板")
})
module.exports = {}
});

1
js/lib/qrcode.js Normal file

File diff suppressed because one or more lines are too long

263
js/lib/tools.js Normal file
View File

@@ -0,0 +1,263 @@
define(function(require, exports, module){
var dialog = require("artdialog/src/dialog")
function IsPC() {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"];
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
}
function getQueryString(name) {
var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
var r = window.location.search.substr(1).match(reg);
if (r != null) return unescape(r[2]); return null;
}
var unique = 0
function randomString(){
unique = unique+1
return (new Date()).valueOf()+""+unique
}
function Uint8ArrayToString(fileData){
var dataString = "";
for (var i = 0; i < fileData.length; i++) {
dataString += String.fromCharCode(fileData[i]);
}
return dataString;
}
function getPar(par){
var local_url = document.location.href;
var get = local_url.indexOf(par +"=");
if(get == -1){
return false;
}
var get_par = local_url.slice(par.length + get + 1);
var nextPar = get_par.indexOf("&");
if(nextPar != -1){
get_par = get_par.slice(0, nextPar);
}
return get_par;
}
stringendecoder = function(){
this.REGX_HTML_ENCODE = /"|&|'|<|>|[\x00-\x20]|[\x7F-\xFF]|[\u0100-\u2700]/g;
this.REGX_HTML_DECODE = /&\w+;|&#(\d+);/g;
this.REGX_TRIM = /(^\s*)|(\s*$)/g;
this.HTML_DECODE = {
"&lt;" : "<",
"&gt;" : ">",
"&amp;" : "&",
"&nbsp;": " ",
"&quot;": "\"",
"&copy;": ""
};
this.encodeHtml = function(s){
s = (s != undefined) ? s : this.toString();
return (typeof s != "string") ? s :
s.replace(this.REGX_HTML_ENCODE,
function($0){
var c = $0.charCodeAt(0), r = ["&#"];
c = (c == 0x20) ? 0xA0 : c;
r.push(c); r.push(";");
return r.join("");
});
};
this.decodeHtml = function(s){
var HTML_DECODE = this.HTML_DECODE;
s = (s != undefined) ? s : this.toString();
return (typeof s != "string") ? s :
s.replace(this.REGX_HTML_DECODE,
function($0, $1){
var c = HTML_DECODE[$0];
if(c == undefined){
if(!isNaN($1)){
c = String.fromCharCode(($1 == 160) ? 32:$1);
}else{
c = $0;
}
}
return c;
});
};
this.trim = function(s){
s = (s != undefined) ? s : this.toString();
return (typeof s != "string") ? s :
s.replace(this.REGX_TRIM, "");
};
this.hashCode = function(){
var hash = this.__hash__, _char;
if(hash == undefined || hash == 0){
hash = 0;
for (var i = 0, len=this.length; i < len; i++) {
_char = this.charCodeAt(i);
hash = 31*hash + _char;
hash = hash & hash; // Convert to 32bit integer
}
hash = hash & 0x7fffffff;
}
this.__hash__ = hash;
return this.__hash__;
};
};
stringendecoder.call(stringendecoder)
function str2utf8(str) {
return eval('\''+encodeURI(str).replace(/%/gm, '')+'\'').toLowerCase();
}
function showtext(text){
var d = dialog({
content: "<span class='nnt'>"+text+"</span>",
quickClose: true
});
d.showModal();
setTimeout(function(){
d.close().remove();
},1000)
}
function showmodaltext(text){
var d = dialog({
content: text
});
d.showModal();
return d
}
function timeStamp2String(){
var datetime = new Date();
var year = datetime.getFullYear();
var month = datetime.getMonth() + 1 < 10 ? "0" + (datetime.getMonth() + 1) : datetime.getMonth() + 1;
var date = datetime.getDate() < 10 ? "0" + datetime.getDate() : datetime.getDate();
var hour = datetime.getHours()< 10 ? "0" + datetime.getHours() : datetime.getHours();
var minute = datetime.getMinutes()< 10 ? "0" + datetime.getMinutes() : datetime.getMinutes();
var second = datetime.getSeconds()< 10 ? "0" + datetime.getSeconds() : datetime.getSeconds();
return year + "-" + month + "-" + date+" "+hour+":"+minute+":"+second;
}
function getByteLen(val) {
var len = 0;
for (var i = 0; i < val.length; i++) {
var a= val.charAt(i);
if (a.match(/[^\x00-\xff]/ig) != null) {
len += 2;
}else {
len += 1;
}
}
return len;
}
function HEX2DEC(hex){
return parseInt(hex,16).toString();
}
function HEX2RGB(hex){
hex = hex.substring(1);
if(hex.length === 3){
hex += hex;
}
return [HEX2DEC(hex.substring(0,2)),HEX2DEC(hex.substring(2,4)),HEX2DEC(hex.substring(4))];
}
function RGB2Hex(r,g,b) {
var hex = "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
return hex;
}
function countSubstr(str, substr, isIgnore) {
var count;
var reg = "";
substr2 = substr.replaceAll('\/','\\/')
console.log(substr2)
if (isIgnore == true) {
reg = "/" + substr2 + "/gi";
} else {
reg = "/" + substr2 + "/g";
}
reg = eval(reg);
if (str.match(reg) == null) {
count = 0;
} else {
count = str.match(reg).length;
}
return count;
}
window.onerror = function (msg, url, lineNo, columnNo, error) {
if((typeof globalProjectName)!="undefined")
stop_project()
var editForm = $('<div class="nnt" style="width:294px"/>')
editForm.append($('<div style="margin-top:-63px;margin-left:105px;margin-bottom:15px;box-shadow: 1px 1px 20px #4e73df;background-color:white;width:75px;height:75px;padding:40px;border-radius:80px;border:solid #4e73df 3px;display:flex;align-items:center;justify-content:center"><img src="icons/crash.svg" style="width:45px;"></div>'))
editForm.append($('<h3 style="text-align:center;margin-bottom:5px">出错了</h3>'))
editForm.append($('<h6 style="text-align:center;margin-bottom:10px">请复制以下信息,发送给管理员</h6>'))
console.log(msg)
var string = msg.toLowerCase();
var substring = "script error";
if (string.indexOf(substring) > -1) {
editForm.append('<p>Script Error: See Browser Console for Detail</p>');
} else {
var message = [
'<b>User: </b>' + ((typeof globalUserName)=="undefined"?"undefined":globalUserName),
'<b>Project: </b>' + ((typeof globalProjectName)=="undefined"?"undefined":globalProjectName),
'<b>Message: </b>' + msg,
'<b>URL: </b>' + url,
'<b>Line: </b>' + lineNo,
'<b>Column: </b>' + columnNo,
'<b>Error object: </b>' + JSON.stringify(error)
].join('<br>');
var p = $("<p></p>")
p.html(message)
editForm.append(p)
}
var bottomDiv = $('<div style="width:100%;margin-top:15px;display:flex;flex-direction:row;align-items:center;justify-content:space-around"/>')
var cancelEdit = $('<a class="btn btn-danger btn-circle" style="box-shadow:1px 1px 5px #e74a3b"><i class="fa fa-arrow-left"></i></a>')
cancelEdit.click(function(){
modifyDia.close()
})
bottomDiv.append(cancelEdit)
editForm.append(bottomDiv)
var modifyDia = dialog({
content:editForm[0],
cancel:false
})
modifyDia.showModal()
return false;
}
$(function(){
String.prototype.replaceAll = function(s1,s2){
return this.replace(new RegExp(s1,"gm"),s2);
}
function isIE() {
if(!!window.ActiveXObject || "ActiveXObject" in window){
return true;
}else{
return false;
   }
}
if(isIE())
{
var editForm = $('<div class="nnt" style="width:294px"/>')
editForm.append($('<div style="margin-top:-63px;margin-left:105px;margin-bottom:15px;box-shadow: 1px 1px 20px #4e73df;background-color:white;width:75px;height:75px;padding:40px;border-radius:80px;border:solid #4e73df 3px;display:flex;align-items:center;justify-content:center"><img src="icons/crash.svg" style="width:45px;"></div>'))
editForm.append($('<h3 style="text-align:center;margin-bottom:5px">出错了</h3>'))
editForm.append($('<h6 style="text-align:center;margin-bottom:10px">浏览器版本过低无法正常使用MixIO平台请您更新至最新版的Chrome、Edge、Firefox或Safari浏览器。</h6>'))
var modifyDia = dialog({
content:editForm[0],
cancel:false
})
modifyDia.showModal()
}
})
module.exports = {
showtext: showtext
}
})

View File

@@ -4,26 +4,6 @@ var globalBLE = {}
function copy(obj) {
return JSON.parse(JSON.stringify(obj))
}
$(function() {
if ('_cordovaNative' in window) {
var scriptcordova = document.createElement('script');
scriptcordova.async = false;
scriptcordova.src = "https://injection/www/cordova.js";
document.head.appendChild(scriptcordova);
}
$("#copypass").click(function(){
projectPass = $("#prjpass").text()
var input = document.createElement('input');
document.body.appendChild(input);
input.setAttribute('value', projectPass);
input.select();
if (document.execCommand('copy')) {
document.execCommand('copy');
}
document.body.removeChild(input);
showtext("密钥信息已复制到剪贴板")
})
})
$(function() {
get_width();
activeExit = false;
@@ -36,17 +16,6 @@ $(function() {
save_layout();
}
};
/*
if (Math.random() > 0.6) {
var d = dialog({
title: '限时推广',
content: '<div style="width:250px">尊敬的MixIO用户您好<br>现邀请您参与《MixIO平台技术接受度调查》共计10题预计用时5-8分钟。您的作答数据将被用于科学研究和平台改进设计感谢您的参与 <a href="https://wj.qq.com/s2/11118283/89a9/">点击此处进入调查</a></div>',
cancelValue: '我知道了',
cancel: function() {}
});
d.showModal();
}
*/
})
const DATA_MODE = 0;

2
js/sea.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -1,11 +1,8 @@
var VERSION = "1.10.0"
var VERSION = "2.0.0"
// change pwd to src
if (process.argv[0].indexOf("node") != -1) {
// exec from source
process.chdir(process.argv[1].replace("mixio.js",""))
} else {
// exec from binary
if(process.platform == "win32") {
process.chdir(process.argv[0].replace("mixio.exe",""))
}