Files
links/patches/public/assets/js/backend/split/number.js
T

524 lines
26 KiB
JavaScript
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: function () {
Table.api.init({
extend: {
index_url: 'split.number/index' + location.search,
add_url: 'split.number/add',
edit_url: 'split.number/edit',
del_url: 'split.number/del',
multi_url: 'split.number/multi',
table: 'split_number',
}
});
var table = $("#table");
var searchSelect = Controller.api.searchSelectColumn;
var searchSelectMeta = Controller.api.searchSelectMeta;
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
sortOrder: 'desc',
fixedColumns: true,
fixedRightNumber: 1,
searchFormVisible: true,
columns: [
[
{checkbox: true},
searchSelect('split_link_id', __('Link_url'), Config.splitLinkFilterList || {}, true),
{field: 'id', title: __('Id'), sortable: true},
{
field: 'link_url_text',
title: __('Link_url'),
operate: false,
formatter: Table.api.formatter.content
},
{field: 'ticket_name', title: __('Ticket_name'), operate: 'LIKE'},
{
field: 'number',
title: __('Number'),
operate: 'LIKE',
formatter: Controller.api.formatter.numberWithDeferred
},
$.extend(
{field: 'number_type', title: __('Number_type'), searchList: Config.numberTypeList, formatter: Table.api.formatter.normal},
searchSelectMeta(false)
),
{field: 'visit_count', title: __('Visit_count'), operate: false, sortable: true},
{field: 'inbound_count', title: __('Inbound_count'), operate: false, sortable: true},
$.extend(
{field: 'platform_status', title: __('Platform_status'), searchList: Config.platformStatusList, formatter: Controller.api.formatter.platformStatus},
searchSelectMeta(false)
),
$.extend(
{field: 'status', title: __('Status'), searchList: Config.statusList, formatter: Table.api.formatter.toggle, yes: 'normal', no: 'hidden'},
searchSelectMeta(false)
),
$.extend(
{
field: 'ratio_deferred',
title: __('Ratio_deferred'),
visible: false,
searchable: true,
operate: '=',
searchList: Config.ratioDeferredList || {}
},
searchSelectMeta(false)
),
{
field: 'createtime',
title: __('Createtime'),
operate: 'RANGE',
addclass: 'datetimerange',
autocomplete: false,
formatter: Table.api.formatter.datetime,
sortable: true
},
{
field: 'operate',
title: __('Operate'),
table: table,
events: Table.api.events.operate,
formatter: Table.api.formatter.operate
}
]
]
});
table.on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table', function () {
var ids = Table.api.selectedids(table);
$('.btn-batch-update-status').toggleClass('btn-disabled disabled', ids.length === 0);
});
$('.btn-batch-update-status').on('click', function (e) {
e.preventDefault();
e.stopPropagation();
if ($(this).hasClass('disabled')) {
return false;
}
var ids = Table.api.selectedids(table);
if (!ids.length) {
Toastr.warning(__('Please select at least one item'));
return false;
}
Controller.api.openBatchUpdateModal(ids, table);
});
$('.btn-batch-operate').on('click', function (e) {
e.preventDefault();
e.stopPropagation();
Controller.api.openBatchOperateModal(table);
});
table.on('post-body.bs.table', function () {
table.find('[data-toggle="tooltip"]').tooltip({container: 'body'});
});
table.on('post-common-search.bs.table', function (e, tbl) {
Controller.api.initCommonSearchSelectpicker(tbl);
});
Table.api.bindevent(table);
Controller.api.bindDeferredFilter(table);
Controller.api.bindDeferredCleanup(table);
},
add: function () {
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
searchSelectColumn: function (field, title, searchList, liveSearch) {
return {
field: field,
title: title,
visible: false,
searchList: searchList || {},
operate: '=',
addclass: 'selectpicker',
extend: Controller.api.searchSelectExtend(liveSearch !== false)
};
},
searchSelectMeta: function (liveSearch) {
return {
addclass: 'selectpicker',
extend: Controller.api.searchSelectExtend(liveSearch !== false)
};
},
searchSelectExtend: function (liveSearch) {
var text = __('Please select');
if (!text || text === 'Please select' || text === 'Please Select') {
text = '请选择';
}
var ext = 'data-none-selected-text="' + text + '" title="' + text + '"';
if (liveSearch) {
ext += ' data-live-search="true"';
}
return ext;
},
initCommonSearchSelectpicker: function (tbl) {
var $form = $('form.form-commonsearch', tbl.$container);
if ($form.length) {
Form.events.selectpicker($form);
}
},
formatter: {
platformStatus: function (value, row) {
var text = row.platform_status_text != null && row.platform_status_text !== ''
? String(row.platform_status_text)
: (Config.platformStatusList && Config.platformStatusList[value] ? Config.platformStatusList[value] : value);
var cls = value === 'online' ? 'success' : (value === 'offline' ? 'default' : 'warning');
return '<span class="text-' + cls + '">' + Fast.api.escape(text || '') + '</span>';
},
isRatioDeferred: function (row) {
return parseInt(row.ratio_deferred, 10) === 1 && String(row.status || '') === 'normal';
},
ratioDeferredTooltip: function (row) {
var streak = parseInt(row.no_inbound_click_streak, 10) || 0;
var template = __('Ratio deferred tooltip');
if (!template || template === 'Ratio deferred tooltip') {
template = '连续 %s 次访问无进线增长,已触线下号比率,选号已后置,等待同步裁决';
}
return template.indexOf('%s') >= 0 ? template.replace('%s', String(streak)) : template;
},
ratioDeferredBadgeHtml: function (tooltip) {
var label = __('Ratio deferred badge');
if (!label || label === 'Ratio deferred badge') {
label = '降权中';
}
return '<span class="label label-warning split-ratio-deferred-badge" style="margin-left:6px;font-size:11px;font-weight:500;vertical-align:middle;"'
+ ' data-toggle="tooltip" data-placement="top" title="' + Fast.api.escape(tooltip) + '">'
+ '<i class="fa fa-level-down"></i> ' + Fast.api.escape(label)
+ '</span>';
},
numberWithDeferred: function (value, row) {
var html = Fast.api.escape(String(value || ''));
if (Controller.api.formatter.isRatioDeferred(row)) {
html += Controller.api.formatter.ratioDeferredBadgeHtml(
Controller.api.formatter.ratioDeferredTooltip(row)
);
}
return html;
}
},
refreshSearchSelect: function ($field) {
if ($field.length && $field.hasClass('selectpicker') && $field.data('selectpicker')) {
$field.selectpicker('refresh');
}
},
syncStatusTabs: function (table, statusValue) {
var $tabs = table.closest('.panel-intro').find('.panel-heading [data-field="status"]');
if (!$tabs.length) {
return;
}
$tabs.find('li').removeClass('active');
$tabs.find('li a[data-value="' + (statusValue === null || statusValue === undefined ? '' : statusValue) + '"]')
.parent()
.addClass('active');
},
/**
* 工具栏「降权中」快捷筛选:与列表徽章一致(ratio_deferred=1 且 status=normal
*/
bindDeferredFilter: function (table) {
var active = false;
var savedStatus = '';
var $btn = $('.btn-filter-ratio-deferred');
if (!$btn.length) {
return;
}
var applyFilter = function () {
var $form = table.closest('.bootstrap-table').find('form.form-commonsearch');
if (!$form.length) {
return false;
}
var $ratioField = $form.find('[name="ratio_deferred"]');
var $statusField = $form.find('[name="status"]');
if (active) {
savedStatus = $statusField.length ? String($statusField.val() || '') : '';
if ($ratioField.length) {
$ratioField.val('1');
Controller.api.refreshSearchSelect($ratioField);
}
if ($statusField.length) {
$statusField.val('normal');
Controller.api.refreshSearchSelect($statusField);
}
Controller.api.syncStatusTabs(table, 'normal');
} else {
if ($ratioField.length) {
$ratioField.val('');
Controller.api.refreshSearchSelect($ratioField);
}
if ($statusField.length) {
$statusField.val(savedStatus);
Controller.api.refreshSearchSelect($statusField);
}
Controller.api.syncStatusTabs(table, savedStatus);
savedStatus = '';
}
table.trigger('uncheckbox');
$form.trigger('submit');
return true;
};
$btn.on('click', function (e) {
e.preventDefault();
active = !active;
$btn.toggleClass('btn-warning', active).toggleClass('btn-default', !active);
if (!applyFilter()) {
active = !active;
$btn.toggleClass('btn-warning', active).toggleClass('btn-default', !active);
Toastr.warning('筛选表单未就绪,请刷新页面后重试');
}
});
},
/**
* 清理无效降权池:无落地页访问基线却标记 ratio_deferred=1 的号码
*/
bindDeferredCleanup: function (table) {
var $btn = $('.btn-cleanup-ratio-deferred');
if (!$btn.length) {
return;
}
$btn.on('click', function (e) {
e.preventDefault();
Fast.api.ajax({
url: 'split.number/cleanupdeferredpreview',
type: 'get'
}, function (data) {
var count = parseInt(data.count, 10) || 0;
if (count <= 0) {
Toastr.info(__('Ratio deferred cleanup none'));
return false;
}
var template = __('Ratio deferred cleanup confirm');
if (!template || template === 'Ratio deferred cleanup confirm') {
template = '将清除 %d 条无效降权记录。确定继续?';
}
var message = template.indexOf('%d') >= 0
? template.replace('%d', String(count))
: template;
Layer.confirm(message, {icon: 3, title: __('Warning')}, function (index) {
Layer.close(index);
Fast.api.ajax({
url: 'split.number/cleanupdeferred',
type: 'post'
}, function (data, ret) {
table.bootstrapTable('refresh');
Toastr.success(ret.msg || __('Ratio deferred cleanup success'));
});
});
return false;
});
});
},
bindevent: function () {
Form.api.bindevent($('form[role=form]'));
Controller.api.fixSelectPlaceholder();
Controller.api.bindNumberTypeToggle();
},
fixSelectPlaceholder: function () {
var text = __('Please select');
if (!text || text === 'Please select' || text === 'Please Select') {
text = '请选择';
}
$('#c-split_link_id').each(function () {
var $el = $(this);
$el.attr({'data-none-selected-text': text, 'title': text});
$el.find('option[value=""]').first().text(text);
if ($el.data('selectpicker')) {
$el.selectpicker('render');
}
});
},
bindNumberTypeToggle: function () {
var $type = $('#c-number_type');
var $wrap = $('.split-number-type-custom');
var $custom = $('#c-number_type_custom');
if (!$type.length) {
return;
}
var toggle = function () {
var val = $type.val();
if (val === 'custom') {
$wrap.removeClass('hide');
$custom.attr('data-rule', 'required');
} else {
$wrap.addClass('hide');
$custom.removeAttr('data-rule');
if (!$wrap.closest('form').attr('id') || $('#edit-form').length === 0) {
$custom.val('');
}
}
};
$type.on('changed.bs.select change', toggle);
toggle();
},
openBatchUpdateModal: function (ids, table) {
var statusHtml = '';
$.each(Config.statusList || {}, function (key, label) {
var checked = key === 'normal' ? ' checked' : '';
statusHtml += '<label class="radio-inline"><input type="radio" name="batch_status" value="' + key + '"' + checked + '> ' + label + '</label>';
});
var manualHtml = '';
$.each(Config.manualManageList || {}, function (key, label) {
var checked = key === '0' ? ' checked' : '';
manualHtml += '<label class="radio-inline"><input type="radio" name="batch_manual_manage" value="' + key + '"' + checked + '> ' + label + '</label>';
});
var html = [
'<div class="split-batch-update-modal" style="padding:18px 22px;">',
' <div class="form-group">',
' <label class="control-label">' + __('Batch selected count') + '</label>',
' <p class="form-control-static" style="font-size:18px;font-weight:600;margin:0;">' + ids.length + ' ' + __('Unit count') + '</p>',
' </div>',
' <div class="form-group">',
' <label class="control-label">' + __('Status') + '</label>',
' <div>' + statusHtml + '</div>',
' </div>',
' <div class="form-group" style="margin-bottom:0;">',
' <label class="control-label">' + __('Manual_manage') + '</label>',
' <div>' + manualHtml + '</div>',
' </div>',
'</div>'
].join('');
Layer.open({
type: 1,
title: __('Batch update title'),
area: ['420px', 'auto'],
shadeClose: false,
content: html,
btn: [__('OK'), __('Cancel')],
yes: function (index, layero) {
var status = layero.find('input[name="batch_status"]:checked').val();
var manualManage = layero.find('input[name="batch_manual_manage"]:checked').val();
if (typeof status === 'undefined' || typeof manualManage === 'undefined') {
Toastr.error(__('Invalid parameters'));
return false;
}
Fast.api.ajax({
url: 'split.number/batchupdate',
type: 'post',
data: {
ids: ids.join(','),
status: status,
manual_manage: manualManage
}
}, function () {
Layer.close(index);
table.bootstrapTable('refresh');
$('.btn-batch-update-status').addClass('btn-disabled disabled');
Toastr.success(__('Batch update success'));
});
return false;
}
});
},
openBatchOperateModal: function (table) {
var pleaseSelect = __('Please select');
if (!pleaseSelect || pleaseSelect === 'Please select' || pleaseSelect === 'Please Select') {
pleaseSelect = '请选择';
}
var linkOptions = ['<option value="">' + Fast.api.escape(pleaseSelect) + '</option>'];
$.each(Config.splitLinkSelectList || {}, function (id, label) {
linkOptions.push('<option value="' + Fast.api.escape(String(id)) + '">' + Fast.api.escape(String(label)) + '</option>');
});
var html = [
'<div class="split-batch-operate-modal" style="padding:18px 22px;">',
' <div class="form-group">',
' <label class="control-label">' + __('Link_url') + '<span class="text-danger">*</span></label>',
' <select id="batch-operate-split-link" class="form-control selectpicker" data-live-search="true" data-none-selected-text="' + pleaseSelect + '" title="' + pleaseSelect + '">',
linkOptions.join(''),
' </select>',
' </div>',
' <div class="form-group">',
' <label class="control-label">' + __('Number') + '<span class="text-danger">*</span></label>',
' <textarea id="batch-operate-numbers" class="form-control" rows="8" placeholder="' + Fast.api.escape(__('Numbers one per line')) + '"></textarea>',
' </div>',
' <div class="form-group">',
' <label class="control-label">' + __('Batch operate action') + '<span class="text-danger">*</span></label>',
' <select id="batch-operate-action" class="form-control selectpicker" data-none-selected-text="' + pleaseSelect + '" title="' + pleaseSelect + '">',
' <option value="enable">' + Fast.api.escape(__('Batch operate enable')) + '</option>',
' <option value="disable">' + Fast.api.escape(__('Batch operate disable')) + '</option>',
' <option value="delete">' + Fast.api.escape(__('Batch operate delete')) + '</option>',
' </select>',
' </div>',
' <div class="form-group" style="margin-bottom:0;text-align:right;">',
' <button type="button" class="btn btn-primary btn-batch-operate-confirm">' + __('OK') + '</button> ',
' <button type="button" class="btn btn-default btn-batch-operate-cancel">' + __('Cancel') + '</button>',
' </div>',
'</div>'
].join('');
var layerIndex = Layer.open({
type: 1,
title: __('Batch operate title'),
area: ['520px', 'auto'],
shadeClose: false,
content: html,
success: function (layero, index) {
Form.events.selectpicker(layero);
layero.find('.btn-batch-operate-cancel').on('click', function () {
Layer.close(index);
});
layero.find('.btn-batch-operate-confirm').on('click', function () {
var splitLinkId = $.trim(layero.find('#batch-operate-split-link').val());
var numbers = $.trim(layero.find('#batch-operate-numbers').val());
var action = $.trim(layero.find('#batch-operate-action').val());
if (!splitLinkId) {
Toastr.warning(__('Please select split link'));
return false;
}
if (!numbers) {
Toastr.warning(__('Please fill at least one number'));
return false;
}
if (!action) {
Toastr.error(__('Invalid batch operate action'));
return false;
}
var submit = function () {
Fast.api.ajax({
url: 'split.number/batchoperate',
type: 'post',
data: {
split_link_id: splitLinkId,
numbers: numbers,
action: action
}
}, function (data, ret) {
Layer.close(index);
table.bootstrapTable('refresh');
Toastr.success(ret.msg || __('Batch operate success'));
});
};
if (action === 'delete') {
Layer.confirm(__('Batch operate delete confirm'), {icon: 3, title: __('Warning')}, function (confirmIndex) {
Layer.close(confirmIndex);
submit();
});
return false;
}
submit();
return false;
});
}
});
}
}
};
return Controller;
});