Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

bat-ria

Package Overview
Dependencies
Maintainers
2
Versions
2
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

bat-ria - npm Package Compare versions

Comparing version 0.1.4 to 0.2.2

.edpproj/.npmignore

64

package.json
{
"name": "bat-ria",
"version": "0.1.4",
"description": "RIA extension for Brand Ads Team",
"main": "main.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/ecomfe/bat-ria.git"
},
"keywords": [
"RIA",
"esui",
"er"
],
"dependencies": {
"er": "3.1.x",
"esui": ">=3.1.0-alpha.5",
"ef": "3.1.x",
"underscore": "1.4.x",
"moment": "2.x",
"etpl": ">=2.0.8",
"urijs": ">=1.12.0"
},
"author": "Justineo, chestnutchen",
"license": "BSD-2-Clause",
"bugs": {
"url": "https://github.com/ecomfe/bat-ria/issues"
},
"homepage": "https://github.com/ecomfe/bat-ria"
"name": "bat-ria",
"version": "0.2.2",
"description": "RIA extension for Brand Ads Team",
"main": "main.js",
"repository": {
"type": "git",
"url": "https://github.com/ecomfe/bat-ria.git"
},
"keywords": [
"RIA",
"esui",
"er"
],
"edp": {
"dependencies": {
"er": ">=3.1.0-beta.3",
"esui": ">=3.1.0-beta.3",
"ef": "3.1.x",
"er-track": "~0.9.1",
"underscore": ">=1.6.0",
"moment": "2.x",
"etpl": ">=2.0.8",
"urijs": ">=1.12.0",
"eoo": "~0.0.9",
"mini-event": "~1.0.2"
}
},
"author": "Justineo, chestnutchen, leeight",
"license": "BSD-2-Clause",
"bugs": {
"url": "https://github.com/ecomfe/bat-ria/issues"
},
"homepage": "https://github.com/ecomfe/bat-ria"
}

@@ -11,5 +11,5 @@ # BAT-RIA 扩展

