478 lines
14 KiB
JavaScript
478 lines
14 KiB
JavaScript
var filterValues = {};
|
||
|
||
/**
|
||
* Listen filter change.
|
||
*
|
||
* @param string field
|
||
* @param string dateSelect
|
||
* @param string $filterValue
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function filterChange(field, dateSelect, $filterValue)
|
||
{
|
||
var parse = field.split('.');
|
||
|
||
field = parse[0];
|
||
var type = '';
|
||
if(parse.length == 2) type = parse[1];
|
||
var id = type.length == 0 ? field : field + '\\[' + type + '\\]';
|
||
var value = $('#' + id).val();
|
||
|
||
if(type.length == 0)
|
||
{
|
||
filterValues[field] = value;
|
||
ajaxGetChart();
|
||
}
|
||
else
|
||
{
|
||
var check = checkDate(dateSelect, $filterValue);
|
||
if(!check) return;
|
||
if(!filterValues[field]) filterValues[field] = {begin: '', end: ''};
|
||
|
||
filterValues[field][type] = value;
|
||
|
||
var begin = filterValues[field].begin;
|
||
var end = filterValues[field].end;
|
||
if((begin.length > 0 && end.length > 0) || (begin.length == 0 && end.length == 0)) ajaxGetChart();
|
||
}
|
||
}
|
||
/**
|
||
* Ajax get pivot data.
|
||
*
|
||
* @access public
|
||
* @return bool
|
||
*/
|
||
function ajaxGetChart()
|
||
{
|
||
/* If the same value is detected for the x and y axes, throw error and clear the echart, then return.*/
|
||
/* 如果x轴和y轴重复了,那么抛出错误并返回。*/
|
||
if(!checkFormSetting()) return;
|
||
|
||
var chartParams = JSON.parse(JSON.stringify(DataStorage.pivot));
|
||
chartParams.filterValues = filterValues;
|
||
|
||
/* Redraw echart. */
|
||
/* 拿数据并重绘图表。*/
|
||
$.post(createLink('pivot', 'ajaxGetChart'), chartParams, function(resp)
|
||
{
|
||
var data = JSON.parse(resp);
|
||
echart.clear();
|
||
echart.setOption(data, true);
|
||
});
|
||
}
|
||
|
||
function getQueryFilters(pivot)
|
||
{
|
||
var filters = '';
|
||
filters = pivot.filters;
|
||
|
||
filters.forEach(function(filter, index)
|
||
{
|
||
if(filter.from == 'query')
|
||
{
|
||
var find = $('#queryFilters').find('.filter-item-' + index + ' .form-' + filter.type);
|
||
if(find.length != 0) filter.default = find.val();
|
||
}
|
||
});
|
||
|
||
return filters;
|
||
}
|
||
|
||
/**
|
||
* If the same value is detected for the x and y axias, throw error and clear the echart, then return.
|
||
*
|
||
* @access public
|
||
* @return bool ture|false
|
||
*/
|
||
function checkFormSetting()
|
||
{
|
||
var pivot = DataStorage.pivot;
|
||
var type = pivot.settings[0].type;
|
||
var result = 'success';
|
||
var errorMsg = '';
|
||
if(checkForm[type])
|
||
{
|
||
for(var key in checkForm[type])
|
||
{
|
||
var fields = checkForm[type][key].split(',');
|
||
var former = fields[0];
|
||
var latter = fields[1];
|
||
|
||
if(key == 'cantequal')
|
||
{
|
||
if(pivot.settings[0][latter].includes(pivot.settings[0][former]))
|
||
{
|
||
result = 'fail';
|
||
errorMsg = pivotLang['errorList']['cantequal'];
|
||
errorMsg = errorMsg.replace(/%s/, pivotLang[type][latter]);
|
||
errorMsg = errorMsg.replace(/%s/, pivotLang[type][former]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if(result == 'fail')
|
||
{
|
||
var message = new $.zui.Messager(errorMsg,
|
||
{
|
||
html: true,
|
||
icon: 'exclamation-sign',
|
||
type: 'danger',
|
||
close: true,
|
||
});
|
||
|
||
message.show();
|
||
|
||
echart.clear();
|
||
return false;
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
/**
|
||
* Validate form required.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function validate(showError = false)
|
||
{
|
||
var pivot = DataStorage.pivot;
|
||
var formSettings = pivot.settings;
|
||
var isReady = true;
|
||
var firstErrDom = null;
|
||
|
||
if("summary" in formSettings && formSettings.summary == 'notuse')
|
||
{
|
||
if(isReady) $('#datagrid-tip').addClass('hidden');
|
||
return true;
|
||
}
|
||
|
||
/* check group settings. */
|
||
var exist = false;
|
||
for(var key in formSettings)
|
||
{
|
||
if(key.indexOf('group') != '-1' && formSettings[key].length > 0) exist = true;
|
||
}
|
||
|
||
var tr = $('#step2Content form#groupForm table tbody tr:nth-child(1)');
|
||
tr.find('#groupLabel').remove();
|
||
tr.find('#group1').removeClass('has-error');
|
||
|
||
if(!exist)
|
||
{
|
||
isReady = false;
|
||
|
||
if(showError)
|
||
{
|
||
var error = '<div id="groupLabel" class="text-danger help-text">' + moreThanOneLang + '</div>';
|
||
tr.find('#group1').addClass('has-error');
|
||
tr.find('#group1').next().after(error);
|
||
|
||
firstErrDom = tr.find('#group1').parents('tr');
|
||
}
|
||
}
|
||
|
||
/* check columns settings. */
|
||
formSettings.columns.forEach(function(value, index)
|
||
{
|
||
var $column = $('#step2Content form#columnForm .column-' + index);
|
||
$column.find('#column' + index + 'Label').remove();
|
||
$column.find('#stat' + index + 'Label').remove();
|
||
$column.find('#column').removeClass('has-error');
|
||
$column.find('#stat').removeClass('has-error');
|
||
|
||
if(!value.field || value.field.length == 0)
|
||
{
|
||
isReady = false;
|
||
if(showError)
|
||
{
|
||
var error = '<div id="column' + index + 'Label" class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang.step2.columnField) + '</div>';
|
||
$column.find('#column').addClass('has-error');
|
||
$column.find('#column').parent().after(error);
|
||
|
||
if(!firstErrDom) firstErrDom = $column.find('#column').parents('.column');
|
||
}
|
||
}
|
||
|
||
if(value.showOrigin != '1' && (!value.stat || value.stat.length == 0 || value.stat === ''))
|
||
{
|
||
isReady = false;
|
||
if(showError)
|
||
{
|
||
var error = '<div id="stat' + index + 'Label" class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang.step2.calcMode) + '</div>';
|
||
$column.find('#stat').addClass('has-error');
|
||
$column.find('#stat').next().after(error);
|
||
|
||
if(!firstErrDom) firstErrDom = $column.find('#stat').parents('.column');
|
||
}
|
||
}
|
||
});
|
||
|
||
if(isReady) $('#datagrid-tip').addClass('hidden');
|
||
if(!isReady && firstErrDom) firstErrDom[0].scrollIntoView({ behavior: 'smooth', block: 'nearest', inline: 'start' })
|
||
return isReady;
|
||
}
|
||
|
||
/**
|
||
* Multi Validate.
|
||
*
|
||
* @param setting $setting
|
||
* @param showError $showError
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function multiValidate(setting, showError)
|
||
{
|
||
var pivot = DataStorage.pivot;
|
||
var type = pivot.settings[0].type;
|
||
var isReady = true;
|
||
var field = setting.field;
|
||
var error = '<div id="' + field + 'Label"' + ' class="text-danger help-text">' + notemptyLang.replace('%s', pivotLang[type][field]) + '</div>';
|
||
$('#pivotForm .table-form').find('.multi-' + field).each(function()
|
||
{
|
||
$(this).parent('td').find('#' + field + 'Label').remove();
|
||
$(this).parent('td').find('#' + field + '_chosen a').removeClass('has-error');
|
||
|
||
if(setting.required && $(this).val().length == 0)
|
||
{
|
||
isReady = false;
|
||
if(showError)
|
||
{
|
||
$(this).parent('td').find('#' + field + '_chosen a').addClass('has-error');
|
||
$(this).parent('td').find('#' + field + '_chosen').after(error);
|
||
}
|
||
}
|
||
});
|
||
|
||
return isReady;
|
||
}
|
||
|
||
/**
|
||
* Check date.
|
||
*
|
||
* @param string dateSelect
|
||
* @param object $filterValue
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function checkDate(dateSelect, $filterValue)
|
||
{
|
||
var begin = new Date($(dateSelect).parent().find('.default-begin').val().replace(/-/g, "\/")).getTime();
|
||
var end = new Date($(dateSelect).parent().find('.default-end').val().replace(/-/g, "\/")).getTime();
|
||
if(begin > end)
|
||
{
|
||
$(dateSelect).val('');
|
||
if(typeof $filterValue == 'object') $filterValue.val('');
|
||
bootbox.alert(pivotLang.beginGtEnd);
|
||
return false;
|
||
}
|
||
return true;
|
||
}
|
||
|
||
function waitForRepaint(callback)
|
||
{
|
||
window.requestAnimationFrame(function()
|
||
{
|
||
window.requestAnimationFrame(callback);
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Init picker.
|
||
*
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function initPicker($row, pickerName = 'picker-select', onready = false)
|
||
{
|
||
$row.find('.' + pickerName).picker(
|
||
{
|
||
maxDropHeight: pickerHeight,
|
||
onReady: function()
|
||
{
|
||
if(!onready) return;
|
||
if(!$row.find('.picker')) return;
|
||
if(window.getComputedStyle($row.find('.picker').find('.picker-selections')[0]).getPropertyValue('width') !== 'auto')
|
||
{
|
||
var pickerWidth = $row.find('.picker')[0].getBoundingClientRect().width;
|
||
$row.find('.picker').find('.picker-selections').css('width', pickerWidth);
|
||
}
|
||
}
|
||
});
|
||
$row.find("." + pickerName).each(function(index)
|
||
{
|
||
if($(this).hasClass('required')) $(this).siblings("div .picker").addClass('required');
|
||
});
|
||
}
|
||
|
||
/**
|
||
* Init datapicker.
|
||
*
|
||
* @param object $obj
|
||
* @param function callback
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function initDatepicker($obj, callback)
|
||
{
|
||
$obj.find('.form-date').datepicker();
|
||
$obj.find('.form-datetime').datetimepicker();
|
||
if(typeof callback == 'function') callback($obj);
|
||
}
|
||
|
||
/**
|
||
* Attr date check.
|
||
*
|
||
* @param object $obj
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function attrDateCheck($obj)
|
||
{
|
||
$obj.find('.form-date').attr('onchange', 'checkDate(this, this.value)');
|
||
$obj.find('.form-datetime').attr('onchange', 'checkDate(this, this.value)');
|
||
}
|
||
|
||
/**
|
||
* Export file.
|
||
*
|
||
* @param object $domObj
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function exportFile($domObj)
|
||
{
|
||
if(typeof $domObj == 'undefined') return;
|
||
|
||
var fileName = $('#fileName').val().trim() ? $('#fileName').val().trim() : untitled;
|
||
var fileType = $('#fileType').val();
|
||
var tableName = fileName + '.' + fileType;
|
||
|
||
if(fileType == 'xlsx' || fileType == 'xls')
|
||
{
|
||
const new_sheet = XLSX.utils.table_to_book($domObj, {raw: true});
|
||
XLSX.writeFile(new_sheet, tableName);
|
||
}
|
||
else if(fileType == 'html' || fileType == 'mht')
|
||
{
|
||
const htmlContent = $domObj.outerHTML;
|
||
|
||
const $temp = $('<div>').html(htmlContent);
|
||
$temp.find('*').removeAttr('style');
|
||
$temp.find('*').removeAttr('class');
|
||
$temp.find('*').removeAttr('data-flex');
|
||
$temp.find('*').removeAttr('data-width');
|
||
$temp.find('*').removeAttr('data-type');
|
||
$temp.find('*').removeAttr('data-fixed-left-width');
|
||
const cleanTableHTML = $temp.html();
|
||
|
||
var head = '<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
|
||
var style = '<style>table, th, td {font-size: 12px; border: 1px solid gray; border-collapse: collapse;}table th, table td {padding: 5px;}</style>';
|
||
var title = '<title>' + fileName + '</title></head>';
|
||
var body = '<body>' + cleanTableHTML + '</body>';
|
||
const finalHTML = head + style + title + body;
|
||
|
||
if(fileType == 'html')
|
||
{
|
||
const blob = new Blob([finalHTML], { type: 'text/html;charset=utf-8' });
|
||
saveAs(blob, tableName);
|
||
}
|
||
else if(fileType == 'mht')
|
||
{
|
||
const data = {html: finalHTML, fileName: fileName};
|
||
$.post(createLink('file', 'ajaxExport2mht'), data, function(resp)
|
||
{
|
||
const blob = new Blob([resp], { type: "application/x-mimearchive" });
|
||
saveAs(blob, tableName);
|
||
});
|
||
}
|
||
}
|
||
$('#export').modal('hide');
|
||
}
|
||
|
||
/**
|
||
* Zui messager alert.
|
||
*
|
||
* @param string result success|fail
|
||
* @param string mes
|
||
* @access public
|
||
* @return void
|
||
*/
|
||
function zuiMessage(result, mes)
|
||
{
|
||
var icon = result == 'success' ? 'check-circle' : 'exclamation-sign';
|
||
var type = result == 'success' ? 'success' : 'danger';
|
||
|
||
var message = new $.zui.Messager(mes,
|
||
{
|
||
html: true,
|
||
icon: icon,
|
||
type: type,
|
||
close: true,
|
||
});
|
||
|
||
message.show();
|
||
}
|
||
|
||
function select(name, options, selected, attrib, callback)
|
||
{
|
||
var type = 'option';
|
||
if(!Array.isArray(options))
|
||
{
|
||
type = options;
|
||
options = [];
|
||
}
|
||
$.post(createLink('pivot', 'ajaxGetSelect'),
|
||
{
|
||
name: name,
|
||
type: type,
|
||
selectedItems: selected,
|
||
attrib: attrib,
|
||
options: options
|
||
}, function(resp)
|
||
{
|
||
if(typeof callback == 'function') callback(resp);
|
||
});
|
||
}
|
||
|
||
function setDateField(control)
|
||
{
|
||
var $period = $('#selectPeriod');
|
||
if(!$period.length)
|
||
{
|
||
$period = $("<ul id='selectPeriod' class='dropdown-menu'><li><a href='#MONDAY'>" + datepickerText.TEXT_WEEK_MONDAY + "</a></li><li><a href='#SUNDAY'>" + datepickerText.TEXT_WEEK_SUNDAY + "</a></li><li><a href='#MONTHBEGIN'>" + datepickerText.TEXT_MONTH_BEGIN + "</a></li><li><a href='#MONTHEND'>" + datepickerText.TEXT_MONTH_END + "</a></li></ul>").appendTo('body');
|
||
$period.find('li > a').click(function(event)
|
||
{
|
||
var target = control.parents('table, #queryFilters, #filterItems,#filterForm').find('[data-index="' + $period.attr('data-index') + '"]').find('#default:visible');
|
||
if(target.length)
|
||
{
|
||
target.val($(this).attr('href').replace('#', '$')).trigger('change');
|
||
$period.hide();
|
||
}
|
||
event.stopPropagation();
|
||
return false;
|
||
});
|
||
}
|
||
|
||
if(control.hasClass('form-date')) control.datepicker();
|
||
if(control.hasClass('form-datetime')) control.datetimepicker();
|
||
|
||
var dateVal = control.val();
|
||
control.val('').datetimepicker('update').trigger('mousedown');
|
||
control.val(dateVal);
|
||
|
||
control.on('show', function(e)
|
||
{
|
||
var $e = $(e.target);
|
||
var ePos = $e.offset();
|
||
$period.css({'left': ePos.left + 210, 'top': ePos.top + 29, 'min-height': $('.datetimepicker').outerHeight(), 'z-index': 1110}).show().attr('data-index', $e.parents('.filter-item, .filter').data('index')).find('li.active').removeClass('active');
|
||
$period.find("li > a[href='" + $e.val().replace('$', '#') + "']").closest('li').addClass('active');
|
||
}).on('changeDate', function()
|
||
{
|
||
$period.hide();
|
||
}).on('hide', function(){setTimeout(function(){$period.hide();}, 200);});
|
||
}
|