Files
links/public/assets/js/backend/split/number.js
T
2026-07-05 23:40:13 +08:00

1038 lines
48 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,
pageSize: 10,
pageList: Controller.api.streamLoad.PAGE_LIST,
queryParams: function (params) {
return Controller.api.streamLoad.wrapQueryParams(table, params);
},
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: Controller.api.buildRatioDeferredSearchList()
},
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.streamLoad.bind(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;
},
/**
* PHP json_encode 会把 ['0'=>..,'1'=>..] 压成数组,FastAdmin 通用搜索会误用文案作 option value
*/
buildRatioDeferredSearchList: function () {
var list = Config.ratioDeferredList;
if ($.isArray(list)) {
return {0: list[0], 1: list[1]};
}
return list || {};
},
initCommonSearchSelectpicker: function (tbl) {
var $form = $('form.form-commonsearch', tbl.$container);
if ($form.length) {
Form.events.selectpicker($form);
}
},
/**
* 分页选「全部」时改为分块滚动加载,避免一次渲染过多 DOM 导致卡顿
*/
streamLoad: {
CHUNK: 50,
SCROLL_THRESHOLD: 80,
LOAD_DELAY: 1500,
PAGE_LIST: [10, 30, 50, 100, 200, 300, 500, 'All'],
createState: function () {
return {
enabled: false,
loading: false,
pendingLoad: false,
loadTimer: null,
loaded: 0,
total: 0,
chunk: 50,
pendingReset: false,
pendingAllSelect: false,
appendQuery: false
};
},
getState: function (table) {
var state = table.data('splitStreamLoad');
if (!state) {
state = Controller.api.streamLoad.createState();
table.data('splitStreamLoad', state);
}
return state;
},
getAllLabel: function () {
var localeKey = (typeof Config !== 'undefined' && Config.language === 'zh-cn') ? 'zh-CN' : 'en-US';
var locale = $.fn.bootstrapTable.locales && $.fn.bootstrapTable.locales[localeKey];
if (locale && typeof locale.formatAllRows === 'function') {
return locale.formatAllRows();
}
if ($.fn.bootstrapTable.defaults && typeof $.fn.bootstrapTable.defaults.formatAllRows === 'function') {
return $.fn.bootstrapTable.defaults.formatAllRows();
}
return 'All';
},
/**
* initServer 首次请求时实例尚未写入 data('bootstrap.table')getOptions 会退回 jQuery 对象
*/
safeGetOptions: function (table) {
if (!table || !table.length) {
return null;
}
var opts = table.bootstrapTable('getOptions');
if (opts && typeof opts.formatAllRows === 'function') {
return opts;
}
var instance = table.data('bootstrap.table');
if (instance && instance.options && typeof instance.options.formatAllRows === 'function') {
return instance.options;
}
return null;
},
getDefaultPageList: function () {
return Controller.api.streamLoad.PAGE_LIST;
},
getMaxNormalPageSize: function (pageList) {
var api = Controller.api.streamLoad;
var maxNormal = 0;
$.each(pageList || api.getDefaultPageList(), function (i, value) {
if (api.isAllPageSize(value)) {
return;
}
var num = parseInt(value, 10);
if (!isNaN(num) && num > maxNormal) {
maxNormal = num;
}
});
return maxNormal;
},
isAllPageSize: function (pageSize) {
if (pageSize === undefined || pageSize === null || pageSize === '') {
return false;
}
return String(pageSize).toUpperCase() === String(Controller.api.streamLoad.getAllLabel()).toUpperCase();
},
isLargeStoredPageSize: function (table, params) {
var api = Controller.api.streamLoad;
var options = api.safeGetOptions(table);
var pageSize = options ? options.pageSize : null;
var limit = params ? (parseInt(params.limit, 10) || 0) : 0;
if (pageSize !== null && api.isAllPageSize(pageSize)) {
return true;
}
var maxNormal = api.getMaxNormalPageSize(options ? options.pageList : null);
if (typeof pageSize === 'number' && pageSize > maxNormal) {
return true;
}
if (!options && limit > maxNormal) {
return true;
}
return false;
},
shouldEnable: function (table, params) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
if (state.pendingAllSelect || state.enabled) {
return true;
}
var options = api.safeGetOptions(table);
var limit = parseInt(params.limit, 10) || 0;
if (options) {
var totalRows = parseInt(options.totalRows, 10) || 0;
if (api.isAllPageSize(options.pageSize)) {
return true;
}
if (api.isLargeStoredPageSize(table, params)) {
return true;
}
return totalRows > 0 && limit >= totalRows;
}
// 表格构造阶段:All 模式 totalRows 尚未就绪时 limit 可能为 0
if (limit === 0) {
var stored = localStorage.getItem('pagesize');
if (stored && api.isAllPageSize(stored)) {
return true;
}
}
return api.isLargeStoredPageSize(table, params);
},
enable: function (table) {
var state = Controller.api.streamLoad.getState(table);
state.enabled = true;
state.loaded = 0;
state.loading = false;
state.pendingReset = true;
},
disable: function (table) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
api.cancelPendingLoad(table);
state.enabled = false;
state.loaded = 0;
state.total = 0;
state.loading = false;
state.pendingReset = false;
state.pendingAllSelect = false;
api.updateHint(table);
api.togglePaginationNav(table, false);
api.showBottomLoading(table, false);
},
wrapQueryParams: function (table, params) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
if (api.shouldEnable(table, params)) {
state.enabled = true;
state.pendingAllSelect = false;
}
if (!state.enabled) {
return params;
}
params.limit = state.chunk;
if (state.appendQuery) {
params.offset = parseInt(params.offset, 10) || 0;
} else {
params.offset = 0;
state.pendingReset = true;
}
state.appendQuery = false;
return params;
},
bind: function (table) {
var api = Controller.api.streamLoad;
var $wrapper = table.closest('.bootstrap-table');
$wrapper.on('click.splitStream', '.page-list .dropdown-menu li a', function () {
api.cancelPendingLoad(table);
var label = $.trim($(this).text());
if (api.isAllPageSize(label)) {
api.getState(table).pendingAllSelect = true;
api.enable(table);
}
});
table.on('page-change.bs.table', function (e, pageNumber, pageSize) {
var options = api.safeGetOptions(table);
if (!options) {
return;
}
if (api.isAllPageSize(pageSize)
|| (typeof pageSize === 'number' && pageSize === options.totalRows && options.totalRows > 0)) {
api.enable(table);
return;
}
if (typeof pageSize === 'number' && pageSize < options.totalRows) {
api.disable(table);
}
});
table.on('refresh.bs.table search.bs.table common-search.bs.table', function () {
var state = api.getState(table);
api.cancelPendingLoad(table);
if (!state.enabled) {
return;
}
state.loaded = 0;
state.pendingReset = true;
});
table.on('sort.bs.table', function () {
var state = api.getState(table);
api.cancelPendingLoad(table);
if (!state.enabled) {
return;
}
state.loaded = 0;
state.pendingReset = true;
});
table.on('load-success.bs.table', function (e, data) {
var state = api.getState(table);
if (!state.enabled || !data || typeof data.total === 'undefined') {
return;
}
state.total = parseInt(data.total, 10) || 0;
if (state.pendingReset) {
state.loaded = $.isArray(data.rows) ? data.rows.length : 0;
state.pendingReset = false;
}
api.updateHint(table);
api.togglePaginationNav(table, true);
api.bindScrollContainer(table);
api.autoFillViewport(table);
var tableOptions = api.safeGetOptions(table);
if (tableOptions && tableOptions.fixedColumns) {
table.bootstrapTable('resetView');
}
});
table.on('post-body.bs.table', function () {
if (!api.getState(table).enabled) {
return;
}
api.updateHint(table);
});
},
bindScrollContainer: function (table) {
var api = Controller.api.streamLoad;
var $body = table.closest('.bootstrap-table').find('.fixed-table-body');
if (!$body.length || $body.data('splitStreamBound')) {
return;
}
$body.data('splitStreamBound', true);
$body.on('scroll.splitStream', function () {
api.onScroll(table, this);
});
},
onScroll: function (table, el) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
if (!state.enabled || state.loading || state.loaded >= state.total) {
return;
}
var atBottom = el.scrollTop + el.clientHeight >= el.scrollHeight - api.SCROLL_THRESHOLD;
if (!atBottom) {
api.cancelPendingLoad(table);
return;
}
if (state.pendingLoad) {
return;
}
api.scheduleLoadMore(table);
},
isNearBottom: function (table) {
var api = Controller.api.streamLoad;
var $body = table.closest('.bootstrap-table').find('.fixed-table-body');
if (!$body.length) {
return false;
}
var el = $body[0];
return el.scrollTop + el.clientHeight >= el.scrollHeight - api.SCROLL_THRESHOLD;
},
scheduleLoadMore: function (table) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
if (state.loading || state.pendingLoad || !state.enabled || state.loaded >= state.total) {
return;
}
state.pendingLoad = true;
api.showBottomLoading(table, true);
api.updateHint(table, false, true);
state.loadTimer = setTimeout(function () {
state.pendingLoad = false;
state.loadTimer = null;
if (!state.enabled) {
api.showBottomLoading(table, false);
api.updateHint(table);
return;
}
if (!api.isNearBottom(table)) {
api.showBottomLoading(table, false);
api.updateHint(table);
return;
}
api.loadMore(table);
}, api.LOAD_DELAY);
},
cancelPendingLoad: function (table) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
if (state.loadTimer) {
clearTimeout(state.loadTimer);
state.loadTimer = null;
}
state.pendingLoad = false;
if (!state.loading) {
api.showBottomLoading(table, false);
api.updateHint(table);
}
},
showBottomLoading: function (table, show) {
var $body = table.closest('.bootstrap-table').find('.fixed-table-body');
if (!$body.length) {
return;
}
var $bar = $body.children('.split-stream-loading-bar');
if (show) {
if (!$bar.length) {
var loadingText = __('Stream loading bottom');
if (!loadingText || loadingText === 'Stream loading bottom') {
loadingText = '加载中...';
}
$bar = $('<div class="split-stream-loading-bar text-center" style="padding:14px 0;color:#999;border-top:1px solid #f0f0f0;background:#fafafa;">'
+ '<i class="fa fa-spinner fa-spin"></i> ' + Fast.api.escape(loadingText)
+ '</div>');
$body.append($bar);
}
$bar.show();
} else if ($bar.length) {
$bar.hide();
}
},
buildRequestParams: function (table, offset, limit) {
var options = Controller.api.streamLoad.safeGetOptions(table);
if (!options) {
return {offset: offset, limit: limit};
}
var state = Controller.api.streamLoad.getState(table);
state.appendQuery = true;
return options.queryParams({
search: options.searchText,
sort: options.sortName,
order: options.sortOrder,
offset: offset,
limit: limit
});
},
loadMore: function (table) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
if (state.loading || !state.enabled || state.loaded >= state.total) {
return;
}
state.loading = true;
api.updateHint(table, true);
var options = api.safeGetOptions(table);
if (!options) {
state.loading = false;
return;
}
$.ajax({
url: options.url,
type: options.method,
data: api.buildRequestParams(table, state.loaded, state.chunk),
dataType: 'json'
}).done(function (res) {
state.loading = false;
api.showBottomLoading(table, false);
if (!res || typeof res.rows === 'undefined') {
Toastr.error(__('Unknown data format'));
api.updateHint(table);
return;
}
var rows = res.rows || [];
if (rows.length === 0) {
state.loaded = state.total;
api.updateHint(table);
return;
}
table.bootstrapTable('append', rows);
state.loaded += rows.length;
api.updateHint(table);
api.autoFillViewport(table);
if (options.fixedColumns) {
table.bootstrapTable('resetView');
}
}).fail(function () {
state.loading = false;
api.showBottomLoading(table, false);
api.updateHint(table);
Toastr.error(__('Unknown data format'));
});
},
autoFillViewport: function (table) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
if (!state.enabled || state.loading || state.pendingLoad || state.loaded >= state.total) {
return;
}
var $body = table.closest('.bootstrap-table').find('.fixed-table-body');
if (!$body.length) {
return;
}
var el = $body[0];
if (el.scrollHeight <= el.clientHeight + api.SCROLL_THRESHOLD) {
api.scheduleLoadMore(table);
}
},
togglePaginationNav: function (table, hide) {
table.closest('.bootstrap-table').find('.fixed-table-pagination .pagination').toggle(!hide);
},
getHintText: function (loaded, total, loading, pending) {
if (pending) {
var pendingText = __('Stream loading pending');
if (!pendingText || pendingText === 'Stream loading pending') {
pendingText = '即将加载更多,可切换显示条数取消...';
}
return pendingText;
}
if (loading) {
var loadingText = __('Stream loading');
return loadingText && loadingText !== 'Stream loading' ? loadingText : '加载中...';
}
var template = __('Stream loaded');
if (!template || template === 'Stream loaded') {
template = '已加载 %loaded% / %total%,继续滚动加载更多';
}
return template
.replace('%loaded%', String(loaded))
.replace('%total%', String(total));
},
updateHint: function (table, loading, pending) {
var api = Controller.api.streamLoad;
var state = api.getState(table);
var $wrapper = table.closest('.bootstrap-table');
var $detail = $wrapper.find('.pagination-detail');
if (!state.enabled) {
$wrapper.find('.split-stream-hint').remove();
return;
}
var $hint = $wrapper.find('.split-stream-hint');
if (!$hint.length) {
$hint = $('<span class="split-stream-hint text-muted" style="margin-left:10px;font-size:12px;"></span>');
$detail.append($hint);
}
var isPending = pending !== undefined ? pending : state.pendingLoad;
var isLoading = loading !== undefined ? loading : state.loading;
$hint.text(api.getHintText(state.loaded, state.total, isLoading, isPending));
}
},
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;
});