2019-09-18 21:02:24 +08:00

374 lines
8.4 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import {
i18next,
Backend,
Toast,
Alert,
Confirm,
Prompt,
Photo,
Video
} from './third_party';
import Options from './Options';
import Storage from './utils/Storage';
import PackageManager from './package/PackageManager';
import EventDispatcher from './event/EventDispatcher';
import Editor from './editor/Editor.jsx';
import Ajax from './utils/Ajax';
import LanguageLoader from './utils/LanguageLoader';
/**
* 应用程序
* @author mrdoob / http://mrdoob.com/
* @author tengge / https://github.com/tengge1
*/
function Application(container, options) {
// 容器
this.container = container;
this.width = this.container.clientWidth;
this.height = this.container.clientHeight;
window.app = this;
// 配置
this.options = new Options(options);
// 存储
this.storage = new Storage();
this.debug = this.storage.get('debug') || false;
// 包管理器
this.packageManager = new PackageManager();
this.require = this.packageManager.require.bind(this.packageManager);
// 事件
this.event = new EventDispatcher(this);
this.call = this.event.call.bind(this.event);
this.on = this.event.on.bind(this.event);
// 加载语言包
if (!window._t) {
const loader = new LanguageLoader();
loader.load().then(() => {
this.ui = React.createElement(Editor);
// TODO: 由于ammo.js升级导致很多类库不兼容所以只能这么写。
Ammo().then(AmmoLib => {
window.Ammo = AmmoLib;
this.event.start();
ReactDOM.render(this.ui, this.container);
});
});
}
}
// ----------------------- UI函数 ---------------------------------
/**
* 创建元素
* @param {React.Component} type ReactComponent类型
* @param {Object} props ReactComponent属性
* @param {Object} children 子节点
*/
Application.prototype.createElement = function (type, props, children) {
return this.editor.createElement(type, props, children);
};
/**
* 添加元素
* @param {Object} element ReactElement元素
* @param {Function} callback 回调函数
*/
Application.prototype.addElement = function (element, callback) {
return this.editor.addElement(element, callback);
};
/**
* 移除元素
* @param {Object} element ReactElement元素
* @param {Function} callback 回调函数
*/
Application.prototype.removeElement = function (element, callback) {
return this.editor.removeElement(element, callback);
};
/**
* 弹窗一段时间消失的消息窗口
* @param {String} content 内容
*/
Application.prototype.toast = function (content) {
let component = this.createElement(Toast, undefined, content);
this.addElement(component);
setTimeout(() => {
this.removeElement(component);
}, 3000);
};
/**
* 提示窗口
* @param {Object} options 选项
* @param {String} options.title 标题
* @param {String} options.content 内容
* @param {String} options.className 样式类
* @param {Object} options.style 样式
* @param {Function} options.onOK 点击确定回调函数
* @param {Function} options.onClose 点击关闭回调函数
*/
Application.prototype.alert = function (options = {}) {
let {
title,
content,
className,
style,
onOK,
onClose
} = options;
let component;
let close = () => {
component && this.removeElement(component);
};
if (onOK === undefined && onClose === undefined) {
onOK = onClose = close;
} else if (onClose === undefined) {
onClose = onOK;
}
component = this.createElement(Alert, {
title,
okText: _t('OK'),
className,
style,
onOK,
onClose,
}, content);
this.addElement(component);
return {
component,
close,
};
};
/**
* 询问窗口
* @param {Object} options 选项
* @param {String} options.title 标题
* @param {String} options.content 内容
* @param {String} options.className 样式类
* @param {Object} options.style 样式
* @param {Function} options.onOK 点击确定回调函数
* @param {Function} options.onCancel 点击取消回调函数
*/
Application.prototype.confirm = function (options = {}) {
let {
title,
content,
className,
style,
onOK,
onCancel
} = options;
let component;
let close = () => {
component && this.removeElement(component);
};
let handleOK = () => {
if (onOK && onOK() !== false) {
close();
}
};
if (onCancel === undefined) {
onCancel = close;
}
component = this.createElement(Confirm, {
title,
okText: _t('OK'),
cancelText: _t('Cancel'),
className,
style,
onOK: handleOK,
onCancel,
onClose: onCancel,
}, content);
this.addElement(component);
return {
component,
close,
};
};
/**
* 输入窗口
* @param {Object} options 选项
* @param {String} options.title 标题
* @param {String} options.content 内容
* @param {String} options.className 样式类
* @param {Object} options.style 样式
* @param {String} options.value 默认值
* @param {Function} options.onOK 点击确定执行函数
* @param {Function} options.onClose 点击关闭执行函数
*/
Application.prototype.prompt = function (options = {}) {
let {
title,
content,
className,
style,
value,
onOK,
onClose
} = options;
let component;
let close = () => {
component && this.removeElement(component);
};
let handleOK = value => {
if (onOK && onOK(value) !== false) {
close();
}
};
if (onClose === undefined) {
onClose = close;
}
component = this.createElement(Prompt, {
title,
content,
className,
style,
value,
okText: _t('OK'),
onOK: handleOK,
onClose,
});
this.addElement(component);
return {
component,
close,
};
};
/**
* 显示加载器
* @param {*} text 加载器文本
*/
Application.prototype.mask = function (text) {
this.call('showMask', this, true, text);
};
/**
* 隐藏加载器
*/
Application.prototype.unmask = function () {
this.call('showMask', this, false);
};
/**
* 查看图片
* @param {String} url 地址
*/
Application.prototype.photo = function (url) {
let component = null;
let close = () => {
if (component) {
this.removeElement(component);
component = null;
}
};
component = this.createElement(Photo, {
url,
onClick: close
});
this.addElement(component);
};
/**
* 查看视频
* @param {String} url 地址
*/
Application.prototype.video = function (url) {
let component = null;
let close = () => {
if (component) {
this.removeElement(component);
component = null;
}
};
component = this.createElement(Video, {
url,
onClick: close
});
this.addElement(component);
};
// -------------------- 工具函数 -----------------------
/**
* 上传文件
* @param {Object} url 上传Url
* @param {String} callback 回调函数
*/
Application.prototype.upload = function () {
var input;
return function (url, callback) {
if (!input) {
input = document.createElement('input');
input.type = 'file';
input.style.display = 'none';
input.addEventListener('change', event => {
Ajax.post(url, {
file: event.target.files[0],
}, json => {
var obj = JSON.parse(json);
if (obj.Code === 200) {
callback(obj);
} else {
app.toast(obj.Msg);
}
});
});
document.body.appendChild(input);
}
input.click();
};
}();
// ----------------------- 记录日志 --------------------------------
Application.prototype.log = function (content) { // 普通日志
this.call('log', this, content);
};
Application.prototype.warn = function (content) { // 警告日志
this.call('log', this, content, 'warn');
};
Application.prototype.error = function (content) { // 错误日志
this.call('log', this, content, 'error');
};
export default Application;