608 lines
22 KiB
JavaScript
608 lines
22 KiB
JavaScript
/**
|
||
* ============================================================================
|
||
* UIManager.js - UI 管理器(gameabc 框架层)
|
||
* ============================================================================
|
||
*
|
||
* 职责:
|
||
* - UI 组件的注册、注销、查询和生命周期管理
|
||
* - 场景定义与切换(BaseComponent 组合的具名快照)
|
||
* - 全局公共 UI:Loading / Message / Confirm 对话框
|
||
*
|
||
* 设计原则:
|
||
* 1. 精灵由 gameabc 编辑器预先创建,UIManager 只控制显示/隐藏状态
|
||
* 2. 本文件不含任何游戏专属逻辑,可用于任何基于 gameabc 的子游戏
|
||
* 3. 游戏层通过挂载方法(UIManager.xxx = function(){})扩展专属功能
|
||
*
|
||
* 全局 UI 配置(由子游戏注入,框架不读取任何子游戏全局名):
|
||
* 子游戏在初始化时通过 init(config) 或 configureGlobalUI(config) 传入精灵常量:
|
||
* config.loadingUI = { LAYER, GROUP_ID, SPRITES: { BACKGROUND, LOADING_ICON, LOADING_TEXT } }
|
||
* config.messageUI = { LAYER, GROUP_ID, SPRITES: { BACKGROUND, TEXT } }
|
||
* config.confirmUI = { LAYER, GROUP_ID, SPRITES: { BACKGROUND, TITLE_TEXT, MESSAGE_TEXT, BTN_CONFIRM, BTN_CANCEL } }
|
||
* 不传则跳过 Loading/Message/Confirm 全局 UI(场景/组件等其余功能不受影响)。
|
||
*
|
||
* 依赖(必须在本文件之前加载):
|
||
* EventBus (gameabc-framework/system/EventBus.js)
|
||
* SpriteManager (gameabc-framework/core/SpriteManager.js)
|
||
*
|
||
* ============================================================================
|
||
* @guide 游戏侧扩展模式
|
||
* ============================================================================
|
||
*
|
||
* 游戏层通过独立 JS 文件向 UIManager 挂载专属方法:
|
||
*
|
||
* // CreateRoomUI.js(示例)
|
||
* (function() {
|
||
* 'use strict';
|
||
* var CREATE_ROOM_UI = SpriteConstants.CREATE_ROOM_UI;
|
||
*
|
||
* UIManager.showCreateRoom = function(config) {
|
||
* // 游戏专属逻辑...
|
||
* SpriteManager.showGroup(CREATE_ROOM_UI.GROUP_ID);
|
||
* };
|
||
* UIManager.hideCreateRoom = function() {
|
||
* SpriteManager.hideGroup(CREATE_ROOM_UI.GROUP_ID);
|
||
* };
|
||
* })();
|
||
*
|
||
* ============================================================================
|
||
* @guide 场景管理完整用法
|
||
* ============================================================================
|
||
*
|
||
* // 1. 初始化(在 UIBootstrap 中调用);若有全局 UI,注入其精灵常量(框架不读子游戏全局名):
|
||
* UIManager.init({ loadingUI: SpriteConstants.LOADING_UI, messageUI: SpriteConstants.MESSAGE_UI, confirmUI: SpriteConstants.CONFIRM_UI });
|
||
*
|
||
* // 2. 注册组件(BaseComponent 实例)
|
||
* UIManager.registerComponent('RoomView', roomView);
|
||
* UIManager.registerComponent('GameView', gameView);
|
||
*
|
||
* // 3. 注册场景(关联组件名列表)
|
||
* UIManager.registerScene(UIManager.SCENES.ROOM, ['RoomView']);
|
||
* UIManager.registerScene(UIManager.SCENES.GAME, ['GameView', 'JingCardView']);
|
||
*
|
||
* // 4. 切换场景(自动隐藏旧场景,显示新场景,发射 SCENE_CHANGED 事件)
|
||
* UIManager.switchToScene(UIManager.SCENES.GAME);
|
||
*
|
||
* // 5. 全局 UI
|
||
* UIManager.showLoading('正在加载...');
|
||
* UIManager.showMessage('操作成功', 2000);
|
||
* UIManager.showConfirm('确认', '是否退出?', onOK, onCancel);
|
||
*
|
||
* @version 1.0.0
|
||
*/
|
||
|
||
var UIManager = (function () {
|
||
'use strict';
|
||
|
||
// ==================== 私有变量 ====================
|
||
|
||
/**
|
||
* 全局 UI 精灵常量(由子游戏注入:init(config) / configureGlobalUI)
|
||
* 框架不读取任何子游戏全局名;未注入时三者为 null,对应全局 UI 不可用(优雅跳过)。
|
||
*/
|
||
var LOADING_UI = null;
|
||
var MESSAGE_UI = null;
|
||
var CONFIRM_UI = null;
|
||
|
||
/**
|
||
* 已注册的 UI 组件
|
||
* { componentName: BaseComponent 实例 }
|
||
*/
|
||
var _components = {};
|
||
|
||
/**
|
||
* 已注册的场景
|
||
* { sceneName: [componentName, ...] }
|
||
*/
|
||
var _scenes = {};
|
||
|
||
/**
|
||
* 当前活跃场景名
|
||
* @type {string|null}
|
||
*/
|
||
var _currentScene = null;
|
||
|
||
/**
|
||
* 初始化状态
|
||
*/
|
||
var _isInitialized = false;
|
||
|
||
// ==================== 场景枚举 ====================
|
||
|
||
var SCENES = {
|
||
ROOM: 'ROOM',
|
||
GAME: 'GAME',
|
||
LOADING: 'LOADING'
|
||
};
|
||
|
||
// ==================== 私有方法 ====================
|
||
|
||
/**
|
||
* 应用子游戏注入的全局 UI 配置(Loading/Message/Confirm),并隐藏所有全局弹层。
|
||
* 框架不认识任何子游戏全局名,配置由子游戏在 init()/configureGlobalUI() 时传入。
|
||
* @param {Object} config - { loadingUI, messageUI, confirmUI }
|
||
* @returns {boolean} 是否成功配置(缺省或不完整则跳过,返回 false)
|
||
* @private
|
||
*/
|
||
function _applyGlobalUIConfig(config) {
|
||
if (!config || !config.loadingUI || !config.messageUI || !config.confirmUI) {
|
||
console.warn('[UIManager] 未提供完整的全局 UI 配置(loadingUI/messageUI/confirmUI),跳过全局 UI 初始化');
|
||
return false;
|
||
}
|
||
|
||
LOADING_UI = config.loadingUI;
|
||
MESSAGE_UI = config.messageUI;
|
||
CONFIRM_UI = config.confirmUI;
|
||
|
||
_initLoadingUI();
|
||
_initMessageUI();
|
||
_initConfirmUI();
|
||
return true;
|
||
}
|
||
|
||
/** @private */
|
||
function _initLoadingUI() {
|
||
SpriteManager.hide(LOADING_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.hide(LOADING_UI.SPRITES.LOADING_ICON);
|
||
SpriteManager.hide(LOADING_UI.SPRITES.LOADING_TEXT);
|
||
SpriteManager.hideGroup(LOADING_UI.GROUP_ID);
|
||
console.log('[UIManager] Loading UI 初始化 (Layer ' + LOADING_UI.LAYER + ')');
|
||
}
|
||
|
||
/** @private */
|
||
function _initMessageUI() {
|
||
SpriteManager.hide(MESSAGE_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.hide(MESSAGE_UI.SPRITES.TEXT);
|
||
SpriteManager.hideGroup(MESSAGE_UI.GROUP_ID);
|
||
console.log('[UIManager] Message UI 初始化 (Layer ' + MESSAGE_UI.LAYER + ')');
|
||
}
|
||
|
||
/** @private */
|
||
function _initConfirmUI() {
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.TITLE_TEXT);
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.MESSAGE_TEXT);
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.BTN_CONFIRM);
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.BTN_CANCEL);
|
||
SpriteManager.hideGroup(CONFIRM_UI.GROUP_ID);
|
||
console.log('[UIManager] Confirm UI 初始化 (Layer ' + CONFIRM_UI.LAYER + ')');
|
||
}
|
||
|
||
/**
|
||
* 隐藏当前场景所有可见组件
|
||
* @private
|
||
*/
|
||
function _hideCurrentScene() {
|
||
if (!_currentScene || !_scenes[_currentScene]) { return; }
|
||
var names = _scenes[_currentScene];
|
||
for (var i = 0; i < names.length; i++) {
|
||
var c = _components[names[i]];
|
||
if (c && c.isVisible) { c.hide(); }
|
||
}
|
||
}
|
||
|
||
/**
|
||
* 显示指定场景的所有组件
|
||
* @private
|
||
*/
|
||
function _showScene(sceneName) {
|
||
if (!_scenes[sceneName]) {
|
||
console.error('[UIManager] 场景不存在:', sceneName);
|
||
return;
|
||
}
|
||
var names = _scenes[sceneName];
|
||
for (var i = 0; i < names.length; i++) {
|
||
var c = _components[names[i]];
|
||
if (c && !c.isVisible) { c.show(); }
|
||
}
|
||
}
|
||
|
||
// ==================== 公共 API ====================
|
||
|
||
var publicAPI = {
|
||
|
||
/**
|
||
* 场景枚举常量
|
||
*/
|
||
SCENES: SCENES,
|
||
|
||
/**
|
||
* 是否已初始化(外部只读)
|
||
*/
|
||
initialized: false,
|
||
|
||
// ============================================================
|
||
// 初始化 / 销毁
|
||
// ============================================================
|
||
|
||
/**
|
||
* 初始化 UIManager
|
||
* @param {Object} [globalUIConfig] - 可选的全局 UI 配置 { loadingUI, messageUI, confirmUI },
|
||
* 由子游戏传入(如各自的精灵常量);框架不主动读取任何子游戏全局名。
|
||
* 不传则跳过 Loading/Message/Confirm 全局 UI(可后续用 configureGlobalUI 配置)。
|
||
* @returns {boolean}
|
||
*/
|
||
init: function (globalUIConfig) {
|
||
if (_isInitialized) {
|
||
console.warn('[UIManager] 已初始化,跳过');
|
||
return true;
|
||
}
|
||
|
||
console.log('[UIManager] 初始化 (v1.0.0)');
|
||
|
||
try {
|
||
_components = {};
|
||
_scenes = {};
|
||
_currentScene = null;
|
||
|
||
// 全局 UI 为可选能力:未注入配置则跳过,不阻断 UIManager 初始化
|
||
if (globalUIConfig) { _applyGlobalUIConfig(globalUIConfig); }
|
||
|
||
_isInitialized = true;
|
||
this.initialized = true;
|
||
console.log('[UIManager] 初始化完成');
|
||
return true;
|
||
} catch (err) {
|
||
console.error('[UIManager] 初始化失败:', err);
|
||
return false;
|
||
}
|
||
},
|
||
|
||
/**
|
||
* 配置全局 UI(Loading/Message/Confirm)的精灵常量。供子游戏注入,可在 init 之后单独调用。
|
||
* @param {Object} config - { loadingUI, messageUI, confirmUI }
|
||
* @returns {boolean}
|
||
*/
|
||
configureGlobalUI: function (config) {
|
||
return _applyGlobalUIConfig(config);
|
||
},
|
||
|
||
// ============================================================
|
||
// 组件管理
|
||
// ============================================================
|
||
|
||
/**
|
||
* 注册 UI 组件
|
||
* @param {string} name - 组件名称
|
||
* @param {Object} component - BaseComponent 实例(必须已 init)
|
||
* @returns {boolean}
|
||
*/
|
||
registerComponent: function (name, component) {
|
||
if (!name || typeof name !== 'string') {
|
||
console.error('[UIManager] registerComponent: name 必须是字符串');
|
||
return false;
|
||
}
|
||
if (!component || !component.isInitialized) {
|
||
console.error('[UIManager] registerComponent: 组件未初始化:', name);
|
||
return false;
|
||
}
|
||
if (_components[name]) {
|
||
console.warn('[UIManager] registerComponent: 覆盖已存在组件:', name);
|
||
}
|
||
_components[name] = component;
|
||
console.log('[UIManager] 注册组件 "' + name + '"');
|
||
return true;
|
||
},
|
||
|
||
/**
|
||
* 获取已注册组件
|
||
* @param {string} name
|
||
* @returns {Object|null}
|
||
*/
|
||
getComponent: function (name) {
|
||
return _components[name] || null;
|
||
},
|
||
|
||
/**
|
||
* 注销组件(不销毁,只从注册表移除)
|
||
* @param {string} name
|
||
* @returns {boolean}
|
||
*/
|
||
unregisterComponent: function (name) {
|
||
if (!_components[name]) {
|
||
console.warn('[UIManager] unregisterComponent: 组件不存在:', name);
|
||
return false;
|
||
}
|
||
var c = _components[name];
|
||
if (c.isVisible) { c.hide(); }
|
||
delete _components[name];
|
||
console.log('[UIManager] 注销组件 "' + name + '"');
|
||
return true;
|
||
},
|
||
|
||
/**
|
||
* 销毁组件(调用 component.destroy() 并移除)
|
||
* @param {string} name
|
||
* @returns {boolean}
|
||
*/
|
||
destroyComponent: function (name) {
|
||
if (!_components[name]) {
|
||
console.warn('[UIManager] destroyComponent: 组件不存在:', name);
|
||
return false;
|
||
}
|
||
_components[name].destroy();
|
||
delete _components[name];
|
||
console.log('[UIManager] 销毁组件 "' + name + '"');
|
||
return true;
|
||
},
|
||
|
||
/**
|
||
* 显示指定视图(便捷方法)
|
||
* @param {string} name
|
||
*/
|
||
showView: function (name) {
|
||
var c = _components[name];
|
||
if (!c) { console.warn('[UIManager] showView: 组件不存在:', name); return; }
|
||
c.show();
|
||
},
|
||
|
||
/**
|
||
* 隐藏指定视图(便捷方法)
|
||
* @param {string} name
|
||
*/
|
||
hideView: function (name) {
|
||
var c = _components[name];
|
||
if (!c) { console.warn('[UIManager] hideView: 组件不存在:', name); return; }
|
||
c.hide();
|
||
},
|
||
|
||
// ============================================================
|
||
// 场景管理
|
||
// ============================================================
|
||
|
||
/**
|
||
* 注册场景
|
||
* @param {string} sceneName
|
||
* @param {string[]} componentNames - 该场景包含的组件名列表
|
||
* @returns {boolean}
|
||
*/
|
||
registerScene: function (sceneName, componentNames) {
|
||
if (!sceneName || typeof sceneName !== 'string') {
|
||
console.error('[UIManager] registerScene: sceneName 必须是字符串');
|
||
return false;
|
||
}
|
||
if (!Array.isArray(componentNames)) {
|
||
console.error('[UIManager] registerScene: componentNames 必须是数组');
|
||
return false;
|
||
}
|
||
for (var i = 0; i < componentNames.length; i++) {
|
||
if (!_components[componentNames[i]]) {
|
||
console.error('[UIManager] registerScene: 组件不存在:', componentNames[i]);
|
||
return false;
|
||
}
|
||
}
|
||
_scenes[sceneName] = componentNames;
|
||
console.log('[UIManager] 注册场景 "' + sceneName + '" (' + componentNames.length + ' 个组件)');
|
||
return true;
|
||
},
|
||
|
||
/**
|
||
* 切换到指定场景
|
||
* 自动隐藏当前场景,显示新场景,发射 EventBus.Events.SCENE_CHANGED
|
||
* @param {string} sceneName
|
||
* @returns {boolean}
|
||
*/
|
||
switchToScene: function (sceneName) {
|
||
if (!_scenes[sceneName]) {
|
||
console.error('[UIManager] switchToScene: 场景不存在:', sceneName);
|
||
return false;
|
||
}
|
||
if (_currentScene === sceneName) {
|
||
return true;
|
||
}
|
||
|
||
console.log('[UIManager] 切换场景 "' + (_currentScene || 'null') + '" → "' + sceneName + '"');
|
||
_hideCurrentScene();
|
||
_showScene(sceneName);
|
||
|
||
var oldScene = _currentScene;
|
||
_currentScene = sceneName;
|
||
|
||
EventBus.emit(EventBus.Events.SCENE_CHANGED, { from: oldScene, to: sceneName });
|
||
return true;
|
||
},
|
||
|
||
/**
|
||
* 获取当前场景名
|
||
* @returns {string|null}
|
||
*/
|
||
getCurrentScene: function () {
|
||
return _currentScene;
|
||
},
|
||
|
||
// ============================================================
|
||
// 全局 UI - Loading
|
||
// ============================================================
|
||
|
||
/**
|
||
* 显示加载界面
|
||
* @param {string} [message='加载中...']
|
||
*/
|
||
showLoading: function (message) {
|
||
if (!LOADING_UI) { return; }
|
||
message = message || '加载中...';
|
||
SpriteManager.setText(LOADING_UI.SPRITES.LOADING_TEXT, message);
|
||
SpriteManager.show(LOADING_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.show(LOADING_UI.SPRITES.LOADING_ICON);
|
||
SpriteManager.show(LOADING_UI.SPRITES.LOADING_TEXT);
|
||
SpriteManager.showGroup(LOADING_UI.GROUP_ID);
|
||
},
|
||
|
||
/**
|
||
* 隐藏加载界面
|
||
*/
|
||
hideLoading: function () {
|
||
if (!LOADING_UI) { return; }
|
||
SpriteManager.hide(LOADING_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.hide(LOADING_UI.SPRITES.LOADING_ICON);
|
||
SpriteManager.hide(LOADING_UI.SPRITES.LOADING_TEXT);
|
||
SpriteManager.hideGroup(LOADING_UI.GROUP_ID);
|
||
},
|
||
|
||
// ============================================================
|
||
// 全局 UI - Message
|
||
// ============================================================
|
||
|
||
/**
|
||
* 显示轻提示(Toast,无精灵,仅 console)
|
||
* @param {string} message
|
||
*/
|
||
showToast: function (message) {
|
||
console.log('[UIManager] Toast:', message);
|
||
},
|
||
|
||
/**
|
||
* 显示一个带标签的提示效果(Toast 形式,通用,不含任何玩法语义)
|
||
* @param {string} tag - 效果标签(仅用于日志区分,由调用方自定义)
|
||
* @param {string} title - 提示标题
|
||
* @param {string} [description] - 补充说明
|
||
*/
|
||
showEffectToast: function (tag, title, description) {
|
||
var msg = description ? (title + ':' + description) : title;
|
||
console.log('[UIManager] EffectToast [' + tag + ']:', msg);
|
||
this.showToast(msg);
|
||
},
|
||
|
||
/**
|
||
* 显示消息提示(自动隐藏)
|
||
* @param {string} message
|
||
* @param {number} [duration=2000] 毫秒
|
||
*/
|
||
showMessage: function (message, duration) {
|
||
if (!MESSAGE_UI || !message) { return; }
|
||
duration = duration || 2000;
|
||
SpriteManager.setText(MESSAGE_UI.SPRITES.TEXT, message);
|
||
SpriteManager.show(MESSAGE_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.show(MESSAGE_UI.SPRITES.TEXT);
|
||
SpriteManager.showGroup(MESSAGE_UI.GROUP_ID);
|
||
var self = this;
|
||
setTimeout(function () { self.hideMessage(); }, duration);
|
||
},
|
||
|
||
/**
|
||
* 隐藏消息提示
|
||
*/
|
||
hideMessage: function () {
|
||
if (!MESSAGE_UI) { return; }
|
||
SpriteManager.hide(MESSAGE_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.hide(MESSAGE_UI.SPRITES.TEXT);
|
||
SpriteManager.hideGroup(MESSAGE_UI.GROUP_ID);
|
||
},
|
||
|
||
// ============================================================
|
||
// 全局 UI - Confirm
|
||
// ============================================================
|
||
|
||
/**
|
||
* 显示确认对话框
|
||
* @param {string} title
|
||
* @param {string} message
|
||
* @param {Function} [onConfirm]
|
||
* @param {Function} [onCancel]
|
||
*/
|
||
showConfirm: function (title, message, onConfirm, onCancel) {
|
||
if (!CONFIRM_UI || !message) { return; }
|
||
title = title || '确认';
|
||
SpriteManager.setText(CONFIRM_UI.SPRITES.TITLE_TEXT, title);
|
||
SpriteManager.setText(CONFIRM_UI.SPRITES.MESSAGE_TEXT, message);
|
||
SpriteManager.show(CONFIRM_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.show(CONFIRM_UI.SPRITES.TITLE_TEXT);
|
||
SpriteManager.show(CONFIRM_UI.SPRITES.MESSAGE_TEXT);
|
||
SpriteManager.show(CONFIRM_UI.SPRITES.BTN_CONFIRM);
|
||
SpriteManager.show(CONFIRM_UI.SPRITES.BTN_CANCEL);
|
||
SpriteManager.showGroup(CONFIRM_UI.GROUP_ID);
|
||
// 回调通过全局变量传递(gameabc 引擎通过点击事件触发)
|
||
window._confirmCallback = { onConfirm: onConfirm, onCancel: onCancel };
|
||
},
|
||
|
||
/**
|
||
* 隐藏确认对话框
|
||
*/
|
||
hideConfirm: function () {
|
||
if (!CONFIRM_UI) { return; }
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.BACKGROUND);
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.TITLE_TEXT);
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.MESSAGE_TEXT);
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.BTN_CONFIRM);
|
||
SpriteManager.hide(CONFIRM_UI.SPRITES.BTN_CANCEL);
|
||
SpriteManager.hideGroup(CONFIRM_UI.GROUP_ID);
|
||
if (window._confirmCallback) { delete window._confirmCallback; }
|
||
},
|
||
|
||
// ============================================================
|
||
// 工具方法
|
||
// ============================================================
|
||
|
||
/**
|
||
* 获取所有已注册组件名称
|
||
* @returns {string[]}
|
||
*/
|
||
getRegisteredComponents: function () {
|
||
var names = [];
|
||
for (var n in _components) {
|
||
if (_components.hasOwnProperty(n)) { names.push(n); }
|
||
}
|
||
return names;
|
||
},
|
||
|
||
/**
|
||
* 获取所有已注册场景名称
|
||
* @returns {string[]}
|
||
*/
|
||
getRegisteredScenes: function () {
|
||
var names = [];
|
||
for (var n in _scenes) {
|
||
if (_scenes.hasOwnProperty(n)) { names.push(n); }
|
||
}
|
||
return names;
|
||
},
|
||
|
||
/**
|
||
* 获取当前状态快照
|
||
* @returns {Object}
|
||
*/
|
||
getState: function () {
|
||
return {
|
||
isInitialized: _isInitialized,
|
||
currentScene: _currentScene,
|
||
componentCount: Object.keys(_components).length,
|
||
sceneCount: Object.keys(_scenes).length,
|
||
components: this.getRegisteredComponents(),
|
||
scenes: this.getRegisteredScenes()
|
||
};
|
||
},
|
||
|
||
/**
|
||
* 打印状态(调试用)
|
||
*/
|
||
printState: function () {
|
||
console.log('[UIManager] 状态:', JSON.stringify(this.getState(), null, 2));
|
||
},
|
||
|
||
/**
|
||
* 销毁 UIManager(销毁所有组件并重置状态)
|
||
*/
|
||
destroy: function () {
|
||
console.log('[UIManager] 开始销毁');
|
||
for (var name in _components) {
|
||
if (_components.hasOwnProperty(name)) { this.destroyComponent(name); }
|
||
}
|
||
this.hideLoading();
|
||
this.hideMessage();
|
||
this.hideConfirm();
|
||
_components = {};
|
||
_scenes = {};
|
||
_currentScene = null;
|
||
_isInitialized = false;
|
||
this.initialized = false;
|
||
console.log('[UIManager] 销毁完成');
|
||
}
|
||
};
|
||
|
||
return publicAPI;
|
||
|
||
})();
|
||
|
||
if (typeof module !== 'undefined' && module.exports) {
|
||
module.exports = UIManager;
|
||
}
|