bat-ria
Version:
RIA extension for Brand Ads Team
361 lines (321 loc) • 12.1 kB
JavaScript
/**
* Copyright 2014 Baidu Inc. All rights reserved.
*
* @ignore
* @file BAT工具模块
* @author Justineo
*/
define(function (require) {
var u = require('underscore');
var moment = require('moment');
var io = require('./io/serverIO');
/**
* 工具模块
*
* @singleton
*/
var util = {};
/**
* 根据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;
}
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;
}
};
/**
* 生成时间段数据
*
* 未指定`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) {
// 只有一个参数时,认为是options
if (arguments.length === 1) {
options = begin;
}
var defaults = {
inputFormat: 'YYYYMMDDHHmmss',
outputFormat: 'Date'
};
options = u.defaults({}, options, defaults);
// 解析输入,没有则使用默认时间
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');
// 默认前七天
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'
};
return u.mapKey(
{
begin: begin,
end: end
},
{
begin: keys.begin,
end: keys.end
}
);
};
/**
* 将同构对象的数组转换为按对象中某个键值为键名的对象
*
* 可以定义转换器,来转换输出对象的内容
* `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;
};
/**
* 根据生成在列表页中操作列中的链接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'
};
link = u.defaults(link, defaults);
if (link.disabled) {
return '<span class="' + u.escape(link.className) + ' auth-disabled">'
+ u.escape(link.text) + '</span>';
}
var attrs = {
href: link.url,
'class': link.className
};
if (link.target && link.target.toLowerCase() !== '_self') {
attrs.target = link.target;
}
if (u.typeOf(link.extra) === 'Object') {
u.each(link.extra, function (val, key) {
attrs['data-' + key] = val;
});
}
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
};
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 || '');
};
/**
* 下载文件
* @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 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();
};
return util;
});