在 `common/main` 中如此通过 MA-RIA 来启动系统:
在 `common/main`(或其他入口模块)中如此通过 BAT-RIA 来启动系统:
```javascript
require('bat-ria/main').start().then(function () {
require('bat-ria/main').start(config).then(function () {
// custom system initialization

@@ -16,0 +16,0 @@ });

@@ -8,3 +8,3 @@ /**

var u = require('underscore');
var URI = require('urijs');
var uri = require('urijs');
var loading = require('../ui/loading');

@@ -14,33 +14,77 @@

var user = require('../system/user');
var aderId = user.ader && user.ader.id
|| URI.parseQuery(document.location.search).aderId
|| user.visitor && user.visitor.id;
return aderId ? { aderId: aderId } : {};
var aderId = user.getAderId();
return u.purify({
aderId: aderId
});
}
function activate() {
/**
* 可用的钩子名称如下:
* - SHOW_LOADING
* - ADD_ADER_ID
* - ADD_ER_REQUEST_HEADER
*
* 默认全部启用
*/
var hooks = {
SHOW_LOADING: true,
ADD_ADER_ID: true,
ADD_ER_REQUEST_HEADER: true
};
/**
* 激活扩展
*
* @param {Object} options 需要启用的钩子扩展,默认为都启用,键名为钩子名称,键值为falsy值时禁用
*/
function activate(options) {
// 设定默认值
u.extend(hooks, options);
var io = require('../io/serverIO');
io.hooks.filterIndexUrl = function(url) {
return URI(url).addQuery(getAderArgMap()).toString();
};
if (hooks.ADD_ADER_ID) {
io.hooks.filterIndexUrl = function(url) {
return uri(url).addQuery(getAderArgMap()).toString();
};
var Uploader = require('../ui/Uploader');
Uploader.prototype.filterAction = function (action) {
var argMap = getAderArgMap();
if (argMap) {
action = uri(action).addQuery(argMap).toString();
}
return action;
};
}
io.hooks.beforeRequest = function(options) {
var url = options.url;
var argMap = getAderArgMap();
if (argMap) {
options.url = URI(url).addQuery(argMap).toString();
if (hooks.ADD_ADER_ID) {
var url = options.url;
var argMap = getAderArgMap();
if (argMap) {
options.url = uri(url).addQuery(argMap).toString();
}
}
loading.show();
};
if (options.showLoading !== false && hooks.SHOW_LOADING) {
loading.show();
}
io.hooks.afterComplete = function() {
loading.hide();
return options;
};
var ajax = require('er/ajax');
ajax.hooks.beforeSend = function(xhr) {
xhr.setRequestHeader('X-Request-By', 'ERApplication');
};
if (hooks.SHOW_LOADING) {
io.hooks.afterComplete = function() {
loading.hide();
};
}
if (hooks.ADD_ER_REQUEST_HEADER) {
var ajax = require('er/ajax');
ajax.hooks.beforeSend = function(xhr) {
xhr.setRequestHeader('X-Request-By', 'ERApplication');
};
}
}

@@ -47,0 +91,0 @@

@@ -13,2 +13,3 @@ /**

var lib = require('esui/lib');
var Control = require('esui/Control');

@@ -22,4 +23,6 @@ /**

// 加载所有验证规则
var MaxLengthRule = require('esui/validator/MaxLengthRule');
var MinLengthRule = require('esui/validator/MinLengthRule');
require('esui/validator/MaxByteLengthRule');
require('esui/validator/MinByteLengthRule');
require('esui/validator/MaxLengthRule');
require('esui/validator/MinLengthRule');
var RequiredRule = require('esui/validator/RequiredRule');

@@ -72,7 +75,7 @@ var PatternRule = require('esui/validator/PatternRule');

var Rule = require('esui/validator/Rule');
var defaultGetErrorMessage = Rule.prototype.getErrorMessage;
MaxLengthRule.prototype.getErrorMessage = function (control) {
if (control.get('maxErrorMessage')) {
var getErrorMessage = Rule.prototype.getErrorMessage;
getErrorMessage.apply(this, arguments);
function getErrorMessage(control) {
if (control.get(this.type + 'ErrorMessage')) {
return defaultGetErrorMessage.apply(this, arguments);
}

@@ -83,48 +86,12 @@ var rangeErrorMessage = getRangeErrorMessage(control);

}
return Rule.prototype.getErrorMessage.apply(this, arguments);
};
MinLengthRule.prototype.getErrorMessage = function (control) {
if (control.get('maxErrorMessage')) {
var getErrorMessage = Rule.prototype.getErrorMessage;
getErrorMessage.apply(this, arguments);
}
var rangeErrorMessage = getRangeErrorMessage(control);
if (rangeErrorMessage) {
return rangeErrorMessage;
}
return Rule.prototype.getErrorMessage.apply(this, arguments);
};
MaxRule.prototype.getErrorMessage = function (control) {
if (control.get('maxErrorMessage')) {
var getErrorMessage = Rule.prototype.getErrorMessage;
getErrorMessage.apply(this, arguments);
}
var rangeErrorMessage = getRangeErrorMessage(control);
if (rangeErrorMessage) {
return rangeErrorMessage;
}
return Rule.prototype.getErrorMessage.apply(this, arguments);
};
return defaultGetErrorMessage.apply(this, arguments);
}
MinRule.prototype.getErrorMessage = function (control) {
if (control.get('maxErrorMessage')) {
var getErrorMessage = Rule.prototype.getErrorMessage;
getErrorMessage.apply(this, arguments);
}
var rangeErrorMessage = getRangeErrorMessage(control);
if (rangeErrorMessage) {
return rangeErrorMessage;
}
return Rule.prototype.getErrorMessage.apply(this, arguments);
};
MaxRule.prototype.getErrorMessage = getErrorMessage;
MinRule.prototype.getErrorMessage = getErrorMessage;
PatternRule.prototype.getErrorMessage = function (control) {
var pattern = control.get('pattern') + '';
if (control.get('patternErrorMessage')
|| !NUMBER_REGEX.hasOwnProperty(pattern)
) {
var getErrorMessage = Rule.prototype.getErrorMessage;
getErrorMessage.apply(this, arguments);
if (control.get('patternErrorMessage') || !NUMBER_REGEX.hasOwnProperty(pattern)) {
return defaultGetErrorMessage.apply(this, arguments);
}

@@ -135,3 +102,3 @@ var rangeErrorMessage = getRangeErrorMessage(control);

}
return Rule.prototype.getErrorMessage.apply(this, arguments);
return defaultGetErrorMessage.apply(this, arguments);
};

@@ -179,5 +146,232 @@ }

/**
* 激活全局ESUI扩展
*
* @ignore
*/
function initializeGlobalExtensions() {
var ui = require('esui');
var globalExtensions = [
// { type: 'CustomData', options: {} }
];
u.each(globalExtensions, function (extension) {
ui.attachExtension(extension.type, extension.options);
});
}
/**
* esui升级前region的过渡扩展
* 增加获取最大地域个数的方法
* 增加多选状态下是否处于全选状态的判断
* 增加获取选中文本的方法
* 增加获取rawValue的时候即使省下边没有全选也把省份id返回的方法(adrc地区格式需求)
* 增加设置rawValue时去掉非子节点的省份,并返回选中文本的方法(adrc地区格式需求)
*
* @ignore
*/
function addRegionExtension() {
var Region = require('esui/Region');
Region.prototype.getMaxRegionSize = function () {
if (!this.maxRegionSize) {
this.maxRegionSize = u.size(this.regionDataIndex);
}
return this.maxRegionSize;
};
Region.prototype.isAllSelected = function () {
if (this.mode === 'multi') {
return this.getMaxRegionSize() === this.getRawValue().length;
}
// 不是多选就直接返回false吧
return false;
};
/*
* 获取地区的文本
*
* @param isFilterParentNode {boolean} 是不是要把有子节点省份的文本过滤掉
* @param region {array} 指定地区的id范围,默认使用已选地区
* @return {string} 选中的地区的文本
*/
Region.prototype.getRegionText = function (isFilterParentNode, region) {
var me = this;
var rawValue = region || this.getRawValue();
var regionTextArr = [];
if (isFilterParentNode) {
u.each(rawValue, function (id) {
var item = me.regionDataIndex[id];
if (!item.children) {
var tmpText = item.text;
if (tmpText) {
regionTextArr.push(tmpText);
}
}
});
}
else {
u.each(rawValue, function (id) {
var tmpText = me.regionDataIndex[id] && me.regionDataIndex[id].text;
if (tmpText) {
regionTextArr.push(tmpText);
}
});
}
return regionTextArr.join(',');
};
/*
* 主要用于adrc地域获取要发送到后端的值
*
* @return {array} 不论省是不是全选都得带上的一个地区id数组
*/
Region.prototype.getRawValueWithProv = function () {
var me = this;
var rawValue = this.getRawValue();
var returnRawValue = [];
u.each(rawValue, function (id) {
var node = me.regionDataIndex[id];
// 检查叶子节点
if (node && !node.children) {
// 如果不是最深叶节点,那就是我们要的特殊的省
if (node.level !== 4) {
returnRawValue.push(id);
}
else {
// 深度为4就是最深的叶节点,是个市,把它的省也搞进来
returnRawValue.push(id);
returnRawValue.push(node.parent.id);
}
}
});
return u.uniq(returnRawValue);
};
/*
* 主要用于adrc设置控件值
*
* @param rawValue {array} 地区的id数组
* @return {string} 返回这些地区的展示文本,不包含省份以上的文本
*/
Region.prototype.setRawValueWithoutProv = function (rawValue) {
if (typeof rawValue === 'string' && rawValue.length) {
rawValue = rawValue.split(',');
}
var me = this;
var regionTextArr = [];
var rawValueToBeSet = [];
u.each(rawValue, function (id) {
var node = me.regionDataIndex[id];
if (node && !node.children) {
regionTextArr.push(node.text);
rawValueToBeSet.push(node.id);
}
});
this.setRawValue(rawValueToBeSet);
return regionTextArr.join(',');
};
}
/**
* esui升级前Crumb的过渡扩展,增加global-redirect的功能
*
* @ignore
*/
function addCrumbGlobalRedirect() {
var Crumb = require('esui/Crumb');
/**
* 链接节点的内容HTML模板
*
* 模板中可以使用以下占位符:
*
* - `{string} text`:文本内容,经过HTML转义
* - `{string} href`:链接地址,经过HTML转义
* - `{string} scope`:当Crumb在一个子action中时是否global跳转,经过HTML转义
* 值为`global`时全局跳转,其他值或空在子action中跳转
*
* @type {string}
* @override
*/
Crumb.prototype.linkNodeTemplate =
'<a class="${classes}" href="${href}" data-redirect="${scope}">${text}</a>';
/**
* 获取节点的HTML内容
*
* @param {meta.CrumbItem} node 节点数据项
* @param {number} index 节点索引序号
* @return {string}
*
* @override
*/
Crumb.prototype.getNodeHTML = function (node, index) {
var classes = this.helper.getPartClasses('node');
if (index === 0) {
classes.push.apply(
classes,
this.helper.getPartClasses('node-first')
);
}
if (index === this.path.length - 1) {
classes.push.apply(
classes,
this.helper.getPartClasses('node-last')
);
}
var template = node.href
? this.linkNodeTemplate
: this.textNodeTemplate;
var data = {
href: u.escape(node.href),
scope: u.escape(node.scope),
text: u.escape(node.text),
classes: classes.join(' ')
};
return lib.format(template, data);
};
}
function addTreeNodeTitle() {
var Tree = require('esui/Tree');
Tree.prototype.itemTemplate = '<span title="${text}">${text}</span>';
}
function fixSidebarHide() {
var Sidebar = require('esui/Sidebar');
/**
* 隐藏控件
*/
Sidebar.prototype.hide = function () {
Control.prototype.hide.call(this);
var mat = lib.g(this.helper.getId('mat'));
if (mat) {
mat.style.display = 'none';
}
// 隐藏主区域
this.main.style.display = 'none';
// minibar
var miniBar = lib.g(this.helper.getId('minibar'));
if (miniBar) {
miniBar.style.display = 'none';
}
};
}
function activate() {
initializeValidationRules();
addControlLinkMode();
initializeGlobalExtensions();
addRegionExtension();
addCrumbGlobalRedirect();
addTreeNodeTitle();
fixSidebarHide();
}

@@ -184,0 +378,0 @@

@@ -6,5 +6,10 @@ /**

define(function(require) {
define(function (require) {
var u = require('underscore');
/**
* underscore扩展模块
*
* @singleton
*/
var util = {};

@@ -30,9 +35,9 @@

function (value, key) {
var isDefaultNull =
var isDefaultNull =
value == null || value === '';
var isInDefaults =
var isInDefaults =
defaults.hasOwnProperty(key) && defaults[key] === value;
if (!isDefaultNull && !isInDefaults) {
if (deep && typeof value === 'object') {
purifiedObject[key] =
purifiedObject[key] =
purify(value, defaults[key], deep);

@@ -49,7 +54,27 @@ }

util.filterObject = function(obj, predicate, context) {
/**
* `filterObject`用来判断是否过滤的方法
* @callback underscore~filterCallback
* @param {Object} obj 需要过滤的对象
* @param {string} key 对应的键
* @return {boolean} 是否过滤,如为falsy值则过滤
*/
/**
* 根据指定条件过滤对象中的键值对
*
* @param {Object} obj 输入的对象
* @param {filterCallback} predicate 判断是否要保留某键值对,返回falsy value则过滤
* @param {*} [context] 判断函数的`this`
* @return {Object} 过滤的结果
*/
util.filterObject = function (obj, predicate, context) {
var result = {};
if (obj == null) { return results; }
u.each(obj, function(value, key) {
if (predicate.call(context, value, key, obj)) { result[key] = value; }
if (obj == null) {
return result;
}
u.each(obj, function (value, key) {
if (predicate.call(context, value, key, obj)) {
result[key] = value;
}
});

@@ -59,7 +84,24 @@ return result;

util.mapKey = function(obj, map) {
/**
* `mapObject`用来处理映射逻辑的方法
* @callback underscore~mapObjectCallback
* @param {*} original 处理前值
* @return {*} 处理后结果
*/
/**
* 根据指定的映射关系修改对象的键值
*
* @param {Object} obj 输入的对象
* @param {mapObjectCallback} iterator 每个键值的映射函数
* @param {*} [context] 判断函数的`this`
* @return {Object} context 映射函数的this
*/
util.mapObject = function (obj, iterator, context) {
var result = {};
if (obj == null) { return results; }
u.each(obj, function(value, key) {
result[map[key]] = value;
if (obj == null) {
return result;
}
u.each(obj, function (value, key) {
result[key] = iterator.call(context, value);
});

@@ -70,2 +112,27 @@ return result;

/**
* 根据指定的映射关系修改对象的键名
*
* 如果键名不在给定的映射关系中,保留原名
*
* @param {Object} obj 输入的对象
* @param {Object.<string, string>} map 键名的映射关系
* @return {Object} 转换过的新对象
*/
util.mapKey = function (obj, map) {
var result = {};
if (obj == null) {
return result;
}
u.each(obj, function (value, key) {
if (map[key]) {
result[map[key]] = value;
}
else {
result[key] = value;
}
});
return result;
};
/**
* 去除字符串首尾空格

@@ -76,3 +143,3 @@ *

*/
util.trim = function(s) {
util.trim = function (s) {
return s.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');

@@ -89,3 +156,3 @@ };

*/
util.pascalize = function(s) {
util.pascalize = function (s) {
s = s + '';

@@ -97,3 +164,3 @@ if (/^[A-Z\-_]+$/.test(s)) {

/[\s-_]+(.)/g,
function(w, c) {
function (w, c) {
return c.toUpperCase();

@@ -114,3 +181,3 @@ }

*/
util.camelize = function(s) {
util.camelize = function (s) {
s = util.pascalize(s);

@@ -133,13 +200,21 @@ return s.charAt(0).toLowerCase() + s.slice(1);

*/
util.dasherize = function(s) {
util.dasherize = function (s) {
s = util.pascalize(s);
// 这里把ABCD这种连续的大写,转成AbcD这种形式。
// 这里把xABCDx这种连续的大写,转成xAbcDx这种形式。
// 如果`encodeURIComponent`,会变成`encodeUriComponent`,
// 然后加横线后就是`encode-uri-component`得到正确的结果
var keepLast = false;
if (/[A-Z]{2,}$/.test(s)) {
// 如果连续的大写出现在最后,则不单独处理最后的字母
keepLast = true;
}
s = s.replace(
/[A-Z]{2,}/g,
function(match) {
function (match) {
return match.charAt(0)
+ match.slice(1, -1).toLowerCase()
+ match.charAt(match.length - 1);
+ (keepLast
? match.slice(1).toLowerCase()
: (match.slice(1, -1).toLowerCase()
+ match.charAt(match.length - 1))
);
}

@@ -149,8 +224,13 @@ );

s = s.replace(
/[A-Z]/g,
function(match) { return '-' + match.toLowerCase(); }
/[A-Z]/g,
function (match) {
return '-' + match.toLowerCase();
}
);
if (s.charAt(0) === '-') {
s = s.substring(1);
s = s.slice(1);
}
if (s.charAt(s.length - 1) === '-') {
s = s.slice(0, -1);
}
return s;

@@ -167,4 +247,5 @@ };

*/
util.constanize = function(s) {
s = util.pascalize(s);
util.constanize = function (s) {
s = util.dasherize(s);
s = s.replace(/-/g, '_');
return s.toUpperCase();

@@ -181,3 +262,3 @@ };

*/
util.pluralize = function(s) {
util.pluralize = function (s) {
return s.replace(/y$/, 'ie') + 's';

@@ -241,5 +322,5 @@ };

*/
util.pad = function(s, padding, length) {
util.pad = function (s, padding, length) {
s = s + '';
var padLength = s.length - length;
var padLength = length - s.length;
if (padLength > 0) {

@@ -262,5 +343,5 @@ var left = new Array(padLength + 1).join(padding);

*/
util.padRight = function() {
util.padRight = function (s, padding, length) {
s = s + '';
var padLength = s.length - length;
var padLength = length - s.length;
if (padLength > 0) {

@@ -281,3 +362,3 @@ var right = new Array(padLength + 1).join(padding);

*/
util.deepClone = function(obj) {
util.deepClone = function (obj) {
// 非对象以及函数就直接返回

@@ -295,3 +376,3 @@ if (!u.isObject(obj) || u.isFunction(obj)) {

obj,
function(value, key) {
function (value, key) {
clone[key] = util.deepClone(value);

@@ -303,2 +384,14 @@ }

/**
* 获取指定参数的类型
*
* 取自`Object.prototype.toString`的结果,比isXX方法更为准确
*
* @param {Mixed} value 需要判断的参数
* @return {string} 参数类型(Object, Array, Function, ...)
*/
util.typeOf = function (value) {
return Object.prototype.toString.call(value).slice(8, -1);
};
function activate() {

@@ -305,0 +398,0 @@ u.mixin(util);

@@ -11,14 +11,124 @@ /**

var u = require('underscore');
var loc = require('../location');
var io = {};
/**
* 常规请求流程中的hook如下:
*
* io.request(url, data, options)
* │
* ├───── io.hooks.beforeRequest(data) ───┐
* │ │
* │<────────────── data ─────────────────┘
* │
* ├───── io.hooks.afterResponse(data) ───┐
* │ │
* │<────────────── data ─────────────────┘
* │
* └─────────────────┐
* ┌──── success ────♦──── failure ────┐
* │ │
* ├─ io.hooks.afterSuccess(data) ─┐ ├─ io.hooks.afterFailure(message) ─┐
* │ │ │ │
* │<──────────── data ────────────┘ │<───────────── message ───────────┘
* │ │
* ├───────────────────────────────────┘
* ●
*/
io.hooks = {};
var DEFAULT_SERVER_ERROR = {
'success': 'false',
'message': {
'global': '服务器错误'
/**
* 后端返回的结果代码对应的类型
*
* @enum {string}
*/
var CodeType = {
0: 'SUCCESS',
1: 'GLOBAL',
2: 'FIELD',
3: 'REDIRECT',
4: 'NO_SESSION'
};
/**
* 最小的自定义错误代码
* 小于此代码的均保留为预定义类型,大于等于此代码作为自定义处理
*
* @type {number}
*/
var MINIMAL_CUSTOM_FAIL_CODE = 100;
var SERVER_ERROR = getGlobalError('服务器错误');
var PARSE_ERROR = getGlobalError('数据解析失败');
var SCHEMA_ERROR = getGlobalError('数据格式错误');
var UNKNOWN_ERROR = getGlobalError('未知错误');
/**
* 生成全局错误对象
*
* @param {string} message 错误提示信息
* @return {Object} 全局错误对象
*/
function getGlobalError(message) {
return {
success: false,
message: {
global: message
}
};
}
/**
* 适配新NMP接口返回的结果
*
* @param {Object} data 后端返回的数据对象
* @return {Object} 转换过后符合前端逻辑的对象
*/
io.prepareResponse = function (data) {
if (typeof data.code !== 'undefined') { // 有code时认为是新版接口
var status = CodeType[data.code];
if (!status) {
if (data.code < MINIMAL_CUSTOM_FAIL_CODE) { // 非预定义类型,未知错误
return UNKNOWN_ERROR;
}
else { // 自定义类型错误
var message = data.message || {};
message.code = data.code;
return {
success: false,
message: message
};
}
}
else {
if (status === 'SUCCESS') {
var result = {
success: true,
message: data.message,
result: data.result || data.page
};
return u.purify(result);
}
else {
return {
success: false,
message: data.message
};
}
}
}
else if (typeof data.success !== 'undefined') {
return data;
}
else {
return SCHEMA_ERROR;
}
};
/**
* 跳转到主页
*/
function gotoIndex() {

@@ -28,10 +138,22 @@ var url = '/index.html';

if (typeof io.hooks.filterIndexUrl === 'function') {
url = io.hooks.filterIndexUrl(url);
url = io.hooks.filterIndexUrl(url) || url;
}
document.location.href = url;
loc.assign(url);
}
function requestSuccessHandler(data) {
if (data.success !== 'true') {
/**
* 处理服务端响应成功的情况
*
* @param {Object} rawData 转换后的后端响应对象
* @return {meta.Promise} 处理后的Promise
*/
function requestSuccessHandler(rawData) {
var data = io.prepareResponse(rawData);
if (typeof io.hooks.afterResponse === 'function') {
data = io.hooks.afterResponse(data) || data;
}
if ((data.success + '') !== 'true') {
var message = data.message;

@@ -43,7 +165,7 @@ var title;

if (message.global) {
if (typeof message.global !== 'undefined') {
title = '系统提示';
content = message.global;
}
else if (message.noSession) {
else if (typeof message.noSession !== 'undefined') {
title = '系统超时';

@@ -58,39 +180,42 @@ content = message.noSession;

onok = function() {
window.location.reload(true);
loc.reload(true);
};
}
else {
window.location.href = message.redirect;
loc.assign(message.redirect);
return;
}
}
else if (!message.field) {
else if (typeof message.field !== 'undefined' || typeof message.code !== 'undefined') {
// 字段错误不需要弹窗提示,直接在表单中处理
// 自定义错误也在后面的过程中自行处理
needAlert = false;
}
else { // last resort
title = '系统提示';
content = '请求失败(未知错误)';
content = '未知错误';
}
// field error
else {
needAlert = false;
}
if (needAlert) {
Dialog.alert({
Dialog.alert(u.purify({
title: title,
content: content,
onok: onok
});
}));
}
if (typeof io.hooks.afterFailure === 'function') {
io.hooks.afterFailure(message);
message = io.hooks.afterFailure(message) || message;
}
requestCompleteHandler(message);
message = requestCompleteHandler(message) || message;
return Deferred.rejected(message);
}
// success
else {
else { // 成功状态
if (typeof io.hooks.afterSuccess === 'function') {
io.hooks.afterSuccess(data);
data = io.hooks.afterSuccess(data) || data;
}
var result = data.page || data.result;
requestCompleteHandler(result);
result = requestCompleteHandler(result) || result;
return Deferred.resolved(result);

@@ -100,10 +225,33 @@ }

function requestFailureHandler(data) {
requestCompleteHandler(data);
return requestSuccessHandler(DEFAULT_SERVER_ERROR);
/**
* 处理服务端响应失败的情况
* 转换为成功响应,返回错误提示处理
*
* @param {meta.Promise} fakeXHR 请求的Promise
* @return {meta.Promise} 处理后的Promise
*/
function requestFailureHandler(fakeXHR) {
var status = fakeXHR.status;
var error;
if (status < 200 || (status >= 300 && status !== 304)) { // 服务器没有正常返回
error = SERVER_ERROR;
}
else {
error = PARSE_ERROR;
}
return requestSuccessHandler(error);
}
/**
* 处理服务端响应完成的情况
* 不管成功失败均执行
*
* @param {Object|meta.Promise} data 成功时为返回的数据对象,失败时为请求Promise
* @return {Mixed} 处理后的输入参数
*/
function requestCompleteHandler(data) {
if (typeof io.hooks.afterComplete === 'function') {
io.hooks.afterComplete(data);
data = io.hooks.afterComplete(data) || data;
}

@@ -113,2 +261,10 @@ return data;

/**
* 向服务端发起请求
*
* @param {string} url 请求URL
* @param {Object} data 请求参数
* @param {Object} options 请求选项
* @return {meta.Promise} 请求Promise
*/
io.request = function(url, data, options) {

@@ -118,3 +274,4 @@ var defaults = {

data: data,
dataType: 'json'
dataType: 'json',
charset: 'utf-8'
};

@@ -126,4 +283,6 @@

options.data = u.extend(options.data, data);
if (typeof io.hooks.beforeRequest === 'function') {
io.hooks.beforeRequest(options);
options = io.hooks.beforeRequest(options) || options;
}

@@ -138,12 +297,30 @@

/**
* 以GET方式向服务端发起请求
*
* @param {string} url 请求URL
* @param {Object} data 请求参数
* @param {Object} options 请求选项
* @return {meta.Promise} 请求Promise
*/
io.get = function(url, data, options) {
return this.request(url, data, {
u.extend(options, {
method: 'GET'
});
return this.request(url, data, options);
};
/**
* 以POST方式向服务端发起请求
*
* @param {string} url 请求URL
* @param {Object} data 请求参数
* @param {Object} options 请求选项
* @return {meta.Promise} 请求Promise
*/
io.post = function(url, data, options) {
return this.request(url, data, {
u.extend(options, {
method: 'POST'
});
return this.request(url, data, options);
};

@@ -150,0 +327,0 @@

@@ -9,24 +9,25 @@ /**

var config;
var config = {};
var u = require('underscore');
var util = require('./util');
var Deferred = require('er/Deferred');
require('./extension/hooks').activate();
require('./extension/underscore').activate();
/**
* 初始化API请求器
*
* @ignore
*/
function initApiConfig() {
// init api requesters
var requesters = u.filterObject(config.api, function (path) {
// 跳过以`/download`结尾的路径
return !/\/download$/.test(path);
});
config.api = u.extend(
config.api,
util.genRequesters(requesters)
);
config.api = util.genRequesters(config.api);
}
/**
* 初始化ER 配置
*
* @ignore
*/
function initErConfigs() {
var erConfig = require('er/config');
erConfig.indexURL = config.index;
erConfig.systemName = config.systemName;
}

@@ -37,25 +38,60 @@

*
* @inner
* @param {Array} [extra] 额外的请求发送器
* @return {er.Promise} 处理完毕的Promise
* @ignore
*/
function loadData() {
var Deferred = require('er/Deferred');
function loadData(extra) {
extra = extra ? u.map(extra, function (api) {
if (typeof api === 'string') {
return util.genRequesters(api);
}
else {
return api;
}
}) : [];
return Deferred.all(
config.api.user(),
config.api.constants()
var requests = [config.api.user, config.api.constants].concat(extra || []);
return Deferred.all.apply(
Deferred,
u.map(requests, function (requester) {
return Deferred.when(requester());
})
);
}
/**
* 默认读取用户信息和系统常量后初始化对应模块
*
* @param {Object} session 用户信息
* @param {Object} constants 服务器端常量
* @return {er.Promise} 处理完毕的Promise
*/
function initData(session, constants) {
// init user
// 初始化用户信息
var user = require('./system/user');
user.init(session);
// init constants
// 初始化系统常量
var consts = require('./system/constants');
var localConstants = require('common/constants');
consts.init(u.extend(localConstants, constants));
// 返回其余请求结果
var extra = [].slice.call(arguments).slice(2);
return Deferred.all.apply(
Deferred,
u.map(extra, function (result) {
return Deferred.resolved(result);
})
);
}
function erStart() {
/**
* 启动ER
*
* @ignore
*/
function init() {
initErConfigs();

@@ -67,12 +103,37 @@

function start(riaConfig) {
/**
* RIA启动入口
*
* @param {Object} riaConfig RIA配置
* @param {Array} requesters 初始化数据需要的请求发送器
* @param {Function} callback 初始化请求返回后的回调函数
* @return {er.Promise} 处理完毕的Promise
* @ignore
*/
function start(riaConfig, requesters, callback) {
config = riaConfig;
require('./extension/underscore').activate();
require('./extension/hooks').activate(config.hooks);
require('./extension/ui').activate();
if (!(riaConfig.ext && riaConfig.ext.track === false)) {
// 默认开启,如果想要禁用的话,可以在调用bat-ria的时候关闭
// require('bat-ria').start({
// ext: {
// track: false
// }
// });
require('./extension/track').activate();
}
// 对API配置进行一下封装
initApiConfig();
return loadData()
// 读取必要信息后初始化系统
return loadData(requesters)
.then(initData)
.then(erStart);
.then(callback)
.then(init);
}

@@ -79,0 +140,0 @@

/**
* UB RIA Base
* Copyright 2013 Baidu Inc. All rights reserved.
*
* @ignore
* @file Action基类
* @author otakustay
* @date $DATE$
* @file 业务`Action`基类
* @author Justineo(justice360@gmail.com)
*/
define(
function (require) {
var util = require('er/util');
var u = require('underscore');
var Action = require('er/Action');
/**
* Action基类,提供实体名称和实体描述的维护
*
* @extends er.Action
* @constructor
*/
function BaseAction() {
Action.apply(this, arguments);
}
define(function (require) {
var util = require('er/util');
var u = require('underscore');
var Action = require('er/Action');
util.inherits(BaseAction, Action);
/**
* `Action`基类
*
* @extends er.Action
* @constructor
*/
function BaseAction() {
Action.apply(this, arguments);
}
/**
* 创建数据模型对象
*
* 此方法会在返回的`Model`中加上`entityDescription`属性
*
* @param {Object} args 模型的初始化数据
* @return {BaseModel}
* @protected
* @override
*/
BaseAction.prototype.createModel = function (args) {
var model = Action.prototype.createModel.apply(this, arguments);
util.inherits(BaseAction, Action);
// Action基类的默认返回值是一个空对象`{}`,
// 但是普通的`Model`对象因为方法和属性全在`prototype`上,也会被判断为空
var Model = require('er/Model');
if (!(model instanceof Model) && u.isEmpty(model)) {
var BaseModel = require('./BaseModel');
model = new BaseModel(args);
}
/**
* @override
*/
BaseAction.prototype.createModel = function (args) {
var model = Action.prototype.createModel.apply(this, arguments);
return model;
};
// `Action`基类的默认返回值是一个空对象`{}`,
// 但是普通的`Model`对象因为方法和属性全在`prototype`上,也会被判断为空
var Model = require('er/Model');
if (!(model instanceof Model) && u.isEmpty(model)) {
var BaseModel = require('./BaseModel');
model = new BaseModel(args);
}
/**
* 返回来源URL,无来源URL时可指定一个默认地址
*
* @param {string | URL} [defaultURL](optional) 无来源URL时的跳转地址
* @param {boolean} [isForce] 强制跳转至历史记录
* @protected
* @override
*/
BaseAction.prototype.back = function (defaultURL, isForce) {
if (typeof arguments[0] === 'boolean') {
isForce = defaultURL;
defaultURL = null;
}
else {
defaultURL = defaultURL || '';
}
var referrer = this.context && this.context.referrer;
var url = referrer || defaultURL;
if (url) {
this.redirect(url);
}
else if (isForce) {
window.history.back();
}
};
return BaseAction;
}
);
return model;
};
/**
* 返回来源URL,无来源URL时可指定一个默认地址
*
* @param {string|URL} [defaultURL] 无来源URL时的跳转地址
* @param {boolean} [isForce] 强制跳转至历史记录
* @protected
* @override
*/
BaseAction.prototype.back = function (defaultURL, isForce) {
if (typeof arguments[0] === 'boolean') {
isForce = defaultURL;
defaultURL = null;
}
else {
defaultURL = defaultURL || '';
}
var referrer = this.context && this.context.referrer;
var url = referrer || defaultURL;
if (url) {
this.redirect(url);
}
else if (isForce) {
require('../location').back();
}
};
return BaseAction;
});
/**
* Copyright 2014 Baidu Inc. All rights reserved.
*
* @file Model基类
* @file 业务`Model`基类
* @author Justineo(justice360@gmail.com)
* @date $DATE$
*/
define(
function (require) {
var u = require('underscore');
var util = require('er/util');
var UIModel = require('ef/UIModel');
define(function (require) {
var u = require('underscore');
var util = require('er/util');
var UIModel = require('ef/UIModel');
/**
* 业务`Model`基类
*
* @param {Object=} context 初始化时的数据
*
* @constructor
* @extends ef/UIModel
*/
function BaseModel(context) {
UIModel.call(this, context);
/**
* 业务`Model`基类
*
* @param {Object} [context] 初始化时的数据
*
* @constructor
* @extends ef.UIModel
*/
function BaseModel(context) {
UIModel.call(this, context);
}
util.inherits(BaseModel, UIModel);
/**
* 合并默认数据源
*/
BaseModel.prototype.mergeDefaultDatasource = function() {
if (!this.datasource) {
this.datasource = this.defaultDatasource;
return;
}
util.inherits(BaseModel, UIModel);
/**
* 合并默认数据源
*/
BaseModel.prototype.mergeDefaultDatasource = function() {
if (!this.datasource) {
this.datasource = this.defaultDatasource;
return;
}
// 管它有没有必要,先深复制一份,这样下面就不会为各种情况纠结,
// `datasource`大不到哪里去,深复制不影响性能
var datasource = u.deepClone(this.datasource) || {};
var defaultDatasource = u.deepClone(this.defaultDatasource);
// 管它有没有必要,先深复制一份,这样下面就不会为各种情况纠结,
// `datasource`大不到哪里去,深复制不影响性能
var datasource = u.deepClone(this.datasource) || {};
var defaultDatasource = u.deepClone(this.defaultDatasource);
// 默认数据源可能是对象或者数组,当前的数据源也可能是对象或数组,按以下规则:
//
// - 默认数组 + 当前数组:将当前数组连接到默认的最后
// - 默认数组 + 当前对象:将当前对象加到默认的最后
// - 默认对象 + 当前数组:将默认放在数组第1个
// - 默认对象 + 当前对象:做对象的合并
if (u.isArray(defaultDatasource)) {
// 默认数组 + 当前数组
if (u.isArray(datasource)) {
datasource = defaultDatasource.concat(datasource);
}
// 默认数组 + 当前对象
else {
datasource = defaultDatasource.push(datasource);
}
// 默认数据源可能是对象或者数组,当前的数据源也可能是对象或数组,按以下规则:
//
// - 默认数组 + 当前数组:将当前数组连接到默认的最后
// - 默认数组 + 当前对象:将当前对象加到默认的最后
// - 默认对象 + 当前数组:将默认放在数组第1个
// - 默认对象 + 当前对象:做对象的合并
if (u.isArray(defaultDatasource)) {
// 默认数组 + 当前数组
if (u.isArray(datasource)) {
datasource = defaultDatasource.concat(datasource);
}
// 默认数组 + 当前对象
else {
// 默认对象 + 当前数组
if (u.isArray(datasource)) {
if (!u.contains(datasource, defaultDatasource)) {
// 其它的数据项有可能会依赖这个属性,因此需要放在最前面
datasource.unshift(defaultDatasource);
}
datasource = defaultDatasource.push(datasource);
}
}
else {
// 默认对象 + 当前数组
if (u.isArray(datasource)) {
if (!u.contains(datasource, defaultDatasource)) {
// 其它的数据项有可能会依赖这个属性,因此需要放在最前面
datasource.unshift(defaultDatasource);
}
// 默认对象 + 当前对象
else {
u.defaults(datasource, defaultDatasource);
}
}
// 默认对象 + 当前对象
else {
u.defaults(datasource, defaultDatasource);
}
}
this.datasource = datasource;
};
this.datasource = datasource;
};
/**
* 加载数据
*
* @return {er/Promise}
*/
BaseModel.prototype.load = function() {
// TODO: 移到`getDatasource`方法中
this.mergeDefaultDatasource();
/**
* 加载数据
*
* @return {er/Promise}
*/
BaseModel.prototype.load = function() {
// TODO: 移到`getDatasource`方法中
this.mergeDefaultDatasource();
return UIModel.prototype.load.apply(this, arguments);
};
return UIModel.prototype.load.apply(this, arguments);
};
return BaseModel;
}
);
return BaseModel;
});
/**
* UB RIA Base
* Copyright 2013 Baidu Inc. All rights reserved.
*
* @ignore
* @file 视图基类
* @author otakustay
* @date $DATE$
* @file 业务`View`基类
* @author Justineo(justice360@gmail.com)
*/
define(
function (require) {
var util = require('er/util');
var u = require('underscore');
var UIView = require('ef/UIView');
/**
* 视图基类
*
* @extends ef.UIView
* @constructor
*/
function BaseView() {
UIView.apply(this, arguments);
}
define(function (require) {
var util = require('er/util');
var u = require('underscore');
var UIView = require('ef/UIView');
var Deferred = require('er/Deferred');
var Dialog = require('esui/Dialog');
util.inherits(BaseView, UIView);
/**
* 业务`View`基类
*
* @extends ef.UIView
* @constructor
*/
function BaseView() {
UIView.apply(this, arguments);
}
/**
* 获取对应模板名称
*
* 当一个视图被作为子Action使用时,需要在其视图模板名后加上`"Main"`以进行区分,
* 根据此设计,可以将视图切分为“完整页面”和“仅用于嵌套”两部分,根据约定命名
*
* @return {string}
* @override
*/
BaseView.prototype.getTemplateName = function () {
var templateName =
UIView.prototype.getTemplateName.apply(this, arguments);
util.inherits(BaseView, UIView);
// 作为子Action嵌入页面时,模板使用`xxxMain`这个target
if (this.model && this.model.get('isChildAction')) {
templateName += '_child';
}
/**
* 获取对应模板名称
*
* 当一个视图被作为子Action使用时,需要在其视图模板名后加上`_child`以进行区分,
* 根据此设计,可以将视图切分为“完整页面”和“仅用于嵌套”两部分,根据约定命名
*
* @return {string}
* @override
*/
BaseView.prototype.getTemplateName = function () {
var templateName =
UIView.prototype.getTemplateName.apply(this, arguments);
return templateName;
};
// 作为子Action嵌入页面时,模板使用`xxxMain`这个target
if (this.model && this.model.get('isChildAction')) {
templateName += '_child';
}
var globalToast;
return templateName;
};
/**
* 显示toast提示信息,这个方法会控制一个单例,以免信息叠在一起
*
* @parma {string} content 显示的内容
* @param {Object} [options] 配置
* @return {esui.Toast}
*/
BaseView.prototype.showToast = function (content, options) {
if (!content) {
return;
}
var globalToast;
if (!globalToast) {
// 此处直接new控件出来,
// 因为这个控件不能属于任何一个业务模块的ViewContext,
// 不然会随着跳转被销毁,造成下次用不了
var Toast = require('../ui/Toast');
var toastOptions = { disposeOnHide: false, autoShow: false };
globalToast = new Toast(toastOptions);
globalToast.on(
'hide',
u.bind(globalToast.detach, globalToast)
);
globalToast.render();
}
/**
* 显示toast提示信息,这个方法会控制一个单例,以免信息叠在一起
*
* @param {string} content 显示的内容
* @param {Object} [options] 配置
* @return {esui.Toast}
*/
BaseView.prototype.showToast = function (content, options) {
if (!content) {
return;
}
// 如果这个信息无比素正好显示着内容,又有新内容要显示,
// 那么新内容也应该有个动画效果,以吸引用户眼球,
// 所以要先`detach`一次,让`animation`生效
globalToast.detach();
var properties = {
content: content,
status: undefined
if (!globalToast) {
// 此处直接new控件出来,
// 因为这个控件不能属于任何一个业务模块的ViewContext,
// 不然会随着跳转被销毁,造成下次用不了
var Toast = require('esui/Toast');
var toastOptions = {
disposeOnHide: false,
autoShow: false
};
properties = u.extend(properties, options);
globalToast.setProperties(properties);
globalToast.show();
return globalToast;
globalToast = new Toast(toastOptions);
globalToast.render();
}
var properties = {
content: content
};
properties = u.extend(properties, options);
globalToast.setProperties(properties);
globalToast.show();
return globalToast;
};
BaseView.prototype.popDialog = function (options) {
//创建main
var main = document.createElement('div');
document.body.appendChild(main);
/**
* 显示Dialog
*
* @param {Object} options 参数
* @return {esui/Dialog}
* @protected
*/
BaseView.prototype.popDialog = function (options) {
// 创建main
var main = document.createElement('div');
document.body.appendChild(main);
var defaults = {
width: 600,
needFoot: true,
draggable: true,
closeOnHide: false,
autoClose: true,
main: main,
viewContext: this.viewContext
};
options = u.defaults({}, options, defaults);
var defaults = {
width: 600,
needFoot: true,
draggable: true,
closeOnHide: false,
autoClose: true,
main: main,
viewContext: this.viewContext
};
options = u.defaults({}, options, defaults);
var ui = require('esui');
var dialog = ui.create('Dialog', options);
var ui = require('esui');
var dialog = ui.create('Dialog', options);
dialog.render();
//使用默认foot时,改变显示文字
if (options.needFoot) {
var okBtn = dialog.getFoot().getChild('btnOk');
var cancelBtn = dialog.getFoot().getChild('btnCancel');
var okText = u.escape(options.okText || '');
var cancelText = u.escape(options.cancelText || '');
okBtn.setContent(okText || Dialog.OK_TEXT);
cancelBtn.setContent(cancelText || Dialog.CANCEL_TEXT);
}
// 使用默认foot时,改变显示文字
if (options.needFoot) {
var okBtn = dialog.getFoot().getChild('btnOk');
var cancelBtn = dialog.getFoot().getChild('btnCancel');
var okText = u.escape(options.okText || '');
var cancelText = u.escape(options.cancelText || '');
okBtn.setContent(okText || Dialog.OK_TEXT);
cancelBtn.setContent(cancelText || Dialog.CANCEL_TEXT);
}
dialog.show();
return dialog;
};
/**
* 等待一个`Dialog`触发`ok`或`cancel`事件,触发后一定会自动关闭
*
* @param {esui.Dialog} [dialog] 指定的对话框控件,未指定则通过`popDialog`创建新对话框
* @param {Object} options 参数
* @return {er.Promise} 一个`Promise`对象,
* 默认为点击确定按钮时进入`resolved`状态,
* 点击取消按钮则进入`rejected`状态
*
* 有两种重载:
* 1. waitDialog(options)
* 2. waitDialog(dialog, options)
*/
BaseView.prototype.waitDialog = function (dialog, options) {
if (!(dialog instanceof Dialog)) {
options = dialog;
dialog = this.popDialog.call(this, options);
}
else if (!dialog.isShow) {
dialog.show();
return dialog;
};
}
BaseView.prototype.waitDialog = function (dialog, options) {
if (!dialog instanceof require('esui/Dialog')) {
options = dialog;
dialog = this.popDialog.apply(this, options);
}
else if (!dialog.isShow) {
dialog.show();
}
function btnClickHandler(dialog, type, args) {
// 如果在参数里设置了处理函数,会在fire时执行
dialog.fire(type);
dialog.hide();
}
function btnClickHandler(dialog, type, args) {
// 如果在参数里设置了处理函数,会在fire时执行
dialog.fire(type, args);
dialog.hide();
}
// 使用默认foot时,改变显示文字
if (options.needFoot || dialog.getFoot()) {
var okBtn = dialog.getFoot().getChild('btnOk');
var cancelBtn = dialog.getFoot().getChild('btnCancel');
var okText = u.escape(options.okText || '');
var cancelText = u.escape(options.cancelText || '');
okBtn.setContent(okText || Dialog.OK_TEXT);
cancelBtn.setContent(cancelText || Dialog.CANCEL_TEXT);
//使用默认foot时,改变显示文字
if (options.needFoot || dialog.getFoot()) {
var okBtn = dialog.getFoot().getChild('btnOk');
var cancelBtn = dialog.getFoot().getChild('btnCancel');
var okText = u.escape(options.okText || '');
var cancelText = u.escape(options.cancelText || '');
okBtn.setContent(okText || Dialog.OK_TEXT);
cancelBtn.setContent(cancelText || Dialog.CANCEL_TEXT);
okBtn.un('click');
cancelBtn.un('click');
okBtn.on('click', u.partial(btnClickHandler, dialog, 'ok'));
cancelBtn.on('click', u.partial(btnClickHandler, dialog, 'cancel'));
}
okBtn.on('click', lib.curry(btnClickHandler, dialog, 'ok'));
cancelBtn.on('click', lib.curry(btnClickHandler, dialog, 'cancel'));
var deferred = new Deferred();
dialog.un('ok');
dialog.un('cancel');
dialog.on('ok', deferred.resolver.resolve);
dialog.on('cancel', deferred.resolver.reject);
return deferred.promise;
};
/**
* 显示一个`Dialog`,并指定触发`ok`与`cancel`事件(默认状态下为点击确定、取消按钮后触发)
* 后的处理函数,可以手动指定阻止自动关闭
*
* @param {esui.Dialog} [dialog] 指定的对话框控件,未指定则通过`popDialog`创建新对话框
* @param {Object} options 参数
* @param {function} [options.onOk] `ok`事件处理函数,`this`指向对应的`Dialog`对象
* @param {function} [options.onCancel] `cancel`事件处理函数,`this`指向对应的`Dialog`对象
* @return {esui.Dialog} 显示的`Dialog`对象
*
* `onOk`或`onCancel`的返回值如果为`false`,则不执行默认的关闭动作;
* 如果返回值是一个`Event`对象,则在调用过`preventDefault()`后不执行默认动作;
* 如果返回一个`Promise`对象,则在`resolve`时执行默认关闭动作,在`reject`时不执行
*
* 有两种重载:
* 1. showDialog(options)
* 2. showDialog(dialog, options)
*/
BaseView.prototype.showDialog = function (dialog, options) {
if (!(dialog instanceof Dialog)) {
options = dialog;
dialog = this.popDialog.call(this, options);
}
else if (!dialog.isShow) {
dialog.show();
}
function btnClickHandler(dialog, type, args) {
// 如果在参数里设置了处理函数,会在fire时执行
dialog.fire(type);
}
options = options || {};
// 使用默认foot时,改变显示文字
if (options.needFoot || dialog.getFoot()) {
var okBtn = dialog.getFoot().getChild('btnOk');
var cancelBtn = dialog.getFoot().getChild('btnCancel');
var okText = u.escape(options.okText || '');
var cancelText = u.escape(options.cancelText || '');
okBtn.setContent(okText || Dialog.OK_TEXT);
cancelBtn.setContent(cancelText || Dialog.CANCEL_TEXT);
okBtn.un('click');
cancelBtn.un('click');
okBtn.on('click', u.partial(btnClickHandler, dialog, 'ok'));
cancelBtn.on('click', u.partial(btnClickHandler, dialog, 'cancel'));
}
function checkHide(useDefault) {
// 返回值为false或被阻止默认行为的event,则不隐藏
if (useDefault === false
|| useDefault instanceof require('mini-event/Event')
&& useDefault.isDefaultPrevented()) {
return;
}
dialog && dialog.hide();
}
var Deferred = require('er/Deferred');
var deferred = new Deferred();
var blank = function () {};
dialog.on('ok', deferred.resolver.resolve);
dialog.on('cancel', deferred.resolver.reject);
var onOk = u.bind(options.onOk || blank, dialog);
var onCancel = u.bind(options.onCancel || blank, dialog);
return deferred.promise;
};
dialog.un('ok');
dialog.un('cancel');
dialog.on('ok', function () {
Deferred.when(onOk()).then(checkHide, u.partial(checkHide, false));
});
dialog.on('cancel', function () {
Deferred.when(onCancel()).then(checkHide, u.partial(checkHide, false));
});
/**
* 等待用户确认
*
* 参数同`ef.UIView.prototype.confirm`,但返回一个`Promise`对象
*
* @return {er.Promise} 一个`Promise`对象,用户确认则进入`resolved`状态,
* 用户取消则进入`rejected`状态
*/
BaseView.prototype.waitConfirm = function () {
var dialog = this.confirm.apply(this, arguments);
var Deferred = require('er/Deferred');
var deferred = new Deferred();
return dialog;
};
dialog.on('ok', deferred.resolver.resolve);
dialog.on('cancel', deferred.resolver.reject);
/**
* 等待用户确认提示
*
* 参数同`ef.UIView.prototype.alert`,但返回一个`Promise`对象
*
* @return {er.Promise} 一个`Promise`对象,用户确认则进入`resolved`状态
*/
BaseView.prototype.waitAlert = function () {
var dialog = this.alert.apply(this, arguments);
var deferred = new Deferred();
return deferred.promise;
};
dialog.on('ok', deferred.resolver.resolve);
/**
* 等待一个`DialogAction`加载完成
*
* @return {er.Promise} 一个`Promise`对象,
* 对应的Action加载完成时进入`resolved`状态,
* 如Action加载失败则进入`rejected`状态
*/
BaseView.prototype.waitActionDialog = function () {
var dialog = this.popActionDialog.apply(this, arguments);
return deferred.promise;
};
var Deferred = require('er/Deferred');
var deferred = new Deferred();
/**
* 等待用户确认
*
* 参数同`ef.UIView.prototype.confirm`,但返回一个`Promise`对象
*
* @return {er.Promise} 一个`Promise`对象,用户确认则进入`resolved`状态,
* 用户取消则进入`rejected`状态
*/
BaseView.prototype.waitConfirm = function () {
var dialog = this.confirm.apply(this, arguments);
var deferred = new Deferred();
dialog.on('actionloaded', deferred.resolver.resolve);
dialog.on('actionloadfail', deferred.resolver.reject);
dialog.on('actionloadabort', deferred.resolver.reject);
dialog.on('ok', deferred.resolver.resolve);
dialog.on('cancel', deferred.resolver.reject);
return deferred.promise;
};
return deferred.promise;
};
return BaseView;
}
);
/**
* 等待一个`DialogAction`加载完成
*
* @return {er.Promise} 一个`Promise`对象,
* 对应的Action加载完成时进入`resolved`状态,
* 如Action加载失败则进入`rejected`状态
*/
BaseView.prototype.waitActionDialog = function () {
var dialog = this.popActionDialog.apply(this, arguments);
var deferred = new Deferred();
dialog.on('actionloaded', deferred.resolver.resolve);
dialog.on('actionloadfail', deferred.resolver.reject);
dialog.on('actionloadabort', deferred.resolver.reject);
return deferred.promise;
};
/**
* 刷新权限设置,在Action加载过新内容时使用
*/
BaseView.prototype.refreshAuth = function () {
var authPanel = this.get('authPanel');
if (authPanel) {
authPanel.initAuth();
}
};
return BaseView;
});
/**
* Copyright 2014 Baidu Inc. All rights reserved.
*
* @file FormAction基类
* @file 表单类型`Action`基类
* @author chestnutchen(chenli11@baidu.com)
* @date $DATE$
*/
define(
function (require) {
var util = require('er/util');
var u = require('underscore');
var Deferred = require('er/Deferred');
var BaseAction = require('./BaseAction');
define(function (require) {
var util = require('er/util');
var u = require('underscore');
var Deferred = require('er/Deferred');
var BaseAction = require('./BaseAction');
/**
* 表单Action基类
*
* @extends BaseAction
* @constructor
*/
function FormAction() {
BaseAction.apply(this, arguments);
}
/**
* 表单类型`Action`基类
*
* @extends BaseAction
* @constructor
*/
function FormAction() {
BaseAction.apply(this, arguments);
}
util.inherits(FormAction, BaseAction);
util.inherits(FormAction, BaseAction);
FormAction.prototype.modelType = require('./FormModel');
/**
* 设置表单提交成功后显示的信息,如果值为`null`或`undefined`则表示不显示任何信息
*
* 如果该字段有内容,则系统使用该字段与提交表单后服务器返回的数据进行模板格式化,
* 因此可以使用服务器返回的字段为占位符。模板使用`underscore.template`方法
*
* @type {string | false | null}
*/
FormAction.prototype.toastMessage = '';
/**
* 当前页面的分类,始终为`"form"`
*
* @type {string}
* @readonly
* @override
*/
FormAction.prototype.category = 'form';
/**
* 获取表单提交成功后显示的信息
*
* 默认提示信息为“保存成功”
*
* @param {Object} result 提交后服务器端返回的信息
* @return {string}
*/
FormAction.prototype.getToastMessage = function (result) {
var message = this.toastMessage;
if (message == null) {
return '';
}
/**
* 设置表单提交成功后显示的信息,如果值为`null`或`undefined`则表示不显示任何信息
*
* 如果该字段有内容,则系统使用该字段与提交表单后服务器返回的数据进行模板格式化,
* 因此可以使用服务器返回的字段为占位符。模板使用`underscore.template`方法
*
* @type {string | false | null}
*/
FormAction.prototype.toastMessage = '';
if (message) {
return u.template(message, result || {});
}
else {
return '保存成功';
}
};
/**
* 获取表单提交成功后显示的信息
*
* 默认提示信息为“保存成功”
*
* @param {Object} result 提交后服务器端返回的信息
* @return {string}
*/
FormAction.prototype.getToastMessage = function (result) {
var message = this.toastMessage;
if (message == null) {
return '';
}
/**
* 处理提交数据成功后的返回
*
* @param {Object} result 提交成功后返回的内容
*/
FormAction.prototype.handleSubmitResult = function (result) {
var toast = this.getToastMessage(result);
if (toast) {
this.view.showToast(toast);
}
if (typeof this.redirectAfterSubmit === 'function') {
this.redirectAfterSubmit(result);
}
};
if (message) {
return u.template(message, result || {});
}
else {
return '保存成功';
}
};
/**
* 默认提交/取消后跳转的路径
* @type {string}
*/
FormAction.prototype.backLocation = null;
/**
* 处理提交数据成功后的返回
*
* @param {Object} result 提交成功后返回的内容
*/
FormAction.prototype.handleSubmitResult = function (result) {
var toast = this.getToastMessage(result);
if (toast) {
this.view.showToast(toast);
}
if (typeof this.redirectAfterSubmit === 'function') {
this.redirectAfterSubmit(result);
}
};
/**
* 执行提交成功后的跳转操作
* 在有referrer的情况下跳转至referrer
* 在没有referrer的情况下history.back()
*
* 可在业务action里边重写
*
* @param {Object} result 提交后服务器返回的数据
*/
FormAction.prototype.redirectAfterSubmit = function (result) {
this.back(this.backLocation, true);
};
/**
* 执行提交成功后的跳转操作
* 在有referrer的情况下跳转至referrer
* 在没有referrer的情况下history.back()
*
* 可在业务action里边重写
*
* @param {Object} result 提交后服务器返回的数据
*/
FormAction.prototype.redirectAfterSubmit = function (result) {
this.back(true);
};
/**
* 处理提交错误
*
* @param {Object} message 失败时的message对象
*/
FormAction.prototype.handleSubmitError = function (message) {
if (message && message.field) {
this.view.notifyErrors(message.field);
this.view.handleValidateInvalid();
}
this.view.showToast('保存失败');
};
/**
* 处理提交错误
*
* @param {Object} 失败时的message对象
*/
FormAction.prototype.handleSubmitError = function (message) {
if (message && message.field) {
this.view.notifyErrors(message.field);
}
this.view.showToast('保存失败');
};
/**
* 处理本地的验证错误
* 没有name的controls请自行扩展处理
*
* @param {Object|string} errors 本地验证得到的错误信息
* object视为`FieldError`,string视为`GlobalError`
* object的格式:
* {
* name1: errorMessage1,
* name2: errorMessage2
* }
*
* @return {Mixed} 本地验证得到的错误信息
*/
FormAction.prototype.handleLocalValidationErrors = function (errors) {
if (typeof errors === 'string') {
this.view.alert(errors, '系统提示');
}
else if (typeof errors === 'object') {
this.view.notifyErrors(errors);
}
return errors;
};
/**
* 处理本地的验证错误
* 没有name的controls请自行扩展处理
*
* @param {meta.FieldError[]} errors 本地验证得到的错误集合
* @return {Mixed} 处理完后的返回值,返回对象的情况下将显示错误
*/
FormAction.prototype.handleLocalValidationErrors = function (errors) {
if (typeof errors === 'object') {
this.view.notifyErrors(errors);
return errors;
}
};
/**
* 重置的操作
*/
FormAction.prototype.reset = function () {
var reset = this.fire('reset');
if (!reset.isDefaultPrevented()) {
this.view.rollbackFormData(this.model.getDefaultData());
}
};
/**
* 设置取消编辑时的提示信息标题
*
* @type {string}
*/
FormAction.prototype.cancelConfirmTitle = '确认取消编辑';
/**
* 设置取消编辑时的提示信息标题
*
* @type {string}
*/
FormAction.prototype.cancelConfirmTitle = '确认取消编辑';
/**
* 获取取消编辑时的提示信息标题
*
* @return {string}
*/
FormAction.prototype.getCancelConfirmTitle = function () {
return this.cancelConfirmTitle;
};
/**
* 获取取消编辑时的提示信息标题
*
* @return {string}
*/
FormAction.prototype.getCancelConfirmTitle = function () {
return this.cancelConfirmTitle;
};
/**
* 设置取消编辑时的提示信息内容
*
* @type {string}
*/
FormAction.prototype.cancelConfirmMessage =
'取消编辑将不保留已经填写的数据,确定继续吗?';
/**
* 设置取消编辑时的提示信息内容
*
* @type {string}
*/
FormAction.prototype.cancelConfirmMessage =
'取消编辑将不保留已经填写的数据,确定继续吗?';
/**
* 获取取消编辑时的提示信息内容
*
* @return {string}
*/
FormAction.prototype.getCancelConfirmMessage = function () {
return this.cancelConfirmMessage;
};
/**
* 获取取消编辑时的提示信息内容
*
* @return {string}
*/
FormAction.prototype.getCancelConfirmMessage = function () {
return this.cancelConfirmMessage;
};
/**
* 取消编辑的操作
* TODO: 把回滚表单数据放到reset按钮的逻辑里边
* submitcancel 回滚表单数据,使用原始数据重新填充
* aftercancel 执行取消编辑后重定向操作
*/
FormAction.prototype.cancel = function () {
var submitCancelEvent = this.fire('submitcancel');
/**
* 取消编辑的操作
*
* @fires submitcancel
* @fires aftercancel
*/
FormAction.prototype.cancel = function () {
var submitCancelEvent = this.fire('submitcancel');
var handleFinishEvent = this.fire('aftercancel');
if (!submitCancelEvent.isDefaultPrevented()) {
this.view.rollbackFormData();
}
if (!handleFinishEvent.isDefaultPrevented() && !submitCancelEvent.isDefaultPrevented()) {
this.redirectAfterCancel();
}
};
var handleFinishEvent = this.fire('aftercancel');
/**
* 取消编辑时的确认提示
*/
FormAction.prototype.cancelEdit = function () {
var formData = this.view.getFormData();
if (!handleFinishEvent.isDefaultPrevented()) {
this.redirectAfterCancel();
}
};
if (this.model.isFormDataChanged(formData)) {
var options = {
title: this.getCancelConfirmTitle(),
content: this.getCancelConfirmMessage()
};
this.view.waitConfirm(options)
.then(u.bind(this.cancel, this));
}
else {
this.cancel();
}
};
/**
* 取消编辑时的确认提示
*/
FormAction.prototype.cancelEdit = function () {
var formData = this.view.getFormData();
/**
* 在取消编辑后重定向
* 在有referrer的情况下跳转至referrer
* 在没有referrer的情况下history.back()
*
* 可在业务action里边重写
*/
FormAction.prototype.redirectAfterCancel = function () {
this.back(this.backLocation, true);
};
if (this.model.isFormDataChanged(formData)) {
var options = {
title: this.getCancelConfirmTitle(),
content: this.getCancelConfirmMessage()
};
this.view.waitConfirm(options)
.then(u.bind(this.cancel, this));
/**
* 提交表单
*
* @param {Object} submitData 表单数据
* @return {er.Promise}
*/
FormAction.prototype.submit = function (submitData) {
var handleBeforeSubmit = this.fire('beforesubmit', {submitData: submitData});
if (!handleBeforeSubmit.isDefaultPrevented()) {
try {
var submitRequester = this.model.submitRequester;
return submitRequester(submitData)
.then(
u.bind(this.handleSubmitResult, this),
u.bind(this.handleSubmitError, this)
);
}
else {
this.cancel();
catch (ex) {
return Deferred.rejected(ex);
}
};
}
};
/**
* 在取消编辑后重定向
* 在有referrer的情况下跳转至referrer
* 在没有referrer的情况下history.back()
*
* 可在业务action里边重写
*/
FormAction.prototype.redirectAfterCancel = function () {
this.back(true);
};
/**
* 校验表单前可扩展的操作,在提交之前做*异步*的校验
* 比如弹个框“提交有风险,是否要提交”之类
*
* @param {Object} submitData 最终要提交的数据
* @return {*}
* 当且仅当返回Deferred.rejected()阻止后续流程
* 其他任意返回结果均与Deferred.resolved()等效
*/
FormAction.prototype.beforeValidate = function (submitData) {
return true;
};
/**
* 提交表单
*
* @param {object} 表单数据
*/
FormAction.prototype.submit = function (submitData) {
var localValidationResult = this.model.validateSubmitData(submitData);
if (localValidationResult !== true) {
var handleResult = this.handleLocalValidationErrors(localValidationResult);
return Deferred.rejected(handleResult);
}
/**
* 校验表单后可扩展的动作,在校验之后做*异步*的处理
* 比如弹个框“提交仍有风险,是否要提交”之类
*
* @param {Object} submitData 最终要提交的数据
* @return {*}
* 当且仅当返回Deferred.rejected()阻止后续流程
* 其他任意返回结果均与Deferred.resolved()等效
*/
FormAction.prototype.afterValidate = function (submitData) {
return true;
};
var handleBeforeSubmit = this.fire('beforesubmit');
/**
* 进行校验,如果设置了Form的`autoValidate`则先进行表单控件自校验,否则只做自定义校验
*
* @param {Object} submitData 最终要提交的数据
* @return {er.Promise} 处理完毕的Promise
*/
FormAction.prototype.validate = function (submitData) {
var localViewValidationResult = this.view.validate();
var localModelValidationResult = this.model.validateSubmitData(submitData);
if (localViewValidationResult && localModelValidationResult === true) {
return Deferred.resolved(submitData);
}
if (!handleBeforeSubmit.isDefaultPrevented()) {
try {
var submitRequester = this.model.submitRequester;
return submitRequester(submitData)
.then(
u.bind(this.handleSubmitResult, this),
u.bind(this.handleSubmitError, this)
);
}
catch (ex) {
return Deferred.rejected(ex);
}
}
};
if (localModelValidationResult !== true) {
this.handleLocalValidationErrors(localModelValidationResult);
}
this.view.handleValidateInvalid();
/**
* 提交表单前锁定提交,完成提交操作后释放提交
*/
FormAction.prototype.submitEdit = function () {
this.view.disableSubmit();
var formData = this.view.getFormData();
var submitData = this.model.getSubmitData(formData);
return Deferred.rejected();
};
require('er/Deferred')
.when(this.submit(submitData))
.ensure(this.view.enableSubmit());
};
/**
* 此处为点击提交按钮后、表单校验前的准备
* 主要逻辑是锁定提交,在校验通过并完成提交操作后释放表单的提交操作
*
* 提交流程:
* disableSubmit ->
* beforeValidate ->
* validate ->
* afterValidate ->
* submit ->
* enableSubmit
*
* 可针对业务需求扩展beforeValidate、afterValidate
* validate、submit若与业务有冲突,也可自行修改,但不推荐
*/
FormAction.prototype.submitEdit = function () {
this.view.disableSubmit();
var formData = this.view.getFormData();
var submitData = this.model.getSubmitData(formData);
/**
* 初始化交互行为
*
* @protected
* @override
*/
FormAction.prototype.initBehavior = function () {
BaseAction.prototype.initBehavior.apply(this, arguments);
this.view.on('submit', this.submitEdit, this);
this.view.on('cancel', this.cancelEdit, this);
};
return FormAction;
}
);
require('er/Deferred')
.when(this.beforeValidate(submitData))
.then(u.bind(this.validate, this, submitData))
.then(u.bind(this.afterValidate, this, submitData))
.then(u.bind(this.submit, this, submitData))
.ensure(u.bind(this.view.enableSubmit, this.view));
};
/**
* 初始化交互行为
*
* @protected
* @override
*/
FormAction.prototype.initBehavior = function () {
BaseAction.prototype.initBehavior.apply(this, arguments);
this.view.on('submit', this.submitEdit, this);
this.view.on('cancel', this.cancelEdit, this);
this.view.on('reset', this.reset, this);
};
return FormAction;
});
/**
* Copyright 2014 Baidu Inc. All rights reserved.
*
* @file FormModel基类
* @file 表单类型`Model`基类
* @author chestnutchen(chenli11@baidu.com)
* @date $DATE$
*/
define(
function (require) {
var BaseModel = require('./BaseModel');
var u = require('underscore');
var util = require('er/util');
var datasource = require('er/datasource');
define(function (require) {
var BaseModel = require('./BaseModel');
var u = require('underscore');
var util = require('er/util');
var datasource = require('er/datasource');
/**
* 表单数据模型基类
*
* @extends BaseModel
* @constructor
*/
function FormModel() {
BaseModel.apply(this, arguments);
}
/**
* 表单类型`Model`基类
*
* @extends BaseModel
* @constructor
*/
function FormModel() {
BaseModel.apply(this, arguments);
}
util.inherits(FormModel, BaseModel);
util.inherits(FormModel, BaseModel);
/**
* 表单默认数据配置
*
* @rule 常用的校验规则
* @formRequester 常规的缺省表单数据promise (可选)
*
*/
FormModel.prototype.formRequester = null;
// 提交接口的promise的生成函数
FormModel.prototype.sumbitRequester = null;
/**
* 表单初始数据请求器
*
* @type {?function}
*/
FormModel.prototype.formRequester = null;
// 默认请求参数,针对formData的请求发送
FormModel.prototype.defaultArgs = {};
/**
* 表单提交请求器
*
* @type {function}
*/
FormModel.prototype.submitRequester = null;
FormModel.prototype.defaultDatasource = {
rule: datasource.constant(require('./rule')),
formData: {
retrieve: function (model) {
if (model.get('formData')) {
return model.get('formData');
/**
* 默认请求参数,针对formData的请求发送
*
* @type {Object}
* @protected
*/
FormModel.prototype.defaultArgs = {};
/**
* 获取默认请求参数,针对formData的请求发送,默认直接返回`this.defaultArgs`
*
* @return {Object}
* @protected
*/
FormModel.prototype.getDefaultArgs = function () {
return this.defaultArgs;
};
/**
* @inheritDoc
*/
FormModel.prototype.defaultDatasource = {
rule: datasource.constant(require('./rule')),
formData: {
retrieve: function (model) {
if (model.get('formData')) {
return model.get('formData');
}
else {
var formRequester = model.formRequester;
if (formRequester) {
return formRequester(model.getDefaultArgs());
}
else {
var formRequester = model.formRequester;
var defaultArgs = model.defaultArgs;
if (formRequester) {
return formRequester(defaultArgs);
}
else {
return {};
}
return {};
}
},
dump: false
}
};
}
},
dump: false
}
};
/**
* 获取缺省数据
*
* @return {Object}
*/
FormModel.prototype.getDefaultData = function () {
return this.get('formData');
};
/**
* 获取缺省数据
*
* @return {Object}
*/
FormModel.prototype.getDefaultData = function () {
return this.get('formData');
};
/**
* 获取最后提交使用的数据
*
* @return {Object}
*/
FormModel.prototype.getSubmitData = function (formData) {
var data = u.extend(formData, this.getExtraData());
data = this.filterData(data);
return data;
};
/**
* 获取最后提交使用的数据
*
* @param {Object} formData 从表单中取得的数据
* @return {Object} 合并后用来提交的数据
*/
FormModel.prototype.getSubmitData = function (formData) {
var data = u.extend(formData, this.getExtraData());
data = this.filterData(data);
return data;
};
/**
* 为表单数据附加数据(比如上传文件的url)
*
* @param {Object} 附加数据
*/
FormModel.prototype.getExtraData = function () {
return {};
};
/**
* 为表单数据附加数据(比如上传文件的url)
*
* @return {Object} 附加数据
*/
FormModel.prototype.getExtraData = function () {
return {};
};
/**
* 过滤提交数据
* 提交前可对所有数据进行操作,比如转换数据格式
*
* @param {Object}
*/
FormModel.prototype.filterData = function(data) {
return data;
};
/**
* 准备提交数据
* 提交前可对所有数据进行操作,比如转换数据格式
*
* @param {Object} data 提交的数据
* @return {Object} 处理完毕的数据
*/
FormModel.prototype.prepareData = function(data) {
return this.filterData(data);
};
/**
* 表单数据是否改动过
*
* @param {Object} 新表单数据
* @return {Boolean}
*/
FormModel.prototype.isFormDataChanged = function (formData) {
var original = this.get('formData');
return !u.isEqual( u.purify(formData, null, true), u.purify(original, null, true));
};
/**
* 准备提交数据
* 提交前可对所有数据进行操作,比如转换数据格式
*
* @deprecated since v0.2.2 名字起得不好,后面使用`prepareData`替代
* @param {Object} data 提交的数据
* @return {Object} 处理完毕的数据
*/
FormModel.prototype.filterData = function(data) {
return data;
};
/**
* 检验表单数据有效性,除了控件自动检测之外的逻辑可以在这里扩展
*
* @param {Object} submitData 提交的数据,包含extraData
* @return {meta.FieldError[] | true}
* {field: {name: message}}
* 返回`true`则验证通过
*/
FormModel.prototype.validateSubmitData = function (submitData) {
return true;
};
/**
* 表单数据是否改动过,默认未改动,取消时直接返回
* 如果需要提示已修改请按需实现此功能
*
* @param {Object} present 新表单数据
* @return {boolean} 是否有变动
*/
FormModel.prototype.isFormDataChanged = function (present) {
return false;
};
return FormModel;
}
);
/**
* 检验表单数据有效性,除了控件自动检测之外的逻辑可以在这里扩展
*
* @param {Object} submitData 提交的数据,包含extraData
* @return {Object|true}
* 返回object形式为
* {
* name1: message1
* name2: message2
* }
* 的`fieldError`内容,可以触发`FormView`的`notifyErrors`
* 返回`true`则验证通过
*/
FormModel.prototype.validateSubmitData = function (submitData) {
return true;
};
return FormModel;
});
/**
* Copyright 2014 Baidu Inc. All rights reserved.
*
* @file FormView基类
* @file 表单类型`View`基类
* @author chestnutchen(chenli11@baidu.com)
* @date $DATE$
*/
define(
function (require) {
var util = require('er/util');
var BaseView = require('./BaseView');
var u = require('underscore');
define(function (require) {
var util = require('er/util');
var BaseView = require('./BaseView');
var u = require('underscore');
var lib = require('esui/lib');
// 使用表单视图,有以下要求:
//
// - 有id为`form`的`Form`控件
// - 所有触发提交的按钮,会触发`form`的`submit`事件
//
// 可选:
//
// - 可以有一个id为`cancel`的按钮,点击后会触发`cancel`事件
/**
* 使用表单视图,有以下要求:
*
* - 有id为`form`的`Form`控件
* - 所有触发提交的按钮,会触发`form`的`submit`事件
* - 可以使用`Form`控件的`data-ui-auto-validate`属性,
* 设置为`true`可以在submit之前自动校验含有`name`属性的`InputControl`
*
* 可选:
*
* - 可以有一个id为`cancel`的按钮,点击后会触发`cancel`事件
* - 可以有一个id为`reset`的按钮,点击后会触发`reset`事件
/**
* 表单视图基类
*
* @extends BaseView
* @constructor
*/
function FormView() {
BaseView.apply(this, arguments);
}
/**
* 表单类型`View`基类
*
* @extends BaseView
* @constructor
*/
function FormView() {
BaseView.apply(this, arguments);
}
util.inherits(FormView, BaseView);
util.inherits(FormView, BaseView);
/**
* 从表单中获取数据
*
* @return {Object}
*/
FormView.prototype.getFormData = function () {
var form = this.get('form');
return form ? form.getData() : {};
};
/**
* 从表单中获取数据
*
* @return {Object}
*/
FormView.prototype.getFormData = function () {
var form = this.get('form');
return u.extend(
{},
form ? form.getData() : {},
this.getExtraFormData()
);
};
/**
* 回滚表单数据
*
* @param {Object} key:value形式的数据 key和input的name一一对应
*/
FormView.prototype.rollbackFormData = function () {
this.setFormData(this.model.getDefaultData());
};
/**
* 获取当前表单需要提交的额外数据
*
* @return {Object} 表单数据
*/
FormView.prototype.getExtraFormData = function () {
return {};
};
/**
* 设置表单数据
*
* @param {Object} key:value形式的数据 key和input的name一一对应
*/
FormView.prototype.setFormData = function (formData) {
var form = this.get('form');
inputs = form.getInputControls();
u.each(inputs, function (input, index) {
var key = input.name;
if (formData) {
if (u.has(formData, key)) {
input.setValue(formData[key]);
}
/**
* 回滚表单数据
*
* @param {Object} defaultData key/value形式的数据,key和input的name一一对应
*/
FormView.prototype.rollbackFormData = function (defaultData) {
this.setFormData(defaultData);
};
/**
* 设置表单数据
*
* @param {Object} formData key:value形式的数据 key和input的name一一对应
*/
FormView.prototype.setFormData = function (formData) {
var form = this.get('form');
var inputs = form.getInputControls();
u.each(inputs, function (input, index) {
var key = input.name;
if (formData) {
if (u.has(formData, key)) {
input.setValue(formData[key]);
}
});
this.setExtraFormData(formData);
};
}
});
this.setExtraFormData(formData);
};
/**
* 设置表单额外数据
* 这个接口提供给不是input的控件去扩展,自个玩去
* 不知道是不是又是可以砍掉的接口
*
* @param {Object} key:value形式的数据 key和input的name一一对应
*/
FormView.prototype.setExtraFormData = function (formData) {
/**
* 设置表单额外数据
* 这个接口提供给不是input的控件去扩展,自个玩去
*
* @param {Object} formData key:value形式的数据 key和input的name一一对应
*/
FormView.prototype.setExtraFormData = function (formData) {
return;
};
/**
* 表单校验
* 为啥要有这东西?Form控件不是有了吗?
* 问得好,Form控件的beforevalidate事件(同步)在FormView中已经阻止掉了
* 然后在FormAction中提供了异步的beforeValidate、validate、afterValidate的扩展点
* 因此FormView必须自己调validate
* 这个方法会在FormAction.validite中和FormModel的校验一起做
* (还不是一堆蛋疼需求导致的...
*
* @return {boolean} 校验是否成功
*/
FormView.prototype.validate = function () {
var form = this.get('form');
var isAutoValidate = form.get('autoValidate');
if (!isAutoValidate) {
return true;
}
return form.validate();
};
/**
* 向用户通知提交错误信息,默认根据`errors`的`key`字段查找对应`name`的控件并显示错误信息
*
* @param {Object} errors 错误信息,每个key为控件`name`,value为`errorMessage`
*
*/
FormView.prototype.notifyErrors = function (errors) {
if (typeof errors !== 'object') {
return;
};
}
/**
* 向用户通知提交错误信息,默认根据`field`字段查找对应`name`的控件并显示错误信息
*
* @param {Object} errors 错误信息,每个key为控件`name`,value为`errorMessage`
*/
FormView.prototype.notifyErrors = function (errors) {
if (typeof errors !== 'object') {
return;
var Validity = require('esui/validator/Validity');
var ValidityState = require('esui/validator/ValidityState');
var form = this.get('form');
u.each(errors, function (message, field) {
var state = new ValidityState(false, message);
var validity = new Validity();
validity.addState('invalid', state);
var input = form.getInputControls(field)[0];
if (input && typeof input.showValidity === 'function') {
input.showValidity(validity);
}
});
};
var Validity = require('esui/validator/Validity');
var ValidityState = require('esui/validator/ValidityState');
var form = this.get('form');
/**
* 重置表单
*/
function reset() {
this.fire('reset');
}
u.each(errors, function (field, message){
var state = new ValidityState(false, message);
var validity = new Validity();
validity.addState('invalid', state);
/**
* 取消编辑
*/
function cancelEdit() {
this.fire('cancel');
}
var input = form.getInputControls(field)[0];
if (input && typeof input.showValidity === 'function') {
input.showValidity(validity);
/**
* 进入提交前的处理
*
* @param {Event} e 事件对象
*/
function submit(e) {
e.preventDefault();
this.fire('submit');
}
/**
* 若页面在目标dom元素下方,设置页面scrollTop至该元素
*
* @param {Element} element label的dom元素
*/
function scrollTo(element) {
var offset = lib.getOffset(element);
if (lib.page.getScrollTop() > offset.top) {
element.scrollIntoView(true);
}
}
/**
* 处理esui表单控件自动校验出错
* 定位至第一个出错的控件
*
* @param {Object} form esui表单控件
* @fire {Event} scrolltofirsterror 定位至页面第一个出错的控件
*/
FormView.prototype.handleValidateInvalid = function () {
var me = this;
var form = this.get('form');
u.some(form.getInputControls(), function (input) {
if (input.hasState('validity-invalid')) {
var e = me.fire('scrolltofirsterror', {firstErrValidity: input});
if (!e.isDefaultPrevented()) {
scrollTo(input.main);
}
});
};
return true;
}
});
};
/**
* 取消编辑
*/
function cancelEdit() {
this.fire('cancel');
/**
* 绑定控件事件
*
* @override
*/
FormView.prototype.bindEvents = function () {
var form = this.get('form');
if (form) {
form.on('beforevalidate', submit, this);
}
/**
* 提交数据
*/
function submit() {
this.fire('submit');
var resetButton = this.get('reset');
if (resetButton) {
resetButton.on('click', reset, this);
}
/**
* 绑定控件事件
*
* @override
*/
FormView.prototype.bindEvents = function () {
var form = this.get('form');
if (form) {
form.on('submit', submit, this);
}
var cancelButton = this.get('cancel');
if (cancelButton) {
cancelButton.on('click', cancelEdit, this);
}
var cancelButton = this.get('cancel');
if (cancelButton) {
cancelButton.on('click', cancelEdit, this);
}
BaseView.prototype.bindEvents.apply(this, arguments);
};
BaseView.prototype.bindEvents.apply(this, arguments);
};
/**
* 禁用提交操作
*/
FormView.prototype.disableSubmit = function () {
if (this.viewContext) {
this.getGroup('submit').disable();
}
};
/**
* 禁用提交操作
*/
FormView.prototype.disableSubmit = function () {
if (this.viewContext) {
this.getGroup('submit').disable();
}
};
/**
* 启用提交操作
*/
FormView.prototype.enableSubmit = function () {
if (this.viewContext) {
this.getGroup('submit').enable();
}
};
/**
* 启用提交操作
*/
FormView.prototype.enableSubmit = function () {
if (this.viewContext) {
this.getGroup('submit').enable();
}
};
return FormView;
}
);
return FormView;
});
/**
* Copyright 2013 Baidu Inc. All rights reserved.
*
* @ignore
* @file 列表Action基类
* @author Justineo
* @date $DATE$
* @file 列表类型`Action`基类
* @author Justineo(justice360@gmail.com)
*/
define(
function (require) {
var BaseAction = require('./BaseAction');
var util = require('er/util');
var u = require('underscore');
var URL = require('er/URL');
/**
* 列表Action基类
*
* @param {string} [entityName] 负责的实体名称
* @extends BaseAction
* @constructor
*/
function ListAction(entityName) {
BaseAction.apply(this, arguments);
}
define(function (require) {
var BaseAction = require('./BaseAction');
var util = require('er/util');
var u = require('underscore');
var URL = require('er/URL');
util.inherits(ListAction, BaseAction);
/**
* 列表`Action`基类
*
* @extends BaseAction
* @constructor
*/
function ListAction() {
BaseAction.apply(this, arguments);
}
ListAction.prototype.modelType = './ListModel';
util.inherits(ListAction, BaseAction);
/**
* 进行查询
*
* @param {Object} args 查询参数
*/
ListAction.prototype.performSearch = function (args) {
// 去除默认参数值
var defaultArgs = this.model.getDefaultArgs();
var extraArgs = this.model.getExtraQuery();
args = u.chain(args)
.purify(defaultArgs)
.extend(extraArgs)
.value();
var event = this.fire('search', { args: args });
if (!event.isDefaultPrevented()) {
this.redirectForSearch(args);
}
};
/**
* 在搜索、翻页等操作后选择触发跳转还是仅刷新列表
*
* @type {boolean}
*/
ListAction.prototype.redirectAfterChange = true;
/**
* 进行查询引起的重定向操作
*
* @param {Object} args 查询参数
*/
ListAction.prototype.redirectForSearch = function (args) {
var path = this.model.get('url').getPath();
var url = URL.withQuery(path, args);
this.redirect(url, { force: true });
};
/**
* 进行查询
*
* @param {Object} args 查询参数
*/
ListAction.prototype.performSearch = function (args) {
// 去除默认参数值
var defaultArgs = this.model.getDefaultArgs();
var extraArgs = this.model.getExtraQuery();
args = u.chain(args)
.extend(extraArgs)
.purify(defaultArgs)
.value();
/**
* 获取指定页码的跳转URL
*
* @param {number} pageNo 指定的页码
* @return {string}
*/
ListAction.prototype.getURLForPage = function (pageNo) {
var url = this.context.url;
var path = url.getPath();
var query = url.getQuery();
query.pageNo = pageNo;
var event = this.fire('search', {args: args});
if (!event.isDefaultPrevented()) {
this.redirectForSearch(args);
}
};
// 第一页省去页码参数
if (pageNo === 1) {
query = u.omit(query, 'pageNo');
}
/**
* 进行查询引起的重定向操作
*
* @param {Object} args 查询参数
*/
ListAction.prototype.redirectForSearch = function (args) {
var path = this.model.get('url').getPath();
var url = URL.withQuery(path, args);
this.loadList(url);
};
return require('er/URL').withQuery(path, query).toString();
};
/**
* 获取指定页码的跳转URL
*
* @param {number} pageNo 指定的页码
* @return {er/URL} 生成的分页URL对象
*/
ListAction.prototype.getURLForPage = function (pageNo) {
var url = this.model.get('url');
var path = url.getPath();
var query = url.getQuery();
query.pageNo = pageNo;
/**
* 查询的事件处理函数
*
* @param {Object} e 事件对象
* @ignore
*/
function search(e) {
this.performSearch(e.args);
// 第一页省去页码参数
if (pageNo === 1) {
query = u.omit(query, 'pageNo');
}
/**
* 前往指定页
*
* @param {mini-event.Event} e 事件对象
* @param {number} e.page 前往的页码
* @ignore
*/
function forwardToPage(e) {
var event = this.fire('pagechange', { page: e.page });
if (!event.isDefaultPrevented()) {
var url = this.getURLForPage(e.page);
this.redirect(url);
}
return require('er/URL').withQuery(path, query);
};
/**
* 查询的事件处理函数
*
* @param {Object} e 事件对象
* @ignore
*/
function search(e) {
this.performSearch(e.args);
}
/**
* 前往指定页
*
* @param {mini-event.Event} e 事件对象
* @param {number} e.page 前往的页码
* @ignore
*/
function forwardToPage(e) {
var event = this.fire('pagechange', {page: e.page});
if (!event.isDefaultPrevented()) {
var url = this.getURLForPage(e.page);
this.loadList(url);
}
}
/**
* 初始化交互行为
*
* @protected
* @override
*/
ListAction.prototype.initBehavior = function () {
BaseAction.prototype.initBehavior.apply(this, arguments);
this.view.on('search', search, this);
this.view.on('pagesizechange', search, this);
this.view.on('pagechange', forwardToPage, this);
};
/**
* 根据新的URL参数刷新列表
*
* @param {er.URL} [url] 新的URL对象,没有时按当前URL刷新
* @return {er.Promise} 返回请求的Promise对象
*/
ListAction.prototype.loadList = function (url) {
if (this.redirectAfterChange) {
this.redirect(url, {force: true});
}
else {
var me = this;
url = url || me.model.get('url');
/**
* 根据布局变化重新调整自身布局
*/
ListAction.prototype.adjustLayout = function () {
this.view.adjustLayout();
};
return ListAction;
}
);
return me.model.loadData(url).then(function () {
me.redirect(url, {silent: true});
me.view.refresh();
});
}
};
/**
* 初始化交互行为
*
* @protected
* @override
*/
ListAction.prototype.initBehavior = function () {
BaseAction.prototype.initBehavior.apply(this, arguments);
this.view.on('search', search, this);
this.view.on('pagechange', forwardToPage, this);
};
/**
* 初始化交互行为
*
* @protected
* @override
*/
ListAction.prototype.reload = function () {
if (this.redirectAfterChange) {
BaseAction.prototype.reload.call(this);
}
else {
this.loadList();
}
};
/**
* 根据布局变化重新调整自身布局
*/
ListAction.prototype.adjustLayout = function () {
this.view.adjustLayout();
};
// /**
// * @inheritDoc
// *
// * @protected
// * @override
// */
// ListAction.prototype.filterRedirect = function (url) {
// if (url.getPath() !== this.model.get('url').getPath()
// || this.redirectAfterChange) {
// return true;
// }
// this.loadList(url);
// return false;
// };
return ListAction;
});
/**
* Copyright 2014 Baidu Inc. All rights reserved.
*
* @file Model基类
* @file 列表类型Model基类
* @author Justineo(justice360@gmail.com)
* @date $DATE$
*/
define(
function (require) {
var u = require('underscore');
var util = require('er/util');
var BaseModel = require('./BaseModel');
var batUtil = require('../util');
define(function (require) {
var u = require('underscore');
var util = require('er/util');
var BaseModel = require('./BaseModel');
var batUtil = require('../util');
/**
* 业务`Model`基类
*
* @param {Object=} context 初始化时的数据
*
* @constructor
* @extends ef/BaseModel
*/
function ListModel(context) {
BaseModel.call(this, context);
}
/**
* 业务`Model`基类
*
* @param {Object} [context] 初始化时的数据
*
* @constructor
* @extends ef.BaseModel
*/
function ListModel(context) {
BaseModel.call(this, context);
}
util.inherits(ListModel, BaseModel);
util.inherits(ListModel, BaseModel);
ListModel.prototype.list;
/**
* 列表数据请求器
*
* @type {function}
*/
ListModel.prototype.listRequester;
/**
* 配置默认查询参数
*
* 如果某个参数与这里的值相同,则不会加到URL中
*
* 创建`Model`时,如果某个参数不存在,则会自动补上这里的值
*
* @type {Object}
* @protected
*/
ListModel.prototype.defaultArgs = {};
/**
* 配置默认查询参数
*
* 如果某个参数与这里的值相同,则不会加到URL中
*
* 创建`Model`时,如果某个参数不存在,则会自动补上这里的值
*
* @type {Object}
* @protected
*/
ListModel.prototype.defaultArgs = {};
/**
* 默认查询参数
*
* 参考{@link ListModel#defaultArgs}属性的说明
*
* @return {Object}
* @protected
*/
ListModel.prototype.getDefaultArgs = function () {
return u.defaults(this.defaultArgs || {}, { pageNo: 1 });
};
/**
* 默认查询参数
*
* 参考{@link ListModel#defaultArgs}属性的说明
*
* @return {Object}
* @protected
*/
ListModel.prototype.getDefaultArgs = function () {
return u.defaults(this.defaultArgs || {}, {pageNo: 1});
};
/**
* 默认数据源
*/
ListModel.prototype.defaultDatasource = {
listPage: {
retrieve: function (model) {
return model.listRequester(model.getQuery())
.then(function(data) {
var page = data;
page.tableData = page.result;
delete page.result;
return page;
});
},
dump: true
/**
* 转换列表数据
* 将返回值中的`result`字段改为`tableData`来放到Model中
*
* @param {Object} data 列表请求接口返回的数据
* @return {Object} 转换完毕的数据
*/
function adaptData(data) {
var page = data;
page.tableData = page.result;
delete page.result;
return page;
}
/**
* @inheritDoc
*/
ListModel.prototype.defaultDatasource = {
listPage: {
retrieve: function (model) {
return model.listRequester(model.getQuery())
.then(adaptData);
},
dump: true
},
// 展示时间区间
time: {
retrieve: function (model) {
var startTime = model.get('startTime');
var endTime = model.get('endTime');
// 展示时间区间
time: {
retrieve: function (model) {
var startTime = model.get('startTime');
var endTime = model.get('endTime');
// 有输入参数
if (startTime && endTime) {
return {
time: batUtil.getTimeRange(startTime, endTime)
};
}
// 有输入参数
if (startTime && endTime) {
return {
time: batUtil.getTimeRange(startTime, endTime)
};
}
// 无输入参数,取默认配置,若无则不需要输出
var range = model.defaultTimeRange;
if (range) {
return {
time: range
};
}
else {
return {};
}
},
dump: true
// 无输入参数,取默认配置,若无则不需要输出
var range = model.defaultTimeRange;
if (range) {
return {
time: range
};
}
else {
return {};
}
},
dump: true
},
// 分页URL模板,就是当前URL中把`page`字段替换掉
urlTemplate: function (model) {
var url = model.get('url');
var path = url.getPath();
// 由于`withQuery`会做URL编码,因此不能直接`query.page = '${page}'`,
// 会被编码成`%24%7Bpage%7D`,此处只能直接操作字符串
var query = url.getQuery();
delete query.pageNo;
var template = '#' + require('er/URL').withQuery(path, query);
var delimiter = u.isEmpty(query) ? '~' : '&';
template += delimiter + 'pageNo=${page}';
return template;
}
};
// 分页URL模板,就是当前URL中把`page`字段替换掉
urlTemplate: function (model) {
var url = model.get('url');
var path = url.getPath();
// 由于`withQuery`会做URL编码,因此不能直接`query.page = '${page}'`,
// 会被编码成`%24%7Bpage%7D`,此处只能直接操作字符串
var query = url.getQuery();
delete query.pageNo;
var template = '#' + require('er/URL').withQuery(path, query);
var delimiter = u.isEmpty(query) ? '~' : '&';
template += delimiter + 'pageNo=${page}';
return template;
}
};
/**
* 默认选择的时间范围
*
* @type {?{begin: Date, end: Date}}
* @protected
*/
ListModel.prototype.defaultTimeRange = null;
/**
* 默认选择的时间范围
*
* @type {?{begin: Date, end: Date}}
* @protected
*/
ListModel.prototype.defaultTimeRange = null;
/**
* 默认选择的时间范围
*
* @return {Object}
* @protected
*/
ListModel.prototype.getQuery = function () {
var url = this.get('url');
var query = url.getQuery();
/**
* 生成默认的后端请求参数
*
* @return {Object}
* @protected
*/
ListModel.prototype.getQuery = function () {
var url = this.get('url');
var query = url.getQuery();
// 取一下默认时间配置
var range = this.defaultTimeRange;
if (range) {
range = batUtil.getTimeRange(range.begin, range.end, {
outputFormat: 'YYYYMMDDHHmmss',
beginKey: 'startTime',
endKey: 'endTime'
});
}
else {
range = {};
}
// 取一下默认时间配置
var range = this.defaultTimeRange;
if (range) {
range = batUtil.getTimeRange(range.begin, range.end, {
outputFormat: 'YYYYMMDDHHmmss',
beginKey: 'startTime',
endKey: 'endTime'
});
}
else {
range = {};
}
// 合并默认参数、附加参数,最后再统一处理一下输出
query = u.chain(query)
.defaults(this.getDefaultArgs())
.defaults(range)
.extend(this.getExtraQuery())
.value();
// 合并默认参数、附加参数,最后再统一处理一下输出
u.chain(query)
.defaults(this.getDefaultArgs())
.defaults(range)
.extend(this.getExtraQuery());
return this.filterQuery(query);
};
return this.prepareQuery(query);
};
/**
* 获取附加的请求参数
*
* @return {Object}
* @protected
*/
ListModel.prototype.getExtraQuery = function () {
return {};
};
/**
* 获取除列表本身参数外附加的请求参数
*
* @return {Object}
* @protected
*/
ListModel.prototype.getExtraQuery = function () {
return {};
};
/**
* 对合并好的请求参数进行统一的后续处理
*
* @param {Object} query 需要处理的参数对象
* @return {Object}
* @protected
*/
ListModel.prototype.filterQuery = function(query) {
return query;
};
/**
* 对合并好的请求参数进行统一的后续处理
*
* @deprecated since v0.2.1 名字起得不好,后面使用`prepareQuery`替代
* @param {Object} query 需要处理的参数对象
* @return {Object}
* @protected
*/
ListModel.prototype.filterQuery = function (query) {
return query;
};
return ListModel;
}
);
/**
* 对合并好的请求参数进行统一的后续处理
*
* @param {Object} query 需要处理的参数对象
* @return {Object}
* @protected
*/
ListModel.prototype.prepareQuery = function (query) {
return this.filterQuery(query);
};
/**
* 重新读取列表数据
*
* @param {er/URL} url 根据指定URL读取数据
* @return {er/Promise} 返回异步请求的Promise对象
* @protected
*/
ListModel.prototype.loadData = function (url) {
var me = this;
var urlQuery = url.getQuery();
me.set('url', url);
me.fill(urlQuery);
return me.listRequester(me.getQuery())
.then(function(data) {
me.fill(adaptData(data));
});
};
return ListModel;
});
/**
* @file [Please Input File Description]
* @file 列表类型`View`基类
* @author Justineo(justice360@gmail.com)

@@ -13,7 +13,8 @@ */

var moment = require('moment');
/**
* [Please Input View Description]
*
* 列表`View`基类
*
* @constructor
* @extends ef.BaseView
*/

@@ -23,5 +24,11 @@ function ListView() {

}
/**
* @inheritDoc
*/
ListView.prototype.uiProperties = {};
/**
* @inheritDoc
*/
ListView.prototype.uiEvents = {};

@@ -32,3 +39,2 @@

*
* @param {ListView} this 当前视图实例
* @param {mini-event.Event} e 控件事件对象

@@ -45,11 +51,7 @@ */

// 总是带上每页显示数
args.pageSize = this.get('pager').get('pageSize');
this.fire('search', { args: args });
this.fire('search', {args: args});
};
/**
* 获取查询参数,默认是取`filter`表单的所有数据,加上表格的排序字段
* 获取查询参数,默认是取`filter`表单的所有数据,加上表格的排序字段和每页显示条目数
*

@@ -62,2 +64,3 @@ * @return {Object}

var args = form ? form.getData() : {};
// 加上原本的排序方向和排序字段名

@@ -72,7 +75,17 @@ args.order = this.model.get('order');

}
// 日期是独立的
var range = this.get('range').getValue().split(',');
args.startTime = moment(range[0]).format('YYYYMMDDHHmmss');
args.endTime = moment(range[1]).format('YYYYMMDDHHmmss');
var range = this.get('range');
if (range) {
range = range.getValue().split(',');
args.startTime = moment(range[0]).format('YYYYMMDDHHmmss');
args.endTime = moment(range[1]).format('YYYYMMDDHHmmss');
}
// 带上每页显示数
var pager = this.get('pager');
if (pager) {
args.pageSize = pager.get('pageSize');
}
return args;

@@ -89,5 +102,67 @@ };

var page = e.target.get('page');
this.fire('pagechange', { page: page });
this.fire('pagechange', {page: page});
}
/**
* 根据表格中所选择的行来控制批量更新按钮的启用/禁用状态
*/
ListView.prototype.updateBatchButtonStatus = function () {
var items = this.getSelectedItems();
this.getGroup('batch').set('disabled', u.isEmpty(items));
this.getGroup('batch').set('readOnly', u.isEmpty(items));
};
/**
* 获取table已经选择的列的数据
*
* @return {Object[]} 当前table的已选择列对应的数据
*/
ListView.prototype.getSelectedItems = function () {
var table = this.get('table');
return table ? table.getSelectedItems() : [];
};
/**
* 触发批量操作
*
* @param {Object} e 控件事件对象
* @ignore
*/
function batchModify(e) {
var args = {
// 批量操作的类型
action: e.target.getData('type'),
selectedItems: this.get('table').getSelectedItems()
};
this.fire('batchmodify', args);
}
/**
* 侧边栏模式改变时要调整整体布局
*
* @param {Object} e 模式切换事件对象
*/
function sidebarModeChange(e) {
// Sidebar目前只提供了操作DOM的方式更新布局,需要对ESUI做优化后再升级这块
var neighbor = document.getElementById('neighbor');
if (!neighbor) {
return;
}
if (e.mode === 'fixed') {
neighbor.className = 'ui-sidebar-neighbor';
}
else {
neighbor.className = 'ui-sidebar-neighbor-hide';
}
this.adjustLayout();
}
/**
* @inheritDoc
*/
ListView.prototype.bindEvents = function() {

@@ -103,2 +178,4 @@ var pager = this.get('pager');

if (table) {
// 选中表格行后控制批量更新按钮的启用/禁用状态
table.on('select', this.updateBatchButtonStatus, this);
// 表格排序触发查询

@@ -114,7 +191,79 @@ table.on('sort', this.submitSearch, this);

var sidebar = this.get('sidebar');
if (sidebar) {
sidebar.on('modechange', sidebarModeChange, this);
}
u.each(
this.getGroup('batch'),
function (button) {
if (button instanceof require('esui/Button')) {
// 批量更新
button.on('click', batchModify, this);
}
},
this
);
BaseView.prototype.bindEvents.apply(this, arguments);
};
/**
* 控制元素展现
*
* @override
*/
ListView.prototype.enterDocument = function () {
BaseView.prototype.enterDocument.apply(this, arguments);
this.updateBatchButtonStatus();
this.adjustLayout();
};
/**
* 根据布局变化重新调整自身布局
*/
ListView.prototype.adjustLayout = function () {
var table = this.get('table');
if (table) {
table.adjustWidth();
}
};
/**
* 根据Model数据重新渲染页面
*/
ListView.prototype.refresh = function () {
// 刷新列表
this.refreshList();
// 最后刷新权限显示
this.refreshAuth();
};
/**
* 根据Model数据重新渲染列表
*/
ListView.prototype.refreshList = function () {
var model = this.model;
var table = this.get('table');
if (table) {
table.setDatasource(model.get('tableData'));
}
var pager = this.get('pager');
if (pager) {
pager.setProperties(
{
count: model.get('totalCount'),
page: model.get('pageNo'),
pageSize: model.get('pageSize')
},
{silent: true}
);
}
};
require('er/util').inherits(ListView, BaseView);
return ListView;
});

@@ -18,7 +18,28 @@ /**

/**
* 电子邮件地址正则
* 电子邮件地址正则字符串
*/
pattern: '^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$'
pattern: '^\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*$',
internal: {
/**
* 公司电子邮件地址正则字符串
*/
pattern: '^\\w+([-+.]\\w+)*@(\\w+\\.)?baidu\\.com$'
}
},
multiEmail: {
/**
* 电子邮件地址正则字符串
*/
pattern: '^((\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*),?)+$',
internal: {
/**
* 公司电子邮件地址正则字符串
*/
pattern: '^((\\w+([-+.]\\w+)*@(\\w+\\.)?baidu\\.com),?)+$'
}
},
description: {

@@ -35,3 +56,3 @@ /**

*/
pattern: '^(1(3|4|5|8)\\d{9})?$'
pattern: '^(1(3|4|5|8)\\d{9})$'
},

@@ -44,3 +65,3 @@

*/
pattern: '(^((0\\d{2,3})-)(\\d{7,8})(-(\\d{3,}))?$)|(^(1(3|4|5|8)\\d{9})?$)'
pattern: '(^((0\\d{2,3})-)(\\d{7,8})(-(\\d{3,}))?$)|(^(1(3|4|5|8)\\d{9})$)'
},

@@ -62,3 +83,3 @@

/**
* 正整数正则
* 正整数正则字符串
*/

@@ -70,3 +91,3 @@ pattern: '^\\d+$'

/**
* 价格类数字正则
* 价格类数字正则字符串
* 精确至小数点后两位

@@ -73,0 +94,0 @@ */

/**
* @file [Please input file description]
* @file 常量保存与转换
* @author Justineo(justice360@gmail.com)

@@ -10,5 +10,23 @@ */

var map = {};
/**
* [Please input module description]
*/
var VL_MAP_SUFFIX = '_MAP';
var VL_DATASOURCE_SUFFIX = '_DATASOURCE';
function handleVL(value, key) {
// 数组且只要数组元素都包含v、l两个key,就进行转换
if (
u.isArray(value)
&& !u.contains(u.pluck(value, 'v'), undefined)
&& !u.contains(u.pluck(value, 'l'), undefined)
) {
var vlMap = map[key + VL_MAP_SUFFIX] = {};
var vlDatasource = map[key + VL_DATASOURCE_SUFFIX] = [];
u.each(value, function(item) {
vlMap[item.v] = item.l;
vlDatasource.push(u.mapKey(item, {v: 'value', l: 'text'}));
});
}
}
var exports = {

@@ -21,2 +39,3 @@ get: function (key) {

map[key] = value;
handleVL(value, key);
},

@@ -28,9 +47,28 @@

getMap: function (key) {
return map[key + VL_MAP_SUFFIX];
},
getDatasource: function (key) {
return map[key + VL_DATASOURCE_SUFFIX];
},
init: function (constants) {
// 先copy所有内容
u.extend(map, constants);
// 处理`VL`类型常量
// 例如 [ { v: 'ACTIVE', l: '已启用' }, { v: 'INACTIVE', l: '未启用' } ]
// 将生成如下几种形式的数据:
// 1. 以v为key、以l为value的对象,命名为`[原始常量名]_MAP`
// 如 { ACTIVE: '已启用', INACTIVE: '未启用' }
// 2. 将v/l分别转换为value/text的数组,命名为`[原始常量名]_DATASOURCE`
// 如 [ { value: 'ACTIVE', text: '已启用' }, { value: 'INACTIVE', text: '未启用' } ]
u.each(map, handleVL);
}
};
// return模块
return exports;
});
/**
* @file [Please input file description]
* @file 用户信息模块
* @author Justineo(justice360@gmail.com)

@@ -7,8 +7,13 @@ */

define(function (require) {
var u = require('underscore');
var permission = require('er/permission');
var URI = require('urijs');
var auth = require('./auth');
/**
* [Please input module description]
* 用户信息模块
*/
var exports = {
init: function(session) {
init: function (session) {
if (session.visitor) {

@@ -23,2 +28,50 @@ this.visitor = session.visitor;

}
// 如果配置了权限信息,需要初始化 `er/permission`
var auth = this.visitor.auth;
if (auth) {
permission.add(u.mapObject(auth, function (value) {
return value !== 'none';
}));
}
},
getVisitor: function () {
return this.visitor || null;
},
getVisitorId: function () {
return this.visitor && this.visitor.id;
},
getAder: function () {
return this.ader || null;
},
getAderId: function () {
return this.ader && this.ader.id
|| URI.parseQuery(document.location.search).aderId
|| this.visitor && this.visitor.id;
},
getAuthMap: function () {
var authMap = this.visitor && this.visitor.auth;
return authMap || null;
},
getAuthType: function (authId) {
return auth.get(authId, this.getAuthMap());
},
getAuth: function (authId) {
var authType = this.getAuthType(authId);
return {
type: authType,
id: authId,
isReadOnly: authType === auth.AuthType.READONLY,
isEditable: authType === auth.AuthType.EDITABLE,
isVisible: authType !== auth.AuthType.NONE,
isNone: authType === auth.AuthType.NONE
};
}

@@ -25,0 +78,0 @@ };

/**
* Copyright 2013 Baidu Inc. All rights reserved.
*
* @file tpl加载插件
* @author otakustay
* @date $DATE$
*/

@@ -15,3 +12,2 @@ define(

var controlModulePrefix = {
// Sidebar不使用esui的,那个不大符合要求
BoxGroup: 'esui',

@@ -26,2 +22,3 @@ Button: 'esui',

Frame: 'esui',
Image: './ui',
Label: 'esui',

@@ -38,2 +35,3 @@ Link: 'esui',

Select: 'esui',
Sidebar: 'esui',
Tab: 'esui',

@@ -46,6 +44,15 @@ Table: 'esui',

Tree: 'esui',
Uploader: './ui',
Validity: 'esui',
Wizard: 'esui',
ActionPanel: 'ef',
ActionDialog: 'ef'
ActionDialog: 'ef',
SelectorTreeStrategy: './ui',
TreeRichSelector: './ui',
TableRichSelector: './ui',
RichSelector: './ui',
ToggleButton: './ui',
AuthPanel: './ui',
SearchTree: './ui',
RichBoxGroup: './ui'
};

@@ -132,3 +139,2 @@

*
* @class tpl
* @singleton

@@ -150,4 +156,4 @@ */

* @param {string} resourceId 模板资源id
* @param {function} parentRequire 父级`require`函数
* @param {function} load 加载完成后调用
* @param {Function} parentRequire 父级`require`函数
* @param {Function} load 加载完成后调用
*/

@@ -162,12 +168,19 @@ load: function (resourceId, parentRequire, load) {

require(dependencies, function () { load(text); });
require(dependencies, function() {
load(text);
});
}
var options = {
method: 'GET',
url: parentRequire.toUrl(resourceId),
cache: true,
dataType: 'text'
};
ajax.request(options).then(addTemplate);
if (/\.html?$/.test(resourceId)) {
var options = {
method: 'GET',
url: parentRequire.toUrl(resourceId),
cache: true,
dataType: 'text'
};
ajax.request(options).then(addTemplate);
}
else {
require([resourceId], addTemplate);
}
},

@@ -174,0 +187,0 @@

/**
* ADM 2.0
* Copyright 2013 Baidu Inc. All rights reserved.
*
* @ignore
* @file 让输入控件在特定事件下自动提交表单的扩展
* @author otakustay
* @date $DATE$
*/

@@ -71,4 +66,4 @@ define(

// 如果没指定表单,就沿DOM结构向上找一个表单控件
var element = this.target
&& this.target.main
var element = this.target
&& this.target.main
&& this.target.main.parentNode;

@@ -128,3 +123,3 @@ while (element) {

);
Extension.prototype.inactivate.apply(this, arguments);

@@ -131,0 +126,0 @@ };

@@ -49,3 +49,3 @@ /**

var typeRule = /table-operation-(\w+)/;
var typeRule = /table-operation-(\w+(?:-\w+)*)/;

@@ -63,6 +63,7 @@ function getTipType(element) {

TableTip.prototype.createAndAttachTip = function (elements, type) {
var element = elements[0];
var options = {
id: 'table-operation-tip-' + u.escape(type),
viewContext: this.target.viewContext,
content: lib.getText(elements[0]),
content: element.getAttribute('data-title') || element.innerHTML,
arrow: true,

@@ -74,3 +75,3 @@ skin: 'table-tip'

u.each(
elements,
elements,
function (element) {

@@ -82,4 +83,4 @@ var options = {

positionOpt: {
bottom: 'bottom',
left: 'left'
top: 'top',
right: 'left'
}

@@ -100,3 +101,4 @@ };

var elements = document.querySelectorAll('.table-operation');
// 根据Table主元素来限定范围
var elements = this.target.main.querySelectorAll('.table-operation');

@@ -116,3 +118,3 @@ u.chain(elements)

this.target.on('afterrender', this.initTips, this);
this.target.on('bodyChange', this.initTips, this);
};

@@ -126,3 +128,3 @@

TableTip.prototype.inactivate = function () {
this.target.un('afterrender', this.initTips, this);
this.target.un('bodyChange', this.initTips, this);

@@ -137,2 +139,2 @@ Extension.prototype.inactivate.apply(this, arguments);

}
);
);

@@ -154,3 +154,3 @@ /**

this.target.un('afterrender', checkLength, this);
Extension.prototype.inactivate.apply(this, arguments);

@@ -157,0 +157,0 @@ };

@@ -13,21 +13,26 @@ define(function (require) {

// 不然会随着跳转被销毁,造成下次用不了
var Toast = require('./Toast');
var toastOptions = {
var ui = require('esui');
require('esui/Dialog');
var main = document.createElement('div');
document.body.appendChild(main);
var dialgOptions = {
main: main,
title: '系统提示',
disposeOnHide: false,
autoShow: false,
mask: true,
duration: Infinity,
top: 180,
width: 'auto',
needFoot: false,
skin: 'loading'
};
globalLoading = new Toast(toastOptions);
globalLoading.on(
'hide',
u.bind(globalLoading.detach, globalLoading)
);
globalLoading.render();
globalLoading = ui.create('Dialog', dialgOptions);
globalLoading.show();
}
var properties = {
content: content || '正在读取数据,请稍候...',
status: undefined
content: content || '正在读取数据,请稍候...'
};

@@ -37,3 +42,5 @@ properties = u.extend(properties, options);

globalLoading.show();
globalLoading.main.style.zIndex = parseInt(globalLoading.main.style.zIndex, 10) + 1;
loadingCount++;
loadingTimer && clearTimeout(loadingTimer);
return globalLoading;

@@ -40,0 +47,0 @@ }

/**
* Copyright 2014 Baidu Inc. All rights reserved.
*
*
* @ignore

@@ -8,227 +8,354 @@ * @file BAT工具模块

*/
define(
function (require) {
var u = require('underscore');
var moment = require('moment');
var io = require('./io/serverIO');
var util = {};
/**
* 根据URL字符串生成请求发送器
*
* @param {string | Array.<string> | Object.<string, string>} url 请求路径或多个请求路径的集合
* @return {Function | Array.<Function> | Object.<string, Function>} 将对应的路径转换为发送器后返回
*/
util.genRequesters = function (url) {
if (u.isString(url)) {
// 只有一个URL,直接返回封装过的请求方法
return function (data) {
return io.post(url, data);
};
}
else if (u.isObject(url)) {
// 是一个集合,那么每个项目都封装一下
var map = u.clone(url);
u.each(map, function (url, name) {
if (u.isString(url)) {
map[name] = function (data) {
return io.post(url, data);
};
}
// 如果不是string那可能封装过了
});
return map;
}
};
define(function (require) {
var u = require('underscore');
var moment = require('moment');
var io = require('./io/serverIO');
util.getTimeRange = function (begin, end, options) {
/**
* 工具模块
*
* @singleton
*/
var util = {};
// 只有一个参数时,认为是options
if (arguments.length === 1) {
options = begin;
/**
* 根据URL字符串生成请求发送器
*
* 传入一个字符串时,只返回一个发送器函数;传入数组或对象时,递归;传入函数时
*
* @param {string|Array.<string>|Object.<string, string>|function} url 请求路径或多个请求路径的集合,或是取值函数
* @param {function(string):boolean} isRequester 判断是否是需要生成请求发送器的路径
* @return {function|Array.<function>|Object.<string, function>} 将对应的路径转换为发送器后返回
*/
util.genRequesters = function (url, isRequester) {
if (u.typeOf(url) === 'String') {
// 只有一个URL,直接返回封装过的请求方法
// 过滤掉不需要生成的URL
isRequester = isRequester || function (path) {
// 默认跳过以`/download`和`/upload`结尾的路径
return !/\/(?:up|down)load$/.test(path);
};
if (!isRequester(url)) {
return url;
}
var defaults = {
inputFormat: 'YYYYMMDDHHmmss',
outputFormat: 'Date'
return function (data, options) {
return io.post(url, data, options);
};
}
else if (u.typeOf(url) === 'Object' || u.typeOf(url) === 'Array') {
// 是一个集合,那么递归封装一下
var collection = u.clone(url);
u.each(collection, function (url, key) {
collection[key] = util.genRequesters(url);
});
return collection;
}
else if (u.typeOf(url) === 'Function') {
// 是一个函数,不用封装
return url;
}
};
options = u.defaults({}, options, defaults);
/**
* 生成时间段数据
*
* 未指定`begin`及`end`时默认取最近7天
*
* 有两种重载:
* 1. getTimeRange(options)
* 2. getTimeRange(begin, end, options)
*
* @param {Date|string} [begin] 开始日期
* @param {Date|string} [end] 结束日期
* @param {Object} [options] 生成选项
* @param {string} [options.inputFormat] 输入参数的格式,为`'Date'`时会当作`Date`对象,否则为格式字符串
* @param {string} [options.outputFormat] 输出参数的格式,参见`inputFormat`
* @param {string} [options.beginKey] 结果对象开始时间的键名
* @param {string} [options.endKey] 结果对象结束时间的键名
* @return {Object} 时间段的数据,格式由`options`参数决定
*/
util.getTimeRange = function (begin, end, options) {
// 解析输入,没有则使用默认时间
if (begin && end) {
begin = u.isString(begin)
? moment(begin, options.inputFormat)
: moment(begin);
end = u.isString(end)
? moment(end, options.inputFormat)
: moment(end);
}
else {
var now = moment().startOf('day');
// 只有一个参数时,认为是options
if (arguments.length === 1) {
options = begin;
}
// 默认前七天
begin = now.clone().subtract('days', 7);
end = now.clone().subtract('day', 1).endOf('day');
}
var defaults = {
inputFormat: 'YYYYMMDDHHmmss',
outputFormat: 'Date'
};
// 处理输出
if (options.outputFormat.toLowerCase() === 'date') {
begin = begin.toDate();
end = end.toDate();
}
else {
begin = begin.format(options.outputFormat);
end = end.format(options.outputFormat);
}
options = u.defaults({}, options, defaults);
var keys = {
begin: options.beginKey || 'begin',
end: options.endKey || 'end'
};
// 解析输入,没有则使用默认时间
if (begin && end) {
begin = u.isString(begin)
? moment(begin, options.inputFormat)
: moment(begin);
end = u.isString(end)
? moment(end, options.inputFormat)
: moment(end);
}
else {
var now = moment().startOf('day');
return u.mapKey(
{
begin: begin,
end: end
},
{
begin: keys.begin,
end: keys.end
}
);
// 默认前七天
begin = now.clone().subtract('days', 7);
end = now.clone().subtract('day', 1).endOf('day');
}
// 处理输出
if (options.outputFormat.toLowerCase() === 'date') {
begin = begin.toDate();
end = end.toDate();
}
else {
begin = begin.format(options.outputFormat);
end = end.format(options.outputFormat);
}
var keys = {
begin: options.beginKey || 'begin',
end: options.endKey || 'end'
};
util.toMap = function (list, key, opt_converter) {
var i, item, k,
map = {},
converter = opt_converter;
return u.mapKey(
{
begin: begin,
end: end
},
{
begin: keys.begin,
end: keys.end
}
);
};
for (i = list.length; i--;) {
item = list[i];
k = item[key];
if (k != null) {
if (u.isFunction(converter)) {
var keyValue = converter(item);
map[keyValue.key] = keyValue.value;
} else if (u.isString(converter)) {
map[k] = item[converter];
} else {
map[k] = item;
}
/**
* 将同构对象的数组转换为按对象中某个键值为键名的对象
*
* 可以定义转换器,来转换输出对象的内容
* `converter`为函数时,接受的参数为输入数组的元素,返回值必须为`{ key: ..., value: ... }`格式,即结果对象的键值对
* `converter`为字符串时,结果对象键值为数组元素对应键名的键值
* `converter`缺失时,结果对象键值为数组元素
*
* 例如:
* `list`为`[ { id: 1, name: 'Thor' }, { id: 2, name: 'Hulk' } ],
* `key`为`id`时,
*
* util.toMap(list, key, function(item) {
* return {
* key: '#' + item.id,
* value: item.name.toUpperCase()
* };
* }) → { '#1': 'THOR', '#2': 'HULK' }
*
* util.toMap(list, key, 'name') → { '1': 'Thor', '2': 'Hulk' }
*
* util.toMap(list, key) → { '1': { id: 1, name: 'Thor' }, '2': { id: 2, name: 'Hulk' } }
*
* @param {Array.<Object>} list 同构对象的数组
* @param {string} key 取对应键值为结果对象的键名
* @param {Function|string} [converter] 转换器
* @return {Object} 转换完毕的对象
*/
util.toMap = function (list, key, converter) {
var i;
var item;
var k;
var map = {};
for (i = list.length; i--;) {
item = list[i];
k = item[key];
if (k != null) {
if (u.isFunction(converter)) {
var keyValue = converter(item);
map[keyValue.key] = keyValue.value;
}
else if (u.isString(converter)) {
map[k] = item[converter];
}
else {
map[k] = item;
}
}
return map;
}
return map;
};
/**
* 根据生成在列表页中操作列中的链接HTML
*
* @param {Object} link 链接配置
* @param {string} [link.className="list-operation"] 链接的className
* @param {string} link.url 链接的目标URL
* @param {string} [link.disabled] 链接是否禁用
* @param {string} [link.target] 链接的target属性
* @param {string} link.text 链接文本
* @param {Object} [link.extra] 附加属性对象,对应kv对会以data-key="value"形式附加到HTML上
* @return {string} 生成的HTML内容
*/
util.genListLink = function (link) {
var defaults = {
className: 'list-operation'
};
util.genListLink = function (link) {
var defaults = {
className: 'list-operation'
};
link = u.defaults(link, defaults);
var attrs = {
href: link.url,
'class': link.className
};
if (link.target && link.target.toLowerCase() !== '_self') {
attrs.target = link.target;
}
link = u.defaults(link, defaults);
attrs = u.map(attrs, function (val, key) {
return key + '="' + u.escape(val) + '"';
});
if (link.disabled) {
return '<span class="' + u.escape(link.className) + ' auth-disabled">'
+ u.escape(link.text) + '</span>';
}
return '<a ' + attrs.join(' ') + '>'
+ u.escape(link.text) + '</a>';
var attrs = {
href: link.url,
'class': link.className
};
util.genListCommand = function (command) {
var defaults = {
tagName: 'span',
className: 'list-operation'
};
command = u.defaults(command, defaults);
var attrs = {
'class': command.className,
'data-command': command.type
};
if (link.target && link.target.toLowerCase() !== '_self') {
attrs.target = link.target;
}
if (command.args != null) {
attrs['data-command-args'] = command.args;
}
attrs = u.map(attrs, function (val, key) {
return key + '="' + u.escape(val) + '"';
if (u.typeOf(link.extra) === 'Object') {
u.each(link.extra, function (val, key) {
attrs['data-' + key] = val;
});
}
var tagName = u.escape(command.tagName);
return '<' + tagName + ' ' + attrs.join(' ') + '>'
attrs = u.map(attrs, function (val, key) {
return key + '="' + u.escape(val) + '"';
});
return '<a ' + attrs.join(' ') + '>'
+ u.escape(link.text) + '</a>';
};
/**
* 根据生成在列表页中操作列中的操作按钮HTML
*
* @param {Object} command 操作配置
* @param {string} [command.className="list-operation"] 操作按钮的className
* @param {string} [command.tagName="span"] 操作按钮的HTML元素类型
* @param {string} command.type 操作按钮点击时触发的事件类型
* @param {string} [command.disabled] 操作按钮是否禁用
* @param {string} [command.args] 操作按钮点击后触发事件所带的参数
* @param {string} command.text 操作按钮显示的文本
* @param {Object} [command.extra] 附加属性对象,对应kv对会以data-key="value"形式附加到HTML上
* @return {string} 生成的HTML内容
*/
util.genListCommand = function (command) {
var defaults = {
tagName: 'span',
className: 'list-operation'
};
command = u.defaults(command, defaults);
var tagName = u.escape(command.tagName);
if (command.disabled) {
return '<' + tagName + ' class="' + u.escape(command.className) + ' auth-disabled">'
+ u.escape(command.text) + '</' + tagName + '>';
}
var attrs = {
'class': command.className,
'data-command': command.type
};
util.genListOperations = function (operations, config) {
config = config || {};
var html = u.map(
operations,
function (operation) {
if (operation.url) {
return util.genListLink(operation);
}
else {
return util.genListCommand(operation);
}
if (typeof command.args !== 'undefined') {
attrs['data-command-args'] = '' + command.args;
}
if (u.typeOf(command.extra) === 'Object') {
u.each(command.extra, function (val, key) {
attrs['data-' + key] = val;
});
}
attrs = u.map(attrs, function (val, key) {
return key + '="' + u.escape(val) + '"';
});
return '<' + tagName + ' ' + attrs.join(' ') + '>'
+ u.escape(command.text) + '</' + tagName + '>';
};
/**
* 生成列表页操作/链接列表的HTML
*
* @param {Array.<Object>} operations 操作/链接配置的数组
* @param {Object} config 列表配置
* @param {string} [config.separator="<span class=\"list-operation-separator\">|</span>"] 列表分隔符
* @return {string} 生成的HTML内容
*/
util.genListOperations = function (operations, config) {
config = config || {};
var html = u.chain(operations)
.map(function (operation) {
if (operation.url) {
return util.genListLink(operation);
}
);
else {
return util.genListCommand(operation);
}
})
.compact()
.value();
return html.join(config.separator || '<span class="list-operation-separator">|</span>');
};
return html.join(config.separator || '');
};
/**
* 下载文件
* @param {string} url 文件地址.
*/
util.download = function (url) {
var divId = '__DownloadContainer__';
var formId = '__DownloadForm__';
var iframeId = '__DownloadIframe__';
var tpl = [
'<form action="${url}" method="post" id="${formId}" ',
'name="${formId}" target="${iframeId}"></form>',
'<iframe src="about:blank" id="${iframeId}" name="${iframeId}">',
'</iframe>'
].join('');
/**
* 下载文件
* @param {string} url 文件地址.
*/
util.download = function (url) {
var divId = '__DownloadContainer__';
var formId = '__DownloadForm__';
var iframeId = '__DownloadIframe__';
/* eslint-disable fecs-indent */
var tpl = [
'<form action="${url}" method="post" id="${formId}" ',
'name="${formId}" target="${iframeId}"></form>',
'<iframe src="about:blank" id="${iframeId}" name="${iframeId}">',
'</iframe>'
].join('');
/* eslint-enable fecs-indent */
function getUrlWithAderId() {
var URI = require('urijs');
var user = require('./system/user');
var aderId = user.ader && user.ader.id
|| URI.parseQuery(document.location.search).aderId;
var query = aderId ? { aderId: aderId } : {};
return URI(url).addQuery(query).toString();
}
function getUrlWithAderId() {
var uri = require('urijs');
var user = require('./system/user');
var aderId = user.ader && user.ader.id
|| uri.parseQuery(document.location.search).aderId;
var query = aderId ? {aderId: aderId} : {};
return uri(url).addQuery(query).toString();
}
function getDownloadContainer() {
var div = document.getElementById(divId);
if (!div) {
div = document.createElement('div');
div.id = divId;
div.style.display = 'none';
document.body.appendChild(div);
}
return div;
function getDownloadContainer() {
var div = document.getElementById(divId);
if (!div) {
div = document.createElement('div');
div.id = divId;
div.style.display = 'none';
document.body.appendChild(div);
}
return div;
}
var ctner = getDownloadContainer();
var render = require('etpl').compile(tpl);
ctner.innerHTML = render({
url: getUrlWithAderId(url),
formId: formId,
iframeId: iframeId
});
document.getElementById(formId).submit();
};
var ctner = getDownloadContainer();
var render = require('etpl').compile(tpl);
ctner.innerHTML = render({
url: getUrlWithAderId(url),
formId: formId,
iframeId: iframeId
});
document.getElementById(formId).submit();
};
return util;
}
);
return util;
});

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc