初始版本
This commit is contained in:
Executable
+847
@@ -0,0 +1,847 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template', 'cookie'], function ($, undefined, Backend, Table, Form, Template, undefined) {
|
||||
$.cookie.prototype.defaults = {path: Config.moduleurl};
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: Config.api_url ? Config.api_url + '/addon/index' : "addon/downloaded",
|
||||
add_url: '',
|
||||
edit_url: '',
|
||||
del_url: '',
|
||||
multi_url: ''
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 弹窗自适应宽高
|
||||
var area = Fast.config.openArea != undefined ? Fast.config.openArea : [$(window).width() > 800 ? '800px' : '95%', $(window).height() > 600 ? '600px' : '95%'];
|
||||
|
||||
var switch_local = function () {
|
||||
if ($(".btn-switch.active").data("type") != "local") {
|
||||
Layer.confirm(__('Store not available tips'), {
|
||||
title: __('Warmtips'),
|
||||
btn: [__('Switch to the local'), __('Try to reload')]
|
||||
}, function (index) {
|
||||
layer.close(index);
|
||||
$(".panel .nav-tabs").hide();
|
||||
$(".toolbar > *:not(:first)").hide();
|
||||
$(".btn-switch[data-type='local']").trigger("click");
|
||||
}, function (index) {
|
||||
layer.close(index);
|
||||
table.bootstrapTable('refresh');
|
||||
});
|
||||
return false;
|
||||
}
|
||||
};
|
||||
table.on('load-success.bs.table', function (e, json) {
|
||||
if (json && typeof json.category != 'undefined' && $(".nav-category li").length == 2) {
|
||||
$.each(json.category, function (i, j) {
|
||||
$("<li><a href='javascript:;' data-id='" + j.id + "'>" + j.name + "</a></li>").insertBefore($(".nav-category li:last"));
|
||||
});
|
||||
}
|
||||
if (typeof json.rows === 'undefined' && typeof json.code != 'undefined') {
|
||||
switch_local();
|
||||
}
|
||||
});
|
||||
table.on('load-error.bs.table', function (e, status, res) {
|
||||
console.log(e, status, res);
|
||||
switch_local();
|
||||
});
|
||||
table.on('post-body.bs.table', function (e, settings, json, xhr) {
|
||||
var parenttable = table.closest('.bootstrap-table');
|
||||
var d = $(".fixed-table-toolbar", parenttable).find(".search input");
|
||||
d.off("keyup drop blur");
|
||||
d.on("keyup", function (e) {
|
||||
if (e.keyCode == 13) {
|
||||
var that = this;
|
||||
var options = table.bootstrapTable('getOptions');
|
||||
var queryParams = options.queryParams;
|
||||
options.pageNumber = 1;
|
||||
options.queryParams = function (params) {
|
||||
var params = queryParams(params);
|
||||
params.search = $(that).val();
|
||||
return params;
|
||||
};
|
||||
table.bootstrapTable('refresh', {});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.helper("Moment", Moment);
|
||||
Template.helper("addons", Config['addons']);
|
||||
|
||||
$("#faupload-addon").data("params", function (files, xhr) {
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
return {
|
||||
uid: userinfo ? userinfo.id : '',
|
||||
token: userinfo ? userinfo.token : '',
|
||||
version: Config.faversion,
|
||||
force: (files[0].force || false) ? 1 : 0
|
||||
};
|
||||
});
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pageSize: 50,
|
||||
queryParams: function (params) {
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
$.extend(params, {
|
||||
uid: userinfo ? userinfo.id : '',
|
||||
token: userinfo ? userinfo.token : '',
|
||||
domain: Config.domain,
|
||||
version: Config.faversion,
|
||||
sid: Controller.api.sid()
|
||||
});
|
||||
return params;
|
||||
},
|
||||
columns: [
|
||||
[
|
||||
{field: 'id', title: 'ID', operate: false, visible: false},
|
||||
{
|
||||
field: 'home',
|
||||
title: __('Index'),
|
||||
width: '50px',
|
||||
formatter: Controller.api.formatter.home
|
||||
},
|
||||
{field: 'name', title: __('Name'), operate: false, visible: false, width: '120px'},
|
||||
{
|
||||
field: 'title',
|
||||
title: __('Title'),
|
||||
operate: 'LIKE',
|
||||
align: 'left',
|
||||
formatter: Controller.api.formatter.title
|
||||
},
|
||||
{
|
||||
field: 'intro',
|
||||
title: __('Intro'),
|
||||
operate: 'LIKE',
|
||||
align: 'left',
|
||||
class: 'visible-lg',
|
||||
formatter: Controller.api.formatter.intro
|
||||
},
|
||||
{
|
||||
field: 'author',
|
||||
title: __('Author'),
|
||||
operate: 'LIKE',
|
||||
width: '100px',
|
||||
formatter: Controller.api.formatter.author
|
||||
},
|
||||
{
|
||||
field: 'price',
|
||||
title: __('Price'),
|
||||
operate: 'LIKE',
|
||||
width: '100px',
|
||||
align: 'center',
|
||||
formatter: Controller.api.formatter.price
|
||||
},
|
||||
{
|
||||
field: 'downloads',
|
||||
title: __('Downloads'),
|
||||
operate: 'LIKE',
|
||||
width: '80px',
|
||||
align: 'center',
|
||||
formatter: Controller.api.formatter.downloads
|
||||
},
|
||||
{
|
||||
field: 'version',
|
||||
title: __('Version'),
|
||||
operate: 'LIKE',
|
||||
width: '80px',
|
||||
align: 'center',
|
||||
formatter: Controller.api.formatter.version
|
||||
},
|
||||
{
|
||||
field: 'toggle',
|
||||
title: __('Status'),
|
||||
width: '80px',
|
||||
formatter: Controller.api.formatter.toggle
|
||||
},
|
||||
{
|
||||
field: 'id',
|
||||
title: __('Operate'),
|
||||
table: table,
|
||||
formatter: Controller.api.formatter.operate,
|
||||
align: 'right',
|
||||
cellStyle: function (value, row, index) {
|
||||
return {css: {'min-width': '158px'}};
|
||||
}
|
||||
},
|
||||
]
|
||||
],
|
||||
responseHandler: function (res) {
|
||||
$.each(res.rows, function (i, j) {
|
||||
j.addon = typeof Config.addons[j.name] != 'undefined' ? Config.addons[j.name] : null;
|
||||
});
|
||||
return res;
|
||||
},
|
||||
dataType: 'jsonp',
|
||||
templateView: false,
|
||||
clickToSelect: false,
|
||||
search: true,
|
||||
showColumns: false,
|
||||
showToggle: false,
|
||||
showExport: false,
|
||||
showSearch: false,
|
||||
commonSearch: true,
|
||||
searchFormVisible: true,
|
||||
searchFormTemplate: 'searchformtpl',
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
|
||||
// 离线安装
|
||||
require(['upload'], function (Upload) {
|
||||
Upload.api.upload("#faupload-addon", function (data, ret, up, file) {
|
||||
Config['addons'][data.addon.name] = data.addon;
|
||||
var addon = data.addon;
|
||||
var testdata = data.addon.testdata;
|
||||
operate(data.addon.name, 'enable', false, function (data, ret) {
|
||||
Layer.alert(__('Offline installed tips') + (testdata ? __('Testdata tips') : ""), {
|
||||
btn: testdata ? [__('Import testdata'), __('Skip testdata')] : [__('OK')],
|
||||
title: __('Warning'),
|
||||
yes: function (index) {
|
||||
if (testdata) {
|
||||
Fast.api.ajax({
|
||||
url: 'addon/testdata',
|
||||
data: {
|
||||
name: addon.name,
|
||||
version: addon.version,
|
||||
faversion: Config.faversion
|
||||
}
|
||||
}, function (data, ret) {
|
||||
Layer.close(index);
|
||||
});
|
||||
} else {
|
||||
Layer.close(index);
|
||||
}
|
||||
},
|
||||
icon: 1
|
||||
});
|
||||
});
|
||||
return false;
|
||||
}, function (data, ret, up, file) {
|
||||
if (ret.msg && ret.msg.match(/(login|登录)/g)) {
|
||||
return Layer.alert(ret.msg, {
|
||||
title: __('Warning'),
|
||||
btn: [__('Login now')],
|
||||
yes: function (index, layero) {
|
||||
$(".btn-userinfo").trigger("click");
|
||||
}
|
||||
});
|
||||
} else if (ret.code === -1) {
|
||||
Layer.confirm(__('Upgrade tips', data.title), {title: __('Warmtips')}, function (index, layero) {
|
||||
up.removeFile(file);
|
||||
file.force = true;
|
||||
up.uploadFile(file);
|
||||
Layer.close(index);
|
||||
});
|
||||
return false;
|
||||
} else if (ret && ret.code === -3) {
|
||||
//插件目录发现影响全局的文件
|
||||
Layer.open({
|
||||
content: Template("conflicttpl", ret.data),
|
||||
shade: 0.8,
|
||||
area: area,
|
||||
title: __('Warning'),
|
||||
btn: [__('Continue install'), __('Cancel')],
|
||||
end: function () {
|
||||
|
||||
},
|
||||
yes: function (index) {
|
||||
up.removeFile(file);
|
||||
file.force = true;
|
||||
up.uploadFile(file);
|
||||
Layer.close(index);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
Layer.alert(ret.msg, {title: __('Warning'), icon: 0});
|
||||
}
|
||||
});
|
||||
|
||||
// 检测是否登录
|
||||
$(document).on("mousedown", "#faupload-addon", function (e) {
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
var uid = userinfo ? userinfo.id : 0;
|
||||
var uploadBtn = Upload.list['faupload-addon'];
|
||||
|
||||
if (parseInt(uid) === 0) {
|
||||
uploadBtn.disable();
|
||||
$(".btn-userinfo").trigger("click");
|
||||
return false;
|
||||
} else {
|
||||
if (uploadBtn.disabled) {
|
||||
uploadBtn.enable();
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 查看插件首页
|
||||
$(document).on("click", ".btn-addonindex", function () {
|
||||
if ($(this).attr("href") == 'javascript:;') {
|
||||
Layer.msg(__('Not installed tips'), {icon: 7});
|
||||
} else if ($(this).closest(".operate").find("a.btn-enable").length > 0) {
|
||||
Layer.msg(__('Not enabled tips'), {icon: 7});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// 切换
|
||||
$(document).on("click", ".btn-switch", function () {
|
||||
$(".btn-switch").removeClass("active");
|
||||
$(this).addClass("active");
|
||||
$("form.form-commonsearch input[name='type']").val($(this).data("type"));
|
||||
var method = $(this).data("type") == 'local' ? 'hideColumn' : 'showColumn';
|
||||
table.bootstrapTable(method, 'price');
|
||||
table.bootstrapTable(method, 'downloads');
|
||||
table.bootstrapTable('refresh', {url: ($(this).data("url") ? $(this).data("url") : $.fn.bootstrapTable.defaults.extend.index_url), pageNumber: 1});
|
||||
return false;
|
||||
});
|
||||
|
||||
// 切换分类
|
||||
$(document).on("click", ".nav-category li a", function () {
|
||||
$(".nav-category li").removeClass("active");
|
||||
$(this).parent().addClass("active");
|
||||
$("form.form-commonsearch input[name='category_id']").val($(this).data("id"));
|
||||
table.bootstrapTable('refresh', {url: $(this).data("url"), pageNumber: 1});
|
||||
return false;
|
||||
});
|
||||
var tables = [];
|
||||
$(document).on("click", "#droptables", function () {
|
||||
if ($(this).prop("checked")) {
|
||||
Fast.api.ajax({
|
||||
url: "addon/get_table_list",
|
||||
async: false,
|
||||
data: {name: $(this).data("name")}
|
||||
}, function (data) {
|
||||
tables = data.tables;
|
||||
return false;
|
||||
});
|
||||
var html;
|
||||
html = tables.length > 0 ? '<div class="alert alert-warning-light droptablestips" style="max-width:480px;max-height:300px;overflow-y: auto;">' + __('The following data tables will be deleted') + ':<br>' + tables.join("<br>") + '</div>'
|
||||
: '<div class="alert alert-warning-light droptablestips">' + __('The Addon did not create a data table') + '</div>';
|
||||
$(html).insertAfter($(this).closest("p"));
|
||||
} else {
|
||||
$(".droptablestips").remove();
|
||||
}
|
||||
$(window).resize();
|
||||
});
|
||||
|
||||
// 会员信息
|
||||
$(document).on("click", ".btn-userinfo", function (e, name, version) {
|
||||
var that = this;
|
||||
var area = [$(window).width() > 800 ? '500px' : '95%', $(window).height() > 600 ? '400px' : '95%'];
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
if (!userinfo) {
|
||||
Fast.api.ajax({
|
||||
url: Config.api_url + '/user/logintpl',
|
||||
type: 'post',
|
||||
loading: false,
|
||||
data: {
|
||||
version: Config.faversion,
|
||||
sid: Controller.api.sid()
|
||||
}
|
||||
}, function (tpldata, ret) {
|
||||
Layer.open({
|
||||
content: Template.render(tpldata, {}),
|
||||
zIndex: 99,
|
||||
area: area,
|
||||
title: __('Login'),
|
||||
resize: false,
|
||||
btn: [__('Login')],
|
||||
yes: function (index, layero) {
|
||||
var data = $("form", layero).serializeArray();
|
||||
data.push({name: "faversion", value: Config.faversion});
|
||||
data.push({name: "sid", value: Controller.api.sid()});
|
||||
Fast.api.ajax({
|
||||
url: Config.api_url + '/user/login',
|
||||
type: 'post',
|
||||
data: data
|
||||
}, function (data, ret) {
|
||||
Controller.api.userinfo.set(data);
|
||||
Layer.closeAll();
|
||||
Layer.alert(ret.msg, {title: __('Warning'), icon: 1});
|
||||
return false;
|
||||
}, function (data, ret) {
|
||||
});
|
||||
},
|
||||
success: function (layero, index) {
|
||||
this.checkEnterKey = function (event) {
|
||||
if (event.keyCode === 13) {
|
||||
$(".layui-layer-btn0").trigger("click");
|
||||
return false;
|
||||
}
|
||||
};
|
||||
$(document).on('keydown', this.checkEnterKey);
|
||||
},
|
||||
end: function () {
|
||||
$(document).off('keydown', this.checkEnterKey);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
} else {
|
||||
Fast.api.ajax({
|
||||
url: Config.api_url + '/user/userinfotpl',
|
||||
type: 'post',
|
||||
data: {
|
||||
uid: userinfo.id,
|
||||
token: userinfo.token,
|
||||
version: Config.faversion,
|
||||
sid: Controller.api.sid()
|
||||
}
|
||||
}, function (tpldata, ret) {
|
||||
Layer.open({
|
||||
content: Template.render(tpldata, userinfo),
|
||||
area: area,
|
||||
title: __('Userinfo'),
|
||||
resize: false,
|
||||
btn: [__('Logout'), __('Close')],
|
||||
yes: function () {
|
||||
Fast.api.ajax({
|
||||
url: Config.api_url + '/user/logout',
|
||||
data: {
|
||||
uid: userinfo.id,
|
||||
token: userinfo.token,
|
||||
version: Config.faversion,
|
||||
sid: Controller.api.sid()
|
||||
}
|
||||
}, function (data, ret) {
|
||||
Controller.api.userinfo.set(null);
|
||||
Layer.closeAll();
|
||||
Layer.alert(ret.msg, {title: __('Warning'), icon: 0});
|
||||
}, function (data, ret) {
|
||||
Controller.api.userinfo.set(null);
|
||||
Layer.closeAll();
|
||||
Layer.alert(ret.msg, {title: __('Warning'), icon: 0});
|
||||
});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}, function (data) {
|
||||
Controller.api.userinfo.set(null);
|
||||
$(that).trigger('click');
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//刷新授权
|
||||
$(document).on("click", ".btn-authorization", function () {
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
if (!userinfo) {
|
||||
$(".btn-userinfo").trigger("click");
|
||||
return false;
|
||||
}
|
||||
Layer.confirm(__('Are you sure you want to refresh authorization?'), {icon: 3, title: __('Warmtips')}, function () {
|
||||
Fast.api.ajax({
|
||||
url: 'addon/authorization',
|
||||
data: {
|
||||
uid: userinfo.id,
|
||||
token: userinfo.token
|
||||
}
|
||||
}, function (data, ret) {
|
||||
$(".btn-refresh").trigger("click");
|
||||
Layer.closeAll();
|
||||
});
|
||||
});
|
||||
return false;
|
||||
});
|
||||
|
||||
var install = function (name, version, force) {
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
var uid = userinfo ? userinfo.id : 0;
|
||||
var token = userinfo ? userinfo.token : '';
|
||||
Fast.api.ajax({
|
||||
url: 'addon/install',
|
||||
data: {
|
||||
name: name,
|
||||
force: force ? 1 : 0,
|
||||
uid: uid,
|
||||
token: token,
|
||||
version: version,
|
||||
faversion: Config.faversion
|
||||
}
|
||||
}, function (data, ret) {
|
||||
Layer.closeAll();
|
||||
Config['addons'][data.addon.name] = ret.data.addon;
|
||||
operate(data.addon.name, 'enable', false, function () {
|
||||
Layer.alert(__('Online installed tips') + (data.addon.testdata ? __('Testdata tips') : ""), {
|
||||
btn: data.addon.testdata ? [__('Import testdata'), __('Skip testdata')] : [__('OK')],
|
||||
title: __('Warning'),
|
||||
yes: function (index) {
|
||||
if (data.addon.testdata) {
|
||||
Fast.api.ajax({
|
||||
url: 'addon/testdata',
|
||||
data: {
|
||||
name: name,
|
||||
uid: uid,
|
||||
token: token,
|
||||
version: version,
|
||||
faversion: Config.faversion
|
||||
}
|
||||
}, function (data, ret) {
|
||||
Layer.close(index);
|
||||
});
|
||||
} else {
|
||||
Layer.close(index);
|
||||
}
|
||||
},
|
||||
icon: 1
|
||||
});
|
||||
Controller.api.refresh(table, name);
|
||||
});
|
||||
}, function (data, ret) {
|
||||
var area = Fast.config.openArea != undefined ? Fast.config.openArea : [$(window).width() > 650 ? '650px' : '95%', $(window).height() > 710 ? '710px' : '95%'];
|
||||
if (ret && ret.code === -2) {
|
||||
//如果登录已经超时,重新提醒登录
|
||||
if (uid && uid != ret.data.uid) {
|
||||
Controller.api.userinfo.set(null);
|
||||
$(".operate[data-name='" + name + "'] .btn-install:first").trigger("click");
|
||||
return;
|
||||
}
|
||||
top.Fast.api.open(ret.data.payurl, __('Pay now'), {
|
||||
area: area,
|
||||
end: function () {
|
||||
Fast.api.ajax({
|
||||
url: 'addon/isbuy',
|
||||
data: {
|
||||
name: name,
|
||||
force: force ? 1 : 0,
|
||||
uid: uid,
|
||||
token: token,
|
||||
version: version,
|
||||
faversion: Config.faversion
|
||||
}
|
||||
}, function () {
|
||||
top.Layer.alert(__('Pay successful tips'), {
|
||||
btn: [__('Continue installation')],
|
||||
title: __('Warning'),
|
||||
icon: 1,
|
||||
yes: function (index) {
|
||||
top.Layer.close(index);
|
||||
install(name, version);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}, function () {
|
||||
console.log(__('Canceled'));
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
} else if (ret && ret.code === -3) {
|
||||
//插件目录发现影响全局的文件
|
||||
Layer.open({
|
||||
content: Template("conflicttpl", ret.data),
|
||||
shade: 0.8,
|
||||
area: area,
|
||||
title: __('Warning'),
|
||||
btn: [__('Continue install'), __('Cancel')],
|
||||
end: function () {
|
||||
|
||||
},
|
||||
yes: function () {
|
||||
install(name, version, true);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
Layer.alert(ret.msg, {title: __('Warning'), icon: 0});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
var uninstall = function (name, force, droptables) {
|
||||
Fast.api.ajax({
|
||||
url: 'addon/uninstall',
|
||||
data: {name: name, force: force ? 1 : 0, droptables: droptables ? 1 : 0}
|
||||
}, function (data, ret) {
|
||||
delete Config['addons'][name];
|
||||
Layer.closeAll();
|
||||
Controller.api.refresh(table, name);
|
||||
}, function (data, ret) {
|
||||
if (ret && ret.code === -3) {
|
||||
//插件目录发现影响全局的文件
|
||||
Layer.open({
|
||||
content: Template("conflicttpl", ret.data),
|
||||
shade: 0.8,
|
||||
area: area,
|
||||
title: __('Warning'),
|
||||
btn: [__('Continue uninstall'), __('Cancel')],
|
||||
end: function () {
|
||||
|
||||
},
|
||||
yes: function () {
|
||||
uninstall(name, true, droptables);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
Layer.alert(ret.msg, {title: __('Warning'), icon: 0});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
var operate = function (name, action, force, success) {
|
||||
Fast.api.ajax({
|
||||
url: 'addon/state',
|
||||
data: {name: name, action: action, force: force ? 1 : 0}
|
||||
}, function (data, ret) {
|
||||
var addon = Config['addons'][name];
|
||||
addon.state = action === 'enable' ? 1 : 0;
|
||||
Layer.closeAll();
|
||||
if (typeof success === 'function') {
|
||||
success(data, ret);
|
||||
}
|
||||
Controller.api.refresh(table, name);
|
||||
}, function (data, ret) {
|
||||
if (ret && ret.code === -3) {
|
||||
//插件目录发现影响全局的文件
|
||||
Layer.open({
|
||||
content: Template("conflicttpl", ret.data),
|
||||
shade: 0.8,
|
||||
area: area,
|
||||
title: __('Warning'),
|
||||
btn: [__('Continue operate'), __('Cancel')],
|
||||
end: function () {
|
||||
|
||||
},
|
||||
yes: function () {
|
||||
operate(name, action, true, success);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
Layer.alert(ret.msg, {title: __('Warning'), icon: 0});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
var upgrade = function (name, version) {
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
var uid = userinfo ? userinfo.id : 0;
|
||||
var token = userinfo ? userinfo.token : '';
|
||||
Fast.api.ajax({
|
||||
url: 'addon/upgrade',
|
||||
data: {name: name, uid: uid, token: token, version: version, faversion: Config.faversion}
|
||||
}, function (data, ret) {
|
||||
Config['addons'][name] = data.addon;
|
||||
Layer.closeAll();
|
||||
Controller.api.refresh(table, name);
|
||||
}, function (data, ret) {
|
||||
Layer.alert(ret.msg, {title: __('Warning')});
|
||||
return false;
|
||||
});
|
||||
};
|
||||
|
||||
// 点击安装
|
||||
$(document).on("click", ".btn-install", function () {
|
||||
var that = this;
|
||||
var name = $(this).closest(".operate").data("name");
|
||||
var version = $(this).data("version");
|
||||
|
||||
var userinfo = Controller.api.userinfo.get();
|
||||
var uid = userinfo ? userinfo.id : 0;
|
||||
|
||||
if (parseInt(uid) === 0) {
|
||||
$(".btn-userinfo").trigger("click", name, version);
|
||||
return false;
|
||||
}
|
||||
install(name, version, false);
|
||||
});
|
||||
|
||||
// 点击卸载
|
||||
$(document).on("click", ".btn-uninstall", function () {
|
||||
var name = $(this).closest(".operate").data('name');
|
||||
if (Config['addons'][name].state == 1) {
|
||||
Layer.alert(__('Please disable the add before trying to uninstall'), {icon: 7});
|
||||
return false;
|
||||
}
|
||||
Template.helper("__", __);
|
||||
tables = [];
|
||||
Layer.confirm(Template("uninstalltpl", {addon: Config['addons'][name]}), {focusBtn: false, title: __("Warning")}, function (index, layero) {
|
||||
uninstall(name, false, $("input[name='droptables']", layero).prop("checked"));
|
||||
});
|
||||
});
|
||||
|
||||
// 点击配置
|
||||
$(document).on("click", ".btn-config", function () {
|
||||
var name = $(this).closest(".operate").data("name");
|
||||
Fast.api.open("addon/config?name=" + name, __('Setting'));
|
||||
});
|
||||
|
||||
// 点击启用/禁用
|
||||
$(document).on("click", ".btn-enable,.btn-disable", function () {
|
||||
var name = $(this).data("name");
|
||||
var action = $(this).data("action");
|
||||
operate(name, action, false);
|
||||
});
|
||||
|
||||
// 点击升级
|
||||
$(document).on("click", ".btn-upgrade", function () {
|
||||
var name = $(this).closest(".operate").data('name');
|
||||
if (Config['addons'][name].state == 1) {
|
||||
Layer.alert(__('Please disable the add before trying to upgrade'), {icon: 7});
|
||||
return false;
|
||||
}
|
||||
var version = $(this).data("version");
|
||||
|
||||
Layer.confirm(__('Upgrade tips', Config['addons'][name].title), {title: __('Warmtips')}, function (index, layero) {
|
||||
upgrade(name, version);
|
||||
});
|
||||
});
|
||||
|
||||
$(document).on("click", ".operate .btn-group .dropdown-toggle", function () {
|
||||
$(this).closest(".btn-group").toggleClass("dropup", $(document).height() - $(this).offset().top <= 200);
|
||||
});
|
||||
|
||||
$(document).on("click", ".view-screenshots", function () {
|
||||
var row = Table.api.getrowbyindex(table, parseInt($(this).data("index")));
|
||||
var data = [];
|
||||
$.each(row.screenshots, function (i, j) {
|
||||
data.push({
|
||||
"src": j
|
||||
});
|
||||
});
|
||||
var json = {
|
||||
"title": row.title,
|
||||
"data": data
|
||||
};
|
||||
top.Layer.photos(top.JSON.parse(JSON.stringify({photos: json})));
|
||||
});
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
config: function () {
|
||||
$(document).on("click", ".nav-group li a[data-toggle='tab']", function () {
|
||||
if ($(this).attr("href") == "#all") {
|
||||
$(".tab-pane").addClass("active in");
|
||||
}
|
||||
return;
|
||||
var type = $(this).attr("href").substring(1);
|
||||
if (type == 'all') {
|
||||
$(".table-config tr").show();
|
||||
} else {
|
||||
$(".table-config tr").hide();
|
||||
$(".table-config tr[data-group='" + type + "']").show();
|
||||
}
|
||||
});
|
||||
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
formatter: {
|
||||
title: function (value, row, index) {
|
||||
if ($(".btn-switch.active").data("type") == "local") {
|
||||
// return value;
|
||||
}
|
||||
var title = '<a class="title" href="' + row.url + '" data-toggle="tooltip" title="' + __('View addon home page') + '" target="_blank"><span class="' + Fast.api.escape(row.color) + '">' + value + '</span></a>';
|
||||
if (row.screenshots && row.screenshots.length > 0) {
|
||||
title += ' <a href="javascript:;" data-index="' + index + '" class="view-screenshots text-success" title="' + __('View addon screenshots') + '" data-toggle="tooltip"><i class="fa fa-image"></i></a>';
|
||||
}
|
||||
return title;
|
||||
},
|
||||
intro: function (value, row, index) {
|
||||
return row.intro + (row.extend ? "<a href='" + Fast.api.escape(row.extend[1]) + "' class='" + Fast.api.escape(row.extend[2]) + "'>" + Fast.api.escape(row.extend[0]) + "</a>" : "");
|
||||
},
|
||||
operate: function (value, row, index) {
|
||||
return Template("operatetpl", {item: row, index: index});
|
||||
},
|
||||
toggle: function (value, row, index) {
|
||||
if (!row.addon) {
|
||||
return '';
|
||||
}
|
||||
return '<a href="javascript:;" data-toggle="tooltip" title="' + __('Click to toggle status') + '" class="btn btn-toggle btn-' + (row.addon.state == 1 ? "disable" : "enable") + '" data-action="' + (row.addon.state == 1 ? "disable" : "enable") + '" data-name="' + row.name + '"><i class="fa ' + (row.addon.state == 0 ? 'fa-toggle-on fa-rotate-180 text-gray' : 'fa-toggle-on text-success') + ' fa-2x"></i></a>';
|
||||
},
|
||||
author: function (value, row, index) {
|
||||
var url = 'javascript:';
|
||||
if (typeof row.homepage !== 'undefined') {
|
||||
url = row.homepage;
|
||||
} else if (typeof row.qq !== 'undefined' && row.qq) {
|
||||
url = 'https://wpa.qq.com/msgrd?v=3&uin=' + row.qq + '&site=&menu=yes';
|
||||
}
|
||||
return '<a href="' + url + '" target="_blank" data-toggle="tooltip" class="text-primary">' + value + '</a>';
|
||||
},
|
||||
price: function (value, row, index) {
|
||||
if (isNaN(value)) {
|
||||
return value;
|
||||
}
|
||||
return parseFloat(value) == 0 ? '<span class="text-success">' + __('Free') + '</span>' : '<span class="text-danger">¥' + value + '</span>';
|
||||
},
|
||||
downloads: function (value, row, index) {
|
||||
return value;
|
||||
},
|
||||
version: function (value, row, index) {
|
||||
return row.addon && row.addon.version != row.version ? '<a href="' + row.url + '?version=' + row.version + '" target="_blank"><span class="releasetips text-primary" data-toggle="tooltip" title="' + __('New version tips', row.version) + '">' + row.addon.version + '<i></i></span></a>' : row.version;
|
||||
},
|
||||
home: function (value, row, index) {
|
||||
return row.addon && parseInt(row.addon.state) > 0 ? '<a href="' + row.addon.url + '" data-toggle="tooltip" title="' + __('View addon index page') + '" target="_blank"><i class="fa fa-home text-primary"></i></a>' : '<a href="javascript:;"><i class="fa fa-home text-gray"></i></a>';
|
||||
},
|
||||
},
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
},
|
||||
userinfo: {
|
||||
get: function () {
|
||||
if (typeof $.cookie !== 'undefined') {
|
||||
var userinfo = $.cookie('fastadmin_userinfo');
|
||||
} else {
|
||||
var userinfo = sessionStorage.getItem("fastadmin_userinfo");
|
||||
}
|
||||
return userinfo ? JSON.parse(userinfo) : null;
|
||||
},
|
||||
set: function (data) {
|
||||
if (typeof $.cookie !== 'undefined') {
|
||||
if (data) {
|
||||
$.cookie("fastadmin_userinfo", JSON.stringify(data));
|
||||
} else {
|
||||
$.removeCookie("fastadmin_userinfo");
|
||||
}
|
||||
} else {
|
||||
if (data) {
|
||||
sessionStorage.setItem("fastadmin_userinfo", JSON.stringify(data));
|
||||
} else {
|
||||
sessionStorage.removeItem("fastadmin_userinfo");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
sid: function () {
|
||||
var sid = $.cookie('fastadmin_sid');
|
||||
if (!sid) {
|
||||
sid = Math.random().toString(20).substr(2, 12);
|
||||
$.cookie('fastadmin_sid', sid);
|
||||
}
|
||||
return sid;
|
||||
},
|
||||
refresh: function (table, name) {
|
||||
//刷新左侧边栏
|
||||
Fast.api.refreshmenu();
|
||||
|
||||
//刷新行数据
|
||||
if ($(".operate[data-name='" + name + "']").length > 0) {
|
||||
var tr = $(".operate[data-name='" + name + "']").closest("tr[data-index]");
|
||||
var index = tr.data("index");
|
||||
var row = Table.api.getrowbyindex(table, index);
|
||||
row.addon = typeof Config['addons'][name] !== 'undefined' ? Config['addons'][name] : undefined;
|
||||
table.bootstrapTable("updateRow", {index: index, row: row});
|
||||
} else if ($(".btn-switch.active").data("type") == "local") {
|
||||
$(".btn-refresh").trigger("click");
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+62
@@ -0,0 +1,62 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'auth/admin/index',
|
||||
add_url: 'auth/admin/add',
|
||||
edit_url: 'auth/admin/edit',
|
||||
del_url: 'auth/admin/del',
|
||||
multi_url: 'auth/admin/multi',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
//在表格内容渲染完成后回调的事件
|
||||
table.on('post-body.bs.table', function (e, json) {
|
||||
$("tbody tr[data-index]", this).each(function () {
|
||||
if (parseInt($("td:eq(1)", this).text()) == Config.admin.id) {
|
||||
$("input[type=checkbox]", this).prop("disabled", true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
columns: [
|
||||
[
|
||||
{field: 'state', checkbox: true, },
|
||||
{field: 'id', title: 'ID'},
|
||||
{field: 'username', title: __('Username')},
|
||||
{field: 'nickname', title: __('Nickname')},
|
||||
{field: 'groups_text', title: __('Group'), operate:false, formatter: Table.api.formatter.label},
|
||||
{field: 'email', title: __('Email')},
|
||||
{field: 'mobile', title: __('Mobile')},
|
||||
{field: 'status', title: __("Status"), searchList: {"normal":__('Normal'),"hidden":__('Hidden')}, formatter: Table.api.formatter.status},
|
||||
{field: 'logintime', title: __('Login time'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: function (value, row, index) {
|
||||
if(row.id == Config.admin.id){
|
||||
return '';
|
||||
}
|
||||
return Table.api.formatter.operate.call(this, value, row, index);
|
||||
}}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
add: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
},
|
||||
edit: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+64
@@ -0,0 +1,64 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'auth/adminlog/index',
|
||||
add_url: '',
|
||||
edit_url: '',
|
||||
del_url: 'auth/adminlog/del',
|
||||
multi_url: 'auth/adminlog/multi',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
fixedColumns: true,
|
||||
fixedRightNumber: 1,
|
||||
columns: [
|
||||
[
|
||||
{field: 'state', checkbox: true,},
|
||||
{field: 'id', title: 'ID', operate: false},
|
||||
{field: 'admin_id', title: __('Admin_id'), formatter: Table.api.formatter.search, visible: false},
|
||||
{field: 'username', title: __('Username'), formatter: Table.api.formatter.search},
|
||||
{field: 'title', title: __('Title'), operate: 'LIKE %...%', placeholder: '模糊搜索'},
|
||||
{field: 'url', title: __('Url'), formatter: Table.api.formatter.url},
|
||||
{field: 'ip', title: __('IP'), events: Table.api.events.ip, formatter: Table.api.formatter.search},
|
||||
{field: 'createtime', title: __('Create time'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
{
|
||||
field: 'operate', title: __('Operate'), table: table,
|
||||
events: Table.api.events.operate,
|
||||
buttons: [{
|
||||
name: 'detail',
|
||||
text: __('Detail'),
|
||||
icon: 'fa fa-list',
|
||||
classname: 'btn btn-info btn-xs btn-detail btn-dialog',
|
||||
url: 'auth/adminlog/detail'
|
||||
}],
|
||||
formatter: Table.api.formatter.operate
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
},
|
||||
formatter: {
|
||||
browser: function (value, row, index) {
|
||||
return '<a class="btn btn-xs btn-browser">' + row.useragent.split(" ")[0] + '</a>';
|
||||
},
|
||||
},
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+160
@@ -0,0 +1,160 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function ($, undefined, Backend, Table, Form, undefined) {
|
||||
//读取选中的条目
|
||||
$.jstree.core.prototype.get_all_checked = function (full) {
|
||||
var obj = this.get_selected(), i, j;
|
||||
for (i = 0, j = obj.length; i < j; i++) {
|
||||
obj = obj.concat(this.get_node(obj[i]).parents);
|
||||
}
|
||||
obj = $.grep(obj, function (v, i, a) {
|
||||
return v != '#';
|
||||
});
|
||||
obj = obj.filter(function (itm, i, a) {
|
||||
return i == a.indexOf(itm);
|
||||
});
|
||||
return full ? $.map(obj, $.proxy(function (i) {
|
||||
return this.get_node(i);
|
||||
}, this)) : obj;
|
||||
};
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
"index_url": "auth/group/index",
|
||||
"add_url": "auth/group/add",
|
||||
"edit_url": "auth/group/edit",
|
||||
"del_url": "auth/group/del",
|
||||
"multi_url": "auth/group/multi",
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
//在表格内容渲染完成后回调的事件
|
||||
table.on('post-body.bs.table', function (e, json) {
|
||||
$("tbody tr[data-index]", this).each(function () {
|
||||
if (Config.admin.group_ids.indexOf(parseInt(parseInt($("td:eq(1)", this).text()))) > -1) {
|
||||
$("input[type=checkbox]", this).prop("disabled", true);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
columns: [
|
||||
[
|
||||
{field: 'state', checkbox: true,},
|
||||
{field: 'id', title: 'ID'},
|
||||
{field: 'pid', title: __('Parent')},
|
||||
{field: 'name', title: __('Name'), align: 'left', formatter:function (value, row, index) {
|
||||
return value.toString().replace(/(&|&)nbsp;/g, ' ');
|
||||
}
|
||||
},
|
||||
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status},
|
||||
{
|
||||
field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: function (value, row, index) {
|
||||
if (Config.admin.group_ids.indexOf(parseInt(row.id)) > -1) {
|
||||
return '';
|
||||
}
|
||||
return Table.api.formatter.operate.call(this, value, row, index);
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
pagination: false,
|
||||
search: false,
|
||||
commonSearch: false,
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);//当内容渲染完成后
|
||||
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"), null, null, function () {
|
||||
if ($("#treeview").length > 0) {
|
||||
var r = $("#treeview").jstree("get_all_checked");
|
||||
$("input[name='row[rules]']").val(r.join(','));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
//渲染权限节点树
|
||||
//变更级别后需要重建节点树
|
||||
$(document).on("change", "select[name='row[pid]']", function () {
|
||||
var pid = $(this).data("pid");
|
||||
var id = $(this).data("id");
|
||||
if ($(this).val() == id) {
|
||||
$("option[value='" + pid + "']", this).prop("selected", true).change();
|
||||
Backend.api.toastr.error(__('Can not change the parent to self'));
|
||||
return false;
|
||||
}
|
||||
$.ajax({
|
||||
url: "auth/group/roletree",
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
data: {id: id, pid: $(this).val()},
|
||||
success: function (ret) {
|
||||
if (ret.hasOwnProperty("code")) {
|
||||
var data = ret.hasOwnProperty("data") && ret.data != "" ? ret.data : "";
|
||||
if (ret.code === 1) {
|
||||
//销毁已有的节点树
|
||||
$("#treeview").jstree("destroy");
|
||||
Controller.api.rendertree(data);
|
||||
} else {
|
||||
Backend.api.toastr.error(ret.msg);
|
||||
}
|
||||
}
|
||||
}, error: function (e) {
|
||||
Backend.api.toastr.error(e.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
//全选和展开
|
||||
$(document).on("click", "#checkall", function () {
|
||||
$("#treeview").jstree($(this).prop("checked") ? "check_all" : "uncheck_all");
|
||||
});
|
||||
$(document).on("click", "#expandall", function () {
|
||||
$("#treeview").jstree($(this).prop("checked") ? "open_all" : "close_all");
|
||||
});
|
||||
$("select[name='row[pid]']").trigger("change");
|
||||
},
|
||||
rendertree: function (content) {
|
||||
$("#treeview")
|
||||
.on('redraw.jstree', function (e) {
|
||||
$(".layer-footer").attr("domrefresh", Math.random());
|
||||
})
|
||||
.jstree({
|
||||
"themes": {"stripes": true},
|
||||
"checkbox": {
|
||||
"keep_selected_style": false,
|
||||
},
|
||||
"types": {
|
||||
"root": {
|
||||
"icon": "fa fa-folder-open",
|
||||
},
|
||||
"menu": {
|
||||
"icon": "fa fa-folder-open",
|
||||
},
|
||||
"file": {
|
||||
"icon": "fa fa-file-o",
|
||||
}
|
||||
},
|
||||
"plugins": ["checkbox", "types"],
|
||||
"core": {
|
||||
'check_callback': true,
|
||||
"data": content
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+221
@@ -0,0 +1,221 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
"index_url": "auth/rule/index",
|
||||
"add_url": "auth/rule/add",
|
||||
"edit_url": "auth/rule/edit",
|
||||
"del_url": "auth/rule/del",
|
||||
"multi_url": "auth/rule/multi",
|
||||
"table": "auth_rule"
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
sortName: '',
|
||||
escape: true,
|
||||
columns: [
|
||||
[
|
||||
{field: 'state', checkbox: true,},
|
||||
{field: 'id', title: 'ID'},
|
||||
{field: 'title', title: __('Title'), align: 'left', formatter: Controller.api.formatter.title, clickToSelect: !false},
|
||||
{field: 'icon', title: __('Icon'), formatter: Controller.api.formatter.icon},
|
||||
{field: 'name', title: __('Name'), align: 'left', formatter: Controller.api.formatter.name},
|
||||
{field: 'weigh', title: __('Weigh')},
|
||||
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status},
|
||||
{
|
||||
field: 'ismenu',
|
||||
title: __('Ismenu'),
|
||||
align: 'center',
|
||||
table: table,
|
||||
formatter: Table.api.formatter.toggle
|
||||
},
|
||||
{
|
||||
field: 'operate',
|
||||
title: __('Operate'),
|
||||
table: table,
|
||||
events: Table.api.events.operate,
|
||||
formatter: Table.api.formatter.operate
|
||||
}
|
||||
]
|
||||
],
|
||||
pagination: false,
|
||||
search: false,
|
||||
commonSearch: false,
|
||||
rowAttributes: function (row, index) {
|
||||
return row.pid == 0 ? {} : {style: "display:none"};
|
||||
}
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
|
||||
var btnSuccessEvent = function (data, ret) {
|
||||
if ($(this).hasClass("btn-change")) {
|
||||
var index = $(this).data("index");
|
||||
var row = Table.api.getrowbyindex(table, index);
|
||||
row.ismenu = $("i.fa.text-gray", this).length > 0 ? 1 : 0;
|
||||
table.bootstrapTable("updateRow", {index: index, row: row});
|
||||
} else if ($(this).hasClass("btn-delone")) {
|
||||
if ($(this).closest("tr[data-index]").find("a.btn-node-sub.disabled").length > 0) {
|
||||
$(this).closest("tr[data-index]").remove();
|
||||
} else {
|
||||
table.bootstrapTable('refresh');
|
||||
}
|
||||
} else if ($(this).hasClass("btn-dragsort")) {
|
||||
table.bootstrapTable('refresh');
|
||||
}
|
||||
Fast.api.refreshmenu();
|
||||
return false;
|
||||
};
|
||||
|
||||
//表格内容渲染前
|
||||
table.on('pre-body.bs.table', function (e, data) {
|
||||
var options = table.bootstrapTable("getOptions");
|
||||
options.escape = true;
|
||||
});
|
||||
|
||||
//当内容渲染完成后
|
||||
table.on('post-body.bs.table', function (e, data) {
|
||||
var options = table.bootstrapTable("getOptions");
|
||||
options.escape = false;
|
||||
|
||||
//点击切换/排序/删除操作后刷新左侧菜单
|
||||
$(".btn-change[data-id],.btn-delone,.btn-dragsort").data("success", btnSuccessEvent);
|
||||
|
||||
});
|
||||
|
||||
table.on('post-body.bs.table', function (e, settings, json, xhr) {
|
||||
//显示隐藏子节点
|
||||
$(">tbody>tr[data-index] > td", this).on('click', "a.btn-node-sub", function () {
|
||||
var status = $(this).data("shown") ? true : false;
|
||||
$("a[data-pid='" + $(this).data("id") + "']").each(function () {
|
||||
$(this).closest("tr").toggle(!status);
|
||||
});
|
||||
if (status) {
|
||||
$("a[data-pid='" + $(this).data("id") + "']").trigger("collapse");
|
||||
}
|
||||
$(this).data("shown", !status);
|
||||
$("i", this).toggleClass("fa-caret-down").toggleClass("fa-caret-right");
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
//隐藏子节点
|
||||
$(document).on("collapse", ".btn-node-sub", function () {
|
||||
if ($("i", this).length > 0) {
|
||||
$("a[data-pid='" + $(this).data("id") + "']").trigger("collapse");
|
||||
}
|
||||
$("i", this).removeClass("fa-caret-down").addClass("fa-caret-right");
|
||||
$(this).data("shown", false);
|
||||
$(this).closest("tr").toggle(false);
|
||||
});
|
||||
|
||||
//批量删除后的回调
|
||||
$(".toolbar > .btn-del,.toolbar .btn-more~ul>li>a").data("success", function (e) {
|
||||
Fast.api.refreshmenu();
|
||||
});
|
||||
|
||||
//展开隐藏一级
|
||||
$(document.body).on("click", ".btn-toggle", function (e) {
|
||||
$("a[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide();
|
||||
var that = this;
|
||||
var show = $("i", that).hasClass("fa-chevron-down");
|
||||
$("i", that).toggleClass("fa-chevron-down", !show).toggleClass("fa-chevron-up", show);
|
||||
$("a[data-id][data-pid][data-pid!=0]").not('.disabled').closest("tr").toggle(show);
|
||||
$(".btn-node-sub[data-pid=0]").data("shown", show);
|
||||
});
|
||||
|
||||
//展开隐藏全部
|
||||
$(document.body).on("click", ".btn-toggle-all", function (e) {
|
||||
var that = this;
|
||||
var show = $("i", that).hasClass("fa-plus");
|
||||
$("i", that).toggleClass("fa-plus", !show).toggleClass("fa-minus", show);
|
||||
$(".btn-node-sub:not([data-pid=0])").closest("tr").toggle(show);
|
||||
$(".btn-node-sub").data("shown", show);
|
||||
$(".btn-node-sub > i").toggleClass("fa-caret-down", show).toggleClass("fa-caret-right", !show);
|
||||
});
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
formatter: {
|
||||
title: function (value, row, index) {
|
||||
value = value.toString().replace(/(&|&)nbsp;/g, ' ');
|
||||
var caret = row.haschild == 1 || row.ismenu == 1 ? '<i class="fa fa-caret-right"></i>' : '';
|
||||
value = value.indexOf(" ") > -1 ? value.replace(/(.*) /, "$1" + caret) : caret + value;
|
||||
|
||||
value = !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||
return '<a href="javascript:;" data-id="' + row.id + '" data-pid="' + row.pid + '" class="'
|
||||
+ (row.haschild == 1 || row.ismenu == 1 ? 'text-primary' : 'disabled') + ' btn-node-sub">' + value + '</a>';
|
||||
},
|
||||
name: function (value, row, index) {
|
||||
return !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||
},
|
||||
icon: function (value, row, index) {
|
||||
return '<span class="' + (!row.ismenu || row.status == 'hidden' ? 'text-muted' : '') + '"><i class="' + value + '"></i></span>';
|
||||
}
|
||||
},
|
||||
bindevent: function () {
|
||||
$(document).on('click', "input[name='row[ismenu]']", function () {
|
||||
var name = $("input[name='row[name]']");
|
||||
var ismenu = $(this).val() == 1;
|
||||
name.prop("placeholder", ismenu ? name.data("placeholder-menu") : name.data("placeholder-node"));
|
||||
$('div[data-type="menu"]').toggleClass("hidden", !ismenu);
|
||||
});
|
||||
$("input[name='row[ismenu]']:checked").trigger("click");
|
||||
|
||||
var iconlist = [];
|
||||
var iconfunc = function () {
|
||||
Layer.open({
|
||||
type: 1,
|
||||
area: ['80%', '80%'], //宽高
|
||||
content: Template('chooseicontpl', {iconlist: iconlist})
|
||||
});
|
||||
};
|
||||
Form.api.bindevent($("form[role=form]"), function (data) {
|
||||
Fast.api.refreshmenu();
|
||||
});
|
||||
$(document).on('change keyup', "#icon", function () {
|
||||
$(this).prev().find("i").prop("class", $(this).val());
|
||||
});
|
||||
$(document).on('click', ".btn-search-icon", function () {
|
||||
if (iconlist.length == 0) {
|
||||
$.get(Config.site.cdnurl + "/assets/libs/font-awesome/css/font-awesome.css", function (ret) {
|
||||
var exp = /fa-(.*):before/ig;
|
||||
var result;
|
||||
while ((result = exp.exec(ret)) != null) {
|
||||
iconlist.push(result[1]);
|
||||
}
|
||||
iconfunc();
|
||||
});
|
||||
} else {
|
||||
iconfunc();
|
||||
}
|
||||
});
|
||||
$(document).on('click', '#chooseicon ul li', function () {
|
||||
$("input[name='row[icon]']").val('fa fa-' + $(this).data("font")).trigger("change");
|
||||
Layer.closeAll();
|
||||
});
|
||||
$(document).on('keyup', 'input.js-icon-search', function () {
|
||||
$("#chooseicon ul li").show();
|
||||
if ($(this).val() != '') {
|
||||
$("#chooseicon ul li:not([data-font*='" + $(this).val() + "'])").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+93
@@ -0,0 +1,93 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'category/index',
|
||||
add_url: 'category/add',
|
||||
edit_url: 'category/edit',
|
||||
del_url: 'category/del',
|
||||
multi_url: 'category/multi',
|
||||
dragsort_url: 'ajax/weigh',
|
||||
table: 'category',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
var tableOptions = {
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'weigh',
|
||||
pagination: false,
|
||||
commonSearch: false,
|
||||
search: false,
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'type', title: __('Type'), operate: false, searchList: Config.searchList, formatter: Table.api.formatter.label},
|
||||
{field: 'name', title: __('Name'), align: 'left', formatter:function (value, row, index) {
|
||||
return value.toString().replace(/(&|&)nbsp;/g, ' ');
|
||||
}
|
||||
},
|
||||
{field: 'nickname', title: __('Nickname')},
|
||||
{field: 'flag', title: __('Flag'), formatter: Table.api.formatter.flag},
|
||||
{field: 'image', title: __('Image'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.image},
|
||||
{field: 'weigh', title: __('Weigh')},
|
||||
{field: 'status', title: __('Status'), operate: false, formatter: Table.api.formatter.status},
|
||||
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
|
||||
]
|
||||
]
|
||||
};
|
||||
// 初始化表格
|
||||
table.bootstrapTable(tableOptions);
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
|
||||
//绑定TAB事件
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
// var options = table.bootstrapTable(tableOptions);
|
||||
var typeStr = $(this).attr("href").replace('#', '');
|
||||
var options = table.bootstrapTable('getOptions');
|
||||
options.pageNumber = 1;
|
||||
options.queryParams = function (params) {
|
||||
// params.filter = JSON.stringify({type: typeStr});
|
||||
params.type = typeStr;
|
||||
|
||||
return params;
|
||||
};
|
||||
table.bootstrapTable('refresh', {});
|
||||
return false;
|
||||
|
||||
});
|
||||
|
||||
//必须默认触发shown.bs.tab事件
|
||||
// $('ul.nav-tabs li.active a[data-toggle="tab"]').trigger("shown.bs.tab");
|
||||
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
setTimeout(function () {
|
||||
$("#c-type").trigger("change");
|
||||
}, 100);
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
$(document).on("change", "#c-type", function () {
|
||||
$("#c-pid option[data-type='all']").prop("selected", true);
|
||||
$("#c-pid option").removeClass("hide");
|
||||
$("#c-pid option[data-type!='" + $(this).val() + "'][data-type!='all']").addClass("hide");
|
||||
$("#c-pid").data("selectpicker") && $("#c-pid").selectpicker("refresh");
|
||||
});
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+80
@@ -0,0 +1,80 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'addtabs', 'table', 'echarts', 'echarts-theme', 'template'], function ($, undefined, Backend, Datatable, Table, Echarts, undefined, Template) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 基于准备好的dom,初始化echarts实例
|
||||
var myChart = Echarts.init(document.getElementById('echart'), 'walden');
|
||||
|
||||
// 指定图表的配置项和数据
|
||||
var option = {
|
||||
title: {
|
||||
text: '',
|
||||
subtext: ''
|
||||
},
|
||||
color: [
|
||||
"#18d1b1",
|
||||
"#3fb1e3",
|
||||
"#626c91",
|
||||
"#a0a7e6",
|
||||
"#c4ebad",
|
||||
"#96dee8"
|
||||
],
|
||||
tooltip: {
|
||||
trigger: 'axis'
|
||||
},
|
||||
legend: {
|
||||
data: [__('Register user')]
|
||||
},
|
||||
toolbox: {
|
||||
show: false,
|
||||
feature: {
|
||||
magicType: {show: true, type: ['stack', 'tiled']},
|
||||
saveAsImage: {show: true}
|
||||
}
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
boundaryGap: false,
|
||||
data: Config.column
|
||||
},
|
||||
yAxis: {},
|
||||
grid: [{
|
||||
left: 'left',
|
||||
top: 'top',
|
||||
right: '10',
|
||||
bottom: 30
|
||||
}],
|
||||
series: [{
|
||||
name: __('Register user'),
|
||||
type: 'line',
|
||||
smooth: true,
|
||||
areaStyle: {
|
||||
normal: {}
|
||||
},
|
||||
lineStyle: {
|
||||
normal: {
|
||||
width: 1.5
|
||||
}
|
||||
},
|
||||
data: Config.userdata
|
||||
}]
|
||||
};
|
||||
|
||||
// 使用刚指定的配置项和数据显示图表。
|
||||
myChart.setOption(option);
|
||||
|
||||
$(window).resize(function () {
|
||||
myChart.resize();
|
||||
});
|
||||
|
||||
$(document).on("click", ".btn-refresh", function () {
|
||||
setTimeout(function () {
|
||||
myChart.resize();
|
||||
}, 0);
|
||||
});
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
return Controller;
|
||||
});
|
||||
Executable
+147
@@ -0,0 +1,147 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
/**
|
||||
* 列表 Ajax 仅保留 addtabs 参数。
|
||||
* 切勿拼接 location.search 中的 sort/filter/op 等,否则从其它模块跳入 /domain/index 时会带错字段导致列表为空。
|
||||
*/
|
||||
var buildListQuery = function () {
|
||||
var rawSearch = location.search || '';
|
||||
if (!rawSearch) {
|
||||
return '';
|
||||
}
|
||||
var addtabsMatch = rawSearch.match(/(?:[?&])addtabs=[^&]*/);
|
||||
return addtabsMatch ? ('?' + addtabsMatch[0].replace(/^[?&]/, '')) : '';
|
||||
};
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
var listQuery = buildListQuery();
|
||||
var indexUrl = 'domain/index' + listQuery;
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: indexUrl,
|
||||
add_url: 'domain/add',
|
||||
edit_url: '',
|
||||
del_url: '',
|
||||
multi_url: '',
|
||||
table: 'domain',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
sortOrder: 'desc',
|
||||
fixedColumns: true,
|
||||
fixedRightNumber: 1,
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'domain', title: __('Domain'), operate: 'LIKE', renderDefault: false},
|
||||
{field: 'full_url', title: __('Full_url'), operate: false, formatter: Table.api.formatter.url},
|
||||
{field: 'zone_status', title: __('Zone_status'), searchList: Config.zoneStatusList, formatter: Table.api.formatter.status},
|
||||
{field: 'ns_status', title: __('Ns_status'), searchList: Config.nsStatusList, formatter: Table.api.formatter.status},
|
||||
{field: 'dns_status', title: __('Dns_status'), searchList: Config.dnsStatusList, formatter: Table.api.formatter.status},
|
||||
{field: 'check_time', title: __('Check_time'), operate: 'RANGE', addclass: 'datetimerange', autocomplete: false, formatter: Table.api.formatter.datetime, sortable: true},
|
||||
{field: 'check_result', title: __('Check_result'), operate: 'LIKE', class: 'autocontent', formatter: Table.api.formatter.content},
|
||||
{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,
|
||||
buttons: [
|
||||
{
|
||||
name: 'detail',
|
||||
text: __('Detail'),
|
||||
icon: 'fa fa-list',
|
||||
classname: 'btn btn-info btn-xs btn-detail btn-dialog',
|
||||
url: 'domain/detail'
|
||||
},
|
||||
{
|
||||
name: 'detect',
|
||||
text: __('Detect'),
|
||||
icon: 'fa fa-refresh',
|
||||
classname: 'btn btn-success btn-xs btn-detect',
|
||||
url: 'domain/detect',
|
||||
refresh: true
|
||||
},
|
||||
{
|
||||
name: 'delconfirm',
|
||||
text: __('Del'),
|
||||
icon: 'fa fa-trash',
|
||||
classname: 'btn btn-danger btn-xs btn-delconfirm'
|
||||
}
|
||||
],
|
||||
formatter: Table.api.formatter.operate
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
table.on('click', '.btn-detect', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var that = this;
|
||||
var rowIndex = $(that).data('row-index');
|
||||
var row = Table.api.getrowbyindex(table, rowIndex);
|
||||
if (!row) {
|
||||
return false;
|
||||
}
|
||||
$(that).addClass('disabled');
|
||||
Fast.api.ajax({
|
||||
url: 'domain/detect/ids/' + row.id,
|
||||
type: 'post'
|
||||
}, function () {
|
||||
table.bootstrapTable('refresh');
|
||||
return false;
|
||||
}, function () {
|
||||
$(that).removeClass('disabled');
|
||||
});
|
||||
});
|
||||
|
||||
table.on('click', '.btn-delconfirm', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
var that = this;
|
||||
var rowIndex = $(that).data('row-index');
|
||||
var row = Table.api.getrowbyindex(table, rowIndex);
|
||||
if (!row) {
|
||||
return false;
|
||||
}
|
||||
Layer.prompt({
|
||||
title: __('Delete domain confirm prompt'),
|
||||
formType: 0,
|
||||
value: ''
|
||||
}, function (value, index) {
|
||||
if ($.trim(value) !== row.domain) {
|
||||
Toastr.error(__('Delete domain confirm mismatch'));
|
||||
return false;
|
||||
}
|
||||
Layer.close(index);
|
||||
Fast.api.ajax({
|
||||
url: 'domain/del',
|
||||
data: {ids: row.id, confirm_domain: $.trim(value)}
|
||||
}, function () {
|
||||
table.bootstrapTable('refresh');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
+261
@@ -0,0 +1,261 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'form', 'table'], function ($, undefined, Backend, Form, Table) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'general/attachment/index',
|
||||
add_url: 'general/attachment/add',
|
||||
edit_url: 'general/attachment/edit',
|
||||
del_url: 'general/attachment/del',
|
||||
multi_url: 'general/attachment/multi',
|
||||
table: 'attachment'
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
sortName: 'id',
|
||||
columns: [
|
||||
[
|
||||
{field: 'state', checkbox: true},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'category', title: __('Category'), operate: 'in', formatter: Table.api.formatter.label, searchList: Config.categoryList},
|
||||
{field: 'admin_id', title: __('Admin_id'), visible: false, addClass: "selectpage", extend: "data-source='auth/admin/index' data-field='nickname'"},
|
||||
{field: 'user_id', title: __('User_id'), visible: false, addClass: "selectpage", extend: "data-source='user/user/index' data-field='nickname'"},
|
||||
{field: 'preview', title: __('Preview'), formatter: Controller.api.formatter.thumb, operate: false},
|
||||
{field: 'url', title: __('Url'), formatter: Controller.api.formatter.url, visible: false},
|
||||
{field: 'filename', title: __('Filename'), sortable: true, formatter: Controller.api.formatter.filename, operate: 'like'},
|
||||
{
|
||||
field: 'filesize', title: __('Filesize'), operate: 'BETWEEN', sortable: true, formatter: function (value, row, index) {
|
||||
var size = parseFloat(value);
|
||||
var i = Math.floor(Math.log(size) / Math.log(1024));
|
||||
return (size / Math.pow(1024, i)).toFixed(i < 2 ? 0 : 2) * 1 + ' ' + ['B', 'KB', 'MB', 'GB', 'TB'][i];
|
||||
}
|
||||
},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), sortable: true},
|
||||
{field: 'imageheight', title: __('Imageheight'), sortable: true},
|
||||
{field: 'imagetype', title: __('Imagetype'), sortable: true, formatter: Table.api.formatter.search, operate: 'like'},
|
||||
{field: 'storage', title: __('Storage'), formatter: Table.api.formatter.search, operate: 'like'},
|
||||
{field: 'mimetype', title: __('Mimetype'), formatter: Controller.api.formatter.mimetype},
|
||||
{
|
||||
field: 'createtime',
|
||||
title: __('Createtime'),
|
||||
formatter: Table.api.formatter.datetime,
|
||||
operate: 'RANGE',
|
||||
addclass: 'datetimerange',
|
||||
sortable: true,
|
||||
width: 150
|
||||
},
|
||||
{
|
||||
field: 'operate',
|
||||
title: __('Operate'),
|
||||
table: table,
|
||||
events: Table.api.events.operate,
|
||||
formatter: Table.api.formatter.operate
|
||||
}
|
||||
]
|
||||
],
|
||||
});
|
||||
|
||||
// 绑定过滤事件
|
||||
$('.filter-type ul li a', table.closest(".panel-intro")).on('click', function (e) {
|
||||
$(this).closest("ul").find("li").removeClass("active");
|
||||
$(this).closest("li").addClass("active");
|
||||
var field = 'mimetype';
|
||||
var value = $(this).data("value") || '';
|
||||
var object = $("[name='" + field + "']", table.closest(".bootstrap-table").find(".commonsearch-table"));
|
||||
if (object.prop('tagName') == "SELECT") {
|
||||
$("option[value='" + value + "']", object).prop("selected", true);
|
||||
} else {
|
||||
object.val(value);
|
||||
}
|
||||
table.trigger("uncheckbox");
|
||||
table.bootstrapTable('refresh', {pageNumber: 1});
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
|
||||
// 附件归类
|
||||
$(document).on('click', '.btn-classify', function () {
|
||||
var ids = Table.api.selectedids(table);
|
||||
Layer.open({
|
||||
title: __('Classify'),
|
||||
content: Template("typetpl", {}),
|
||||
btn: [__('OK')],
|
||||
yes: function (index, layero) {
|
||||
var category = $("select[name='category']", layero).val();
|
||||
Fast.api.ajax({
|
||||
url: "general/attachment/classify",
|
||||
type: "post",
|
||||
data: {category: category, ids: ids.join(',')},
|
||||
}, function () {
|
||||
table.bootstrapTable('refresh', {});
|
||||
Layer.close(index);
|
||||
});
|
||||
},
|
||||
success: function (layero, index) {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
select: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'general/attachment/select',
|
||||
}
|
||||
});
|
||||
var urlArr = [];
|
||||
var multiple = Backend.api.query('multiple');
|
||||
multiple = multiple == 'true' ? true : false;
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
table.on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table', function (e, row) {
|
||||
if (e.type == 'check' || e.type == 'uncheck') {
|
||||
row = [row];
|
||||
} else {
|
||||
urlArr = [];
|
||||
}
|
||||
$.each(row, function (i, j) {
|
||||
if (e.type.indexOf("uncheck") > -1) {
|
||||
var index = urlArr.indexOf(j.url);
|
||||
if (index > -1) {
|
||||
urlArr.splice(index, 1);
|
||||
}
|
||||
} else {
|
||||
urlArr.indexOf(j.url) == -1 && urlArr.push(j.url);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
sortName: 'id',
|
||||
showToggle: false,
|
||||
showExport: false,
|
||||
maintainSelected: true,
|
||||
fixedColumns: true,
|
||||
fixedRightNumber: 1,
|
||||
columns: [
|
||||
[
|
||||
{field: 'state', checkbox: multiple, visible: multiple, operate: false},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'category', title: __('Category'), operate: 'in', formatter: Table.api.formatter.label, searchList: Config.categoryList},
|
||||
{field: 'admin_id', title: __('Admin_id'), formatter: Table.api.formatter.search, visible: false},
|
||||
{field: 'user_id', title: __('User_id'), formatter: Table.api.formatter.search, visible: false},
|
||||
{field: 'url', title: __('Preview'), formatter: Controller.api.formatter.thumb, operate: false},
|
||||
{field: 'filename', title: __('Filename'), sortable: true, formatter: Controller.api.formatter.filename, operate: 'like'},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), operate: false, sortable: true},
|
||||
{field: 'imageheight', title: __('Imageheight'), operate: false, sortable: true},
|
||||
{
|
||||
field: 'mimetype', title: __('Mimetype'), sortable: true, operate: 'LIKE %...%',
|
||||
process: function (value, arg) {
|
||||
return value.replace(/\*/g, '%');
|
||||
},
|
||||
formatter: Controller.api.formatter.mimetype
|
||||
},
|
||||
{field: 'createtime', title: __('Createtime'), width: 120, formatter: Table.api.formatter.datetime, datetimeFormat: 'YYYY-MM-DD', operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
{
|
||||
field: 'operate', title: __('Operate'), width: 85, events: {
|
||||
'click .btn-chooseone': function (e, value, row, index) {
|
||||
Fast.api.close($.extend({multiple: multiple}, row));
|
||||
},
|
||||
}, formatter: function () {
|
||||
return '<a href="javascript:;" class="btn btn-danger btn-chooseone btn-xs"><i class="fa fa-check"></i> ' + __('Choose') + '</a>';
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 绑定过滤事件
|
||||
$('.filter-type ul li a', table.closest(".panel-intro")).on('click', function (e) {
|
||||
$(this).closest("ul").find("li").removeClass("active");
|
||||
$(this).closest("li").addClass("active");
|
||||
var field = 'mimetype';
|
||||
var value = $(this).data("value") || '';
|
||||
var object = $("[name='" + field + "']", table.closest(".bootstrap-table").find(".commonsearch-table"));
|
||||
if (object.prop('tagName') == "SELECT") {
|
||||
$("option[value='" + value + "']", object).prop("selected", true);
|
||||
} else {
|
||||
object.val(value);
|
||||
}
|
||||
table.trigger("uncheckbox");
|
||||
table.bootstrapTable('refresh', {pageNumber: 1});
|
||||
});
|
||||
|
||||
// 选中多个
|
||||
$(document).on("click", ".btn-choose-multi", function () {
|
||||
Fast.api.close({url: urlArr.join(","), multiple: multiple});
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
require(['upload'], function (Upload) {
|
||||
$("#toolbar .faupload").data("category", function (file) {
|
||||
var category = $("ul.nav-tabs[data-field='category'] li.active a").data("value");
|
||||
return category;
|
||||
});
|
||||
Upload.api.upload($("#toolbar .faupload"), function () {
|
||||
$(".btn-refresh").trigger("click");
|
||||
});
|
||||
});
|
||||
},
|
||||
add: function () {
|
||||
//上传完成后刷新父窗口
|
||||
$(".faupload").data("upload-complete", function (files) {
|
||||
setTimeout(function () {
|
||||
window.parent.$(".btn-refresh").trigger("click");
|
||||
}, 100);
|
||||
});
|
||||
// 获取上传类别
|
||||
$("#faupload-third,#faupload-third-chunking").data("category", function (file) {
|
||||
return $("#category-third").val();
|
||||
});
|
||||
// 获取上传类别
|
||||
$("#faupload-local,#faupload-local-chunking").data("category", function (file) {
|
||||
return $("#category-local").val();
|
||||
});
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
},
|
||||
formatter: {
|
||||
thumb: function (value, row, index) {
|
||||
var html = '';
|
||||
if (row.mimetype.indexOf("image") > -1) {
|
||||
html = '<a href="' + row.fullurl + '" target="_blank"><img src="' + row.fullurl + row.thumb_style + '" alt="" style="max-height:60px;max-width:120px"></a>';
|
||||
} else {
|
||||
html = '<a href="' + row.fullurl + '" target="_blank"><img src="' + Fast.api.fixurl("ajax/icon") + "?suffix=" + row.imagetype + '" alt="" style="max-height:90px;max-width:120px"></a>';
|
||||
}
|
||||
return '<div style="width:120px;margin:0 auto;text-align:center;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;">' + html + '</div>';
|
||||
},
|
||||
url: function (value, row, index) {
|
||||
return '<a href="' + row.fullurl + '" target="_blank" class="label bg-green">' + row.url + '</a>';
|
||||
},
|
||||
filename: function (value, row, index) {
|
||||
return '<div style="width:150px;margin:0 auto;text-align:center;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;">' + Table.api.formatter.search.call(this, value, row, index) + '</div>';
|
||||
},
|
||||
mimetype: function (value, row, index) {
|
||||
return '<div style="width:80px;margin:0 auto;text-align:center;overflow:hidden;white-space: nowrap;text-overflow: ellipsis;">' + Table.api.formatter.search.call(this, value, row, index) + '</div>';
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+140
@@ -0,0 +1,140 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
$("form.edit-form").data("validator-options", {
|
||||
display: function (elem) {
|
||||
return $(elem).closest('tr').find("td:first").text();
|
||||
}
|
||||
});
|
||||
Form.api.bindevent($("form.edit-form"));
|
||||
|
||||
//不可见的元素不验证
|
||||
$("form#add-form").data("validator-options", {
|
||||
ignore: ':hidden',
|
||||
rules: {
|
||||
content: function () {
|
||||
return ['radio', 'checkbox', 'select', 'selects'].indexOf($("#add-form select[name='row[type]']").val()) > -1;
|
||||
},
|
||||
extend: function () {
|
||||
return $("#add-form select[name='row[type]']").val() == 'custom';
|
||||
}
|
||||
}
|
||||
});
|
||||
Form.api.bindevent($("form#add-form"), function (ret) {
|
||||
setTimeout(function () {
|
||||
location.reload();
|
||||
}, 1500);
|
||||
});
|
||||
|
||||
//渲染关联显示字段和存储字段
|
||||
var renderselect = function (id, data, defaultvalue) {
|
||||
var html = [];
|
||||
for (var i = 0; i < data.length; i++) {
|
||||
html.push("<option value='" + data[i].name + "' " + (defaultvalue == data[i].name ? "selected" : "") + " data-subtext='" + data[i].title + "'>" + data[i].name + "</option>");
|
||||
}
|
||||
var select = $(id);
|
||||
$(select).html(html.join(""));
|
||||
select.trigger("change");
|
||||
if (select.data("selectpicker")) {
|
||||
select.selectpicker('refresh');
|
||||
}
|
||||
};
|
||||
//关联表切换
|
||||
$(document).on('change', "#c-selectpage-table", function (e, first) {
|
||||
var that = this;
|
||||
Fast.api.ajax({
|
||||
url: "general/config/get_fields_list",
|
||||
data: {table: $(that).val()},
|
||||
}, function (data, ret) {
|
||||
renderselect("#c-selectpage-primarykey", data.fieldList, first ? $("#c-selectpage-primarykey").data("value") : '');
|
||||
renderselect("#c-selectpage-field", data.fieldList, first ? $("#c-selectpage-field").data("value") : '');
|
||||
return false;
|
||||
});
|
||||
return false;
|
||||
});
|
||||
//如果编辑模式则渲染已知数据
|
||||
if (['selectpage', 'selectpages'].indexOf($("#c-type").val()) > -1) {
|
||||
$("#c-selectpage-table").trigger("change", true);
|
||||
}
|
||||
|
||||
//切换类型时
|
||||
$(document).on("change", "#c-type", function () {
|
||||
var value = $(this).val();
|
||||
$(".tf").addClass("hidden");
|
||||
$(".tf.tf-" + value).removeClass("hidden");
|
||||
if (["selectpage", "selectpages"].indexOf(value) > -1 && $("#c-selectpage-table option").length == 1) {
|
||||
//异步加载表列表
|
||||
Fast.api.ajax({
|
||||
url: "general/config/get_table_list",
|
||||
}, function (data, ret) {
|
||||
renderselect("#c-selectpage-table", data.tableList);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
//切换显示隐藏变量字典列表
|
||||
$(document).on("change", "form#add-form select[name='row[type]']", function (e) {
|
||||
$("#add-content-container").toggleClass("hide", ['select', 'selects', 'checkbox', 'radio'].indexOf($(this).val()) > -1 ? false : true);
|
||||
});
|
||||
|
||||
//选择规则
|
||||
$(document).on("click", ".rulelist > li > a", function () {
|
||||
var ruleArr = $("#rule").val() == '' ? [] : $("#rule").val().split(";");
|
||||
var rule = $(this).data("value");
|
||||
var index = ruleArr.indexOf(rule);
|
||||
if (index > -1) {
|
||||
ruleArr.splice(index, 1);
|
||||
} else {
|
||||
ruleArr.push(rule);
|
||||
}
|
||||
$("#rule").val(ruleArr.join(";"));
|
||||
$(this).parent().toggleClass("active");
|
||||
});
|
||||
|
||||
//添加向发件人发送测试邮件按钮和方法
|
||||
$('input[name="row[mail_from]"]').parent().next().append('<a class="btn btn-info testmail">' + __('Send a test message') + '</a>');
|
||||
$(document).on("click", ".testmail", function () {
|
||||
var that = this;
|
||||
Layer.prompt({title: __('Please input your email'), formType: 0}, function (value, index) {
|
||||
Backend.api.ajax({
|
||||
url: "general/config/emailtest",
|
||||
data: $(that).closest("form").serialize() + "&receiver=" + value
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
//删除配置
|
||||
$(document).on("click", ".btn-delcfg", function () {
|
||||
var that = this;
|
||||
Layer.confirm(__('Are you sure you want to delete this item?'), {
|
||||
icon: 3,
|
||||
title: '提示'
|
||||
}, function (index) {
|
||||
Backend.api.ajax({
|
||||
url: "general/config/del",
|
||||
data: {name: $(that).data("name")}
|
||||
}, function () {
|
||||
$(that).closest("tr").remove();
|
||||
Layer.close(index);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'upload'], function ($, undefined, Backend, Table, Form, Upload) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
search: true,
|
||||
advancedSearch: true,
|
||||
pagination: true,
|
||||
extend: {
|
||||
"index_url": "general/profile/index",
|
||||
"add_url": "",
|
||||
"edit_url": "",
|
||||
"del_url": "",
|
||||
"multi_url": "",
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
columns: [
|
||||
[
|
||||
{field: 'id', title: 'ID'},
|
||||
{field: 'title', title: __('Title')},
|
||||
{field: 'url', title: __('Url'), align: 'left', formatter: Table.api.formatter.url},
|
||||
{field: 'ip', title: __('ip'), formatter:Table.api.formatter.search},
|
||||
{field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
]
|
||||
],
|
||||
commonSearch: false
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);//当内容渲染完成后
|
||||
|
||||
// 给上传按钮添加上传成功事件
|
||||
$("#faupload-avatar").data("upload-success", function (data) {
|
||||
var url = Backend.api.cdnurl(data.url);
|
||||
$(".profile-user-img").prop("src", url);
|
||||
Toastr.success("上传成功!");
|
||||
});
|
||||
|
||||
// 给表单绑定事件
|
||||
Form.api.bindevent($("#update-form"), function () {
|
||||
$("input[name='row[password]']").val('');
|
||||
var url = Backend.api.cdnurl($("#c-avatar").val());
|
||||
top.window.$(".user-panel .image img,.user-menu > a > img,.user-header > img").prop("src", url);
|
||||
return true;
|
||||
});
|
||||
},
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+423
@@ -0,0 +1,423 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'addtabs', 'adminlte', 'form'], function ($, undefined, Backend, undefined, AdminLTE, Form) {
|
||||
var Controller = {
|
||||
index: function () {
|
||||
//双击重新加载页面
|
||||
$(document).on("dblclick", ".sidebar-menu li > a", function (e) {
|
||||
$("#con_" + $(this).attr("addtabs") + " iframe").attr('src', function (i, val) {
|
||||
return val;
|
||||
});
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
//修复在移除窗口时下拉框不隐藏的BUG
|
||||
$(window).on("blur", function () {
|
||||
$("[data-toggle='dropdown']").parent().removeClass("open");
|
||||
if ($("body").hasClass("sidebar-open")) {
|
||||
$(".sidebar-toggle").trigger("click");
|
||||
}
|
||||
});
|
||||
|
||||
//快捷搜索
|
||||
$(".menuresult").width($("form.sidebar-form > .input-group").width());
|
||||
var searchResult = $(".menuresult");
|
||||
$("form.sidebar-form").on("blur", "input[name=q]", function () {
|
||||
searchResult.addClass("hide");
|
||||
}).on("focus", "input[name=q]", function () {
|
||||
if ($("a", searchResult).length > 0) {
|
||||
searchResult.removeClass("hide");
|
||||
}
|
||||
}).on("keyup", "input[name=q]", function () {
|
||||
searchResult.html('');
|
||||
var val = $(this).val();
|
||||
var html = [];
|
||||
if (val != '') {
|
||||
$("ul.sidebar-menu li a[addtabs]:not([href^='javascript:;'])").each(function () {
|
||||
if ($("span:first", this).text().indexOf(val) > -1 || $(this).attr("py").indexOf(val) > -1 || $(this).attr("pinyin").indexOf(val) > -1) {
|
||||
html.push('<a data-url="' + ($(this).attr("url") || $(this).attr("href")) + '" href="javascript:;">' + $("span:first", this).text() + '</a>');
|
||||
if (html.length >= 100) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$(searchResult).append(html.join(""));
|
||||
if (html.length > 0) {
|
||||
searchResult.removeClass("hide");
|
||||
} else {
|
||||
searchResult.addClass("hide");
|
||||
}
|
||||
});
|
||||
//快捷搜索点击事件
|
||||
$("form.sidebar-form").on('mousedown click', '.menuresult a[data-url]', function () {
|
||||
Backend.api.addtabs($(this).data("url"));
|
||||
});
|
||||
|
||||
//切换左侧sidebar显示隐藏
|
||||
$(document).on("click fa.event.toggleitem", ".sidebar-menu li > a", function (e) {
|
||||
var nextul = $(this).next("ul");
|
||||
if (nextul.length == 0 && (!$(this).parent("li").hasClass("treeview") || ($("body").hasClass("multiplenav") && $(this).parent().parent().hasClass("sidebar-menu")))) {
|
||||
$(".sidebar-menu li").not($(this).parents("li")).removeClass("active");
|
||||
}
|
||||
//当外部触发隐藏的a时,触发父辈a的事件
|
||||
if (!$(this).closest("ul").is(":visible")) {
|
||||
//如果不需要左侧的菜单栏联动可以注释下面一行即可
|
||||
$(this).closest("ul").prev().trigger("click");
|
||||
}
|
||||
|
||||
var visible = nextul.is(":visible");
|
||||
if (nextul.length == 0) {
|
||||
$(this).parents("li").addClass("active");
|
||||
$(this).closest(".treeview").addClass("treeview-open");
|
||||
} else {
|
||||
}
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
||||
//清除缓存
|
||||
$(document).on('click', "ul.wipecache li a,a.wipecache", function () {
|
||||
$.ajax({
|
||||
url: 'ajax/wipecache',
|
||||
dataType: 'json',
|
||||
data: {type: $(this).data("type")},
|
||||
cache: false,
|
||||
success: function (ret) {
|
||||
if (ret.hasOwnProperty("code")) {
|
||||
var msg = ret.hasOwnProperty("msg") && ret.msg != "" ? ret.msg : "";
|
||||
if (ret.code === 1) {
|
||||
Toastr.success(msg ? msg : __('Wipe cache completed'));
|
||||
} else {
|
||||
Toastr.error(msg ? msg : __('Wipe cache failed'));
|
||||
}
|
||||
} else {
|
||||
Toastr.error(__('Unknown data format'));
|
||||
}
|
||||
}, error: function () {
|
||||
Toastr.error(__('Network error'));
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//全屏事件
|
||||
$(document).on('click', "[data-toggle='fullscreen']", function () {
|
||||
var doc = document.documentElement;
|
||||
if ($(document.body).hasClass("full-screen")) {
|
||||
$(document.body).removeClass("full-screen");
|
||||
document.exitFullscreen ? document.exitFullscreen() : document.mozCancelFullScreen ? document.mozCancelFullScreen() : document.webkitExitFullscreen && document.webkitExitFullscreen();
|
||||
} else {
|
||||
$(document.body).addClass("full-screen");
|
||||
doc.requestFullscreen ? doc.requestFullscreen() : doc.mozRequestFullScreen ? doc.mozRequestFullScreen() : doc.webkitRequestFullscreen ? doc.webkitRequestFullscreen() : doc.msRequestFullscreen && doc.msRequestFullscreen();
|
||||
}
|
||||
});
|
||||
|
||||
var multiplenav = $("body").hasClass("multiplenav") > 0 ? true : false;
|
||||
var firstnav = $("#firstnav .nav-addtabs");
|
||||
var nav = multiplenav ? $("#secondnav .nav-addtabs") : firstnav;
|
||||
|
||||
//刷新菜单事件
|
||||
$(document).on('refresh', '.sidebar-menu', function () {
|
||||
Fast.api.ajax({
|
||||
url: 'index/index',
|
||||
data: {action: 'refreshmenu'},
|
||||
loading: false
|
||||
}, function (data) {
|
||||
$(".sidebar-menu li:not([data-rel='external'])").remove();
|
||||
$(".sidebar-menu").prepend(data.menulist);
|
||||
if (multiplenav) {
|
||||
firstnav.html(data.navlist);
|
||||
}
|
||||
$("li[role='presentation'].active a", nav).trigger('click');
|
||||
$(window).trigger("resize");
|
||||
return false;
|
||||
}, function () {
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
if (multiplenav) {
|
||||
firstnav.css("overflow", "inherit");
|
||||
//一级菜单自适应
|
||||
$(window).resize(function () {
|
||||
var siblingsWidth = 0;
|
||||
firstnav.siblings().each(function () {
|
||||
siblingsWidth += $(this).outerWidth();
|
||||
});
|
||||
firstnav.width(firstnav.parent().width() - siblingsWidth);
|
||||
firstnav.refreshAddtabs();
|
||||
});
|
||||
|
||||
//点击顶部第一级菜单栏
|
||||
firstnav.on("click", "li a", function () {
|
||||
$("li", firstnav).removeClass("active");
|
||||
$(this).closest("li").addClass("active");
|
||||
$(".sidebar-menu > li[pid]").addClass("hidden");
|
||||
if ($(this).attr("url") == "javascript:;") {
|
||||
var sonlist = $(".sidebar-menu > li[pid='" + $(this).attr("addtabs") + "']");
|
||||
sonlist.removeClass("hidden");
|
||||
var sidenav;
|
||||
var last_id = $(this).attr("last-id");
|
||||
if (last_id) {
|
||||
sidenav = $(".sidebar-menu > li[pid='" + $(this).attr("addtabs") + "'] a[addtabs='" + last_id + "']");
|
||||
} else {
|
||||
sidenav = $(".sidebar-menu > li[pid='" + $(this).attr("addtabs") + "']:first > a");
|
||||
}
|
||||
if (sidenav) {
|
||||
sidenav.attr("href") != "javascript:;" && sidenav.trigger('click');
|
||||
}
|
||||
} else {
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
var mobilenav = $(".mobilenav");
|
||||
$("#firstnav .nav-addtabs li a").each(function () {
|
||||
mobilenav.append($(this).clone().addClass("btn btn-app"));
|
||||
});
|
||||
|
||||
//点击移动端一级菜单
|
||||
mobilenav.on("click", "a", function () {
|
||||
$("a", mobilenav).removeClass("active");
|
||||
$(this).addClass("active");
|
||||
$(".sidebar-menu > li[pid]").addClass("hidden");
|
||||
if ($(this).attr("url") == "javascript:;") {
|
||||
var sonlist = $(".sidebar-menu > li[pid='" + $(this).attr("addtabs") + "']");
|
||||
sonlist.removeClass("hidden");
|
||||
}
|
||||
});
|
||||
|
||||
//点击左侧菜单栏
|
||||
$(document).on('click', '.sidebar-menu li a[addtabs]', function (e) {
|
||||
var parents = $(this).parentsUntil("ul.sidebar-menu", "li");
|
||||
var top = parents[parents.length - 1];
|
||||
var pid = $(top).attr("pid");
|
||||
if (pid) {
|
||||
var obj = $("li a[addtabs=" + pid + "]", firstnav);
|
||||
var last_id = obj.attr("last-id");
|
||||
if (!last_id || last_id != pid) {
|
||||
obj.attr("last-id", $(this).attr("addtabs"));
|
||||
if (!obj.closest("li").hasClass("active")) {
|
||||
obj.trigger("click");
|
||||
}
|
||||
}
|
||||
mobilenav.find("a").removeClass("active");
|
||||
mobilenav.find("a[addtabs='" + pid + "']").addClass("active");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//这一行需要放在点击左侧链接事件之前
|
||||
var addtabs = Config.referer ? sessionStorage.getItem("addtabs") : null;
|
||||
|
||||
//绑定tabs事件,如果需要点击强制刷新iframe,则请将iframeForceRefresh置为true,iframeForceRefreshTable只强制刷新表格
|
||||
nav.addtabs({iframeHeight: "100%", iframeForceRefresh: false, iframeForceRefreshTable: true, nav: nav});
|
||||
|
||||
if ($("ul.sidebar-menu li.active a").length > 0) {
|
||||
$("ul.sidebar-menu li.active a").trigger("click");
|
||||
} else {
|
||||
if (multiplenav) {
|
||||
$("li:first > a", firstnav).trigger("click");
|
||||
} else {
|
||||
$("ul.sidebar-menu li a[url!='javascript:;']:first").trigger("click");
|
||||
}
|
||||
}
|
||||
|
||||
//如果是刷新操作则直接返回刷新前的页面
|
||||
if (Config.referer) {
|
||||
if (Config.referer === $(addtabs).attr("url")) {
|
||||
var active = $("ul.sidebar-menu li a[addtabs=" + $(addtabs).attr("addtabs") + "]");
|
||||
if (multiplenav && active.length == 0) {
|
||||
active = $("ul li a[addtabs='" + $(addtabs).attr("addtabs") + "']");
|
||||
}
|
||||
if (active.length > 0) {
|
||||
active.trigger("click");
|
||||
} else {
|
||||
$(addtabs).appendTo(document.body).addClass("hide").trigger("click");
|
||||
}
|
||||
} else {
|
||||
//刷新页面后跳到到刷新前的页面
|
||||
Backend.api.addtabs(Config.referer);
|
||||
}
|
||||
}
|
||||
|
||||
var createCookie = function (name, value) {
|
||||
var date = new Date();
|
||||
date.setTime(date.getTime() + (365 * 24 * 60 * 60 * 1000));
|
||||
var path = Config.moduleurl;
|
||||
document.cookie = encodeURIComponent(Config.cookie.prefix + name) + "=" + encodeURIComponent(value) + "; path=" + path + "; expires=" + date.toGMTString();
|
||||
};
|
||||
|
||||
var my_skins = [
|
||||
"skin-blue",
|
||||
"skin-black",
|
||||
"skin-red",
|
||||
"skin-yellow",
|
||||
"skin-purple",
|
||||
"skin-green",
|
||||
"skin-blue-light",
|
||||
"skin-black-light",
|
||||
"skin-red-light",
|
||||
"skin-yellow-light",
|
||||
"skin-purple-light",
|
||||
"skin-green-light",
|
||||
"skin-black-blue",
|
||||
"skin-black-purple",
|
||||
"skin-black-red",
|
||||
"skin-black-green",
|
||||
"skin-black-yellow",
|
||||
"skin-black-pink",
|
||||
];
|
||||
|
||||
// 皮肤切换
|
||||
$("[data-skin]").on('click', function (e) {
|
||||
var skin = $(this).data('skin');
|
||||
if (!$("body").hasClass(skin)) {
|
||||
$("body").removeClass(my_skins.join(' ')).addClass(skin);
|
||||
var cssfile = Config.site.cdnurl + "/assets/css/skins/" + skin + ".css";
|
||||
$('head').append('<link rel="stylesheet" href="' + cssfile + '" type="text/css" />');
|
||||
$(".skin-list li.active").removeClass("active");
|
||||
$(".skin-list li a[data-skin='" + skin + "']").parent().addClass("active");
|
||||
createCookie('adminskin', skin);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
// 收起菜单栏切换
|
||||
$("[data-layout='sidebar-collapse']").on('click', function () {
|
||||
$(".sidebar-toggle").trigger("click");
|
||||
});
|
||||
|
||||
// 切换子菜单显示和菜单小图标的显示
|
||||
$("[data-menu='show-submenu']").on('click', function () {
|
||||
createCookie('show_submenu', $(this).prop("checked") ? 1 : 0);
|
||||
location.reload();
|
||||
});
|
||||
|
||||
// 右侧控制栏切换
|
||||
$("[data-controlsidebar]").on('click', function () {
|
||||
var cls = $(this).data('controlsidebar');
|
||||
$("body").toggleClass(cls);
|
||||
AdminLTE.layout.fixSidebar();
|
||||
//Fix the problem with right sidebar and layout boxed
|
||||
if (cls == "layout-boxed")
|
||||
AdminLTE.controlSidebar._fix($(".control-sidebar-bg"));
|
||||
if ($('body').hasClass('fixed') && cls == 'fixed') {
|
||||
AdminLTE.pushMenu.expandOnHover();
|
||||
AdminLTE.layout.activate();
|
||||
}
|
||||
AdminLTE.controlSidebar._fix($(".control-sidebar-bg"));
|
||||
AdminLTE.controlSidebar._fix($(".control-sidebar"));
|
||||
var slide = !AdminLTE.options.controlSidebarOptions.slide;
|
||||
AdminLTE.options.controlSidebarOptions.slide = slide;
|
||||
if (!slide)
|
||||
$('.control-sidebar').removeClass('control-sidebar-open');
|
||||
});
|
||||
|
||||
// 右侧控制栏背景切换
|
||||
$("[data-sidebarskin='toggle']").on('click', function () {
|
||||
var sidebar = $(".control-sidebar");
|
||||
if (sidebar.hasClass("control-sidebar-dark")) {
|
||||
sidebar.removeClass("control-sidebar-dark")
|
||||
sidebar.addClass("control-sidebar-light")
|
||||
} else {
|
||||
sidebar.removeClass("control-sidebar-light")
|
||||
sidebar.addClass("control-sidebar-dark")
|
||||
}
|
||||
});
|
||||
|
||||
// 菜单栏展开或收起
|
||||
$("[data-enable='expandOnHover']").on('click', function () {
|
||||
$.AdminLTE.options.sidebarExpandOnHover = $(this).prop("checked") ? 1 : 0;
|
||||
localStorage.setItem('sidebarExpandOnHover', $.AdminLTE.options.sidebarExpandOnHover);
|
||||
AdminLTE.pushMenu.expandOnHover();
|
||||
$.AdminLTE.layout.fixSidebar();
|
||||
});
|
||||
|
||||
// 切换菜单栏
|
||||
$(document).on("click", ".sidebar-toggle", function () {
|
||||
setTimeout(function(){
|
||||
var value = $("body").hasClass("sidebar-collapse") ? 1 : 0;
|
||||
setTimeout(function () {
|
||||
$(window).trigger("resize");
|
||||
}, 300);
|
||||
createCookie('sidebar_collapse', value);
|
||||
}, 0);
|
||||
});
|
||||
|
||||
// 切换多级菜单
|
||||
$(document).on("click", "[data-config='multiplenav']", function () {
|
||||
var value = $(this).prop("checked") ? 1 : 0;
|
||||
createCookie('multiplenav', value);
|
||||
location.reload();
|
||||
});
|
||||
|
||||
// 切换多选项卡
|
||||
$(document).on("click", "[data-config='multipletab']", function () {
|
||||
var value = $(this).prop("checked") ? 1 : 0;
|
||||
$("body").toggleClass("multipletab", value);
|
||||
createCookie('multipletab', value);
|
||||
});
|
||||
|
||||
// 重设选项
|
||||
if ($('body').hasClass('fixed')) {
|
||||
$("[data-layout='fixed']").attr('checked', 'checked');
|
||||
}
|
||||
if ($('body').hasClass('layout-boxed')) {
|
||||
$("[data-layout='layout-boxed']").attr('checked', 'checked');
|
||||
}
|
||||
if ($('body').hasClass('sidebar-collapse')) {
|
||||
$("[data-layout='sidebar-collapse']").attr('checked', 'checked');
|
||||
}
|
||||
if ($('ul.sidebar-menu').hasClass('show-submenu')) {
|
||||
$("[data-menu='show-submenu']").attr('checked', 'checked');
|
||||
}
|
||||
|
||||
var sidebarExpandOnHover = localStorage.getItem('sidebarExpandOnHover');
|
||||
if (sidebarExpandOnHover == '1') {
|
||||
$("[data-enable='expandOnHover']").trigger("click");
|
||||
}
|
||||
|
||||
$.each(my_skins, function (i, j) {
|
||||
if ($("body").hasClass(j)) {
|
||||
$(".skin-list li a[data-skin='" + j + "']").parent().addClass("active");
|
||||
}
|
||||
});
|
||||
|
||||
$(window).resize();
|
||||
|
||||
},
|
||||
login: function () {
|
||||
var lastlogin = localStorage.getItem("lastlogin");
|
||||
if (lastlogin) {
|
||||
lastlogin = JSON.parse(lastlogin);
|
||||
$("#profile-img").attr("src", Backend.api.cdnurl(lastlogin.avatar));
|
||||
$("#profile-name").val(lastlogin.username);
|
||||
}
|
||||
|
||||
//让错误提示框居中
|
||||
Fast.config.toastr.positionClass = "toast-top-center";
|
||||
|
||||
//本地验证未通过时提示
|
||||
$("#login-form").data("validator-options", {
|
||||
invalid: function (form, errors) {
|
||||
$.each(errors, function (i, j) {
|
||||
Toastr.error(j);
|
||||
});
|
||||
},
|
||||
target: '#errtips'
|
||||
});
|
||||
|
||||
//为表单绑定事件
|
||||
Form.api.bindevent($("#login-form"), function (data) {
|
||||
localStorage.setItem("lastlogin", JSON.stringify({
|
||||
id: data.id,
|
||||
username: data.username,
|
||||
avatar: data.avatar
|
||||
}));
|
||||
location.href = Backend.api.fixurl(data.url);
|
||||
}, function (data) {
|
||||
$("input[name=captcha]").next(".input-group-addon").find("img").trigger("click");
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
return Controller;
|
||||
});
|
||||
Executable
+884
@@ -0,0 +1,884 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'split.link/index' + location.search,
|
||||
add_url: 'split.link/add',
|
||||
edit_url: 'split.link/edit',
|
||||
del_url: 'split.link/del',
|
||||
multi_url: 'split.link/multi',
|
||||
table: 'split_link',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
sortOrder: 'desc',
|
||||
fixedColumns: true,
|
||||
fixedRightNumber: 1,
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'countries_text', title: __('Countries'), operate: false, formatter: Table.api.formatter.content},
|
||||
{
|
||||
field: 'link_code',
|
||||
title: __('Link_code'),
|
||||
operate: 'LIKE',
|
||||
formatter: Controller.api.formatter.linkCode
|
||||
},
|
||||
{field: 'description', title: __('Description'), operate: 'LIKE', class: 'autocontent', formatter: Table.api.formatter.content},
|
||||
{
|
||||
field: 'auto_reply_text',
|
||||
title: __('Reply statements column'),
|
||||
operate: false,
|
||||
formatter: Controller.api.formatter.autoReplyText
|
||||
},
|
||||
{field: 'ip_protect', title: __('Ip_protect'), searchList: Config.ipProtectList, formatter: Table.api.formatter.status},
|
||||
{field: 'random_shuffle', title: __('Random_shuffle'), searchList: Config.randomShuffleList, formatter: Table.api.formatter.status},
|
||||
{field: 'status', title: __('Status'), searchList: Config.statusList, formatter: Table.api.formatter.status},
|
||||
{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,
|
||||
buttons: [
|
||||
{
|
||||
name: 'autoreply',
|
||||
text: __('Auto reply'),
|
||||
title: __('Auto reply'),
|
||||
icon: 'fa fa-commenting-o',
|
||||
classname: 'btn btn-warning btn-xs btn-split-autoreply',
|
||||
url: 'javascript:;'
|
||||
},
|
||||
{
|
||||
name: 'pixel',
|
||||
text: __('Pixel config'),
|
||||
title: __('Pixel config'),
|
||||
icon: 'fa fa-bullseye',
|
||||
classname: 'btn btn-info btn-xs btn-split-pixel',
|
||||
url: 'javascript:;'
|
||||
}
|
||||
],
|
||||
formatter: Table.api.formatter.operate
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
table.on('click', '.btn-copy-split-link', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var linkCode = $.trim($(this).data('link-code') || '');
|
||||
if (!linkCode) {
|
||||
return false;
|
||||
}
|
||||
Controller.api.openCopyModal(linkCode);
|
||||
});
|
||||
|
||||
table.on('click', '.btn-copy-link-code-inline', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var linkCode = $.trim($(this).data('link-code') || '');
|
||||
if (linkCode) {
|
||||
Controller.api.copyText(linkCode);
|
||||
}
|
||||
});
|
||||
|
||||
table.on('click', '.btn-split-autoreply', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
var rowIndex = $(this).data('row-index');
|
||||
var row = Table.api.getrowbyindex(table, rowIndex);
|
||||
if (!row || !row.id) {
|
||||
return false;
|
||||
}
|
||||
Controller.api.openAutoReplyModal(row);
|
||||
});
|
||||
|
||||
table.on('click', '.btn-split-pixel', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
e.stopImmediatePropagation();
|
||||
var rowIndex = $(this).data('row-index');
|
||||
var row = Table.api.getrowbyindex(table, rowIndex);
|
||||
if (!row || !row.id) {
|
||||
return false;
|
||||
}
|
||||
Controller.api.openPixelModal(row);
|
||||
});
|
||||
|
||||
Controller.api.bindAutoReplyPreviewTips(table);
|
||||
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
Controller.api.bindLinkCodeInput();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
/**
|
||||
* 规范化后台跨模块跳转 URL,避免在 split.link 页面内相对解析成 split.link/domain
|
||||
*
|
||||
* @param {string} url API 返回的地址
|
||||
* @param {string} fallback 相对 admin 模块根路径,如 domain / domain/add
|
||||
* @return {string}
|
||||
*/
|
||||
normalizeAdminRouteUrl: function (url, fallback) {
|
||||
fallback = fallback || 'domain';
|
||||
url = $.trim(url || '');
|
||||
if (url === '' || /split\.link\/domain/i.test(url)) {
|
||||
return fallback;
|
||||
}
|
||||
var modulePrefix = (Config.moduleurl || '').replace(/\/+$/, '');
|
||||
if (url.indexOf('://') !== -1) {
|
||||
try {
|
||||
var parsed = new URL(url, window.location.origin);
|
||||
var path = (parsed.pathname || '').replace(/\/+$/, '');
|
||||
if (modulePrefix && path.indexOf(modulePrefix) === 0) {
|
||||
path = path.slice(modulePrefix.length);
|
||||
}
|
||||
path = path.replace(/^\/+/, '');
|
||||
return /^split\.link\/domain/i.test(path) ? fallback : (path || fallback);
|
||||
} catch (e) {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
if (url.charAt(0) === '/') {
|
||||
url = url.replace(/^\/+/, '');
|
||||
var moduleKey = modulePrefix.replace(/^\/+/, '');
|
||||
if (moduleKey && url.indexOf(moduleKey + '/') === 0) {
|
||||
url = url.slice(moduleKey.length + 1);
|
||||
}
|
||||
}
|
||||
return /^split\.link\/domain/i.test(url) ? fallback : url;
|
||||
},
|
||||
/** 弹窗样式(仅注入一次) */
|
||||
modalStyleInjected: false,
|
||||
pixelModalStyleInjected: false,
|
||||
injectModalStyles: function () {
|
||||
if (Controller.api.modalStyleInjected) {
|
||||
return;
|
||||
}
|
||||
Controller.api.modalStyleInjected = true;
|
||||
var css = [
|
||||
'.split-link-copy-modal{padding:16px 20px;box-sizing:border-box;}',
|
||||
'.split-link-copy-modal .form-group{margin-bottom:16px;}',
|
||||
'.split-link-copy-modal .control-label{display:block;font-weight:600;color:#444;margin-bottom:8px;}',
|
||||
'.split-link-copy-modal .split-link-code-row{display:flex;align-items:center;flex-wrap:wrap;gap:8px;}',
|
||||
'.split-link-copy-modal .split-link-code-value{font-size:18px;font-weight:600;color:#337ab7;text-decoration:underline;word-break:break-all;}',
|
||||
'.split-link-copy-modal .split-domain-tabs{margin-bottom:0;border-bottom:1px solid #ddd;}',
|
||||
'.split-link-copy-modal .split-domain-tab-box{border:1px solid #ddd;border-top:none;border-radius:0 0 4px 4px;background:#fafafa;overflow:hidden;}',
|
||||
'.split-link-copy-modal .split-domain-tab-box .tab-pane{max-height:280px;overflow-y:auto;overflow-x:hidden;padding:10px 12px;margin:0;}',
|
||||
'.split-link-copy-modal .split-domain-list{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;align-items:stretch;}',
|
||||
'.split-link-copy-modal .split-domain-item{border:1px solid #e8e8e8;border-radius:4px;background:#fff;transition:border-color .2s,box-shadow .2s;height:100%;min-width:0;}',
|
||||
'.split-link-copy-modal .split-domain-item:hover{border-color:#b8d4f0;}',
|
||||
'.split-link-copy-modal .split-domain-item.is-checked{border-color:#337ab7;box-shadow:0 0 0 1px rgba(51,122,183,.15);}',
|
||||
'.split-link-copy-modal .split-domain-item-label{display:flex;align-items:flex-start;gap:8px;margin:0;padding:8px 10px;cursor:pointer;font-weight:normal;width:100%;height:100%;box-sizing:border-box;}',
|
||||
'.split-link-copy-modal .split-domain-item-label input[type=radio]{margin:3px 0 0;flex-shrink:0;}',
|
||||
'.split-link-copy-modal .split-domain-item-body{flex:1;min-width:0;display:flex;flex-direction:column;gap:5px;}',
|
||||
'.split-link-copy-modal .split-domain-name{font-size:13px;font-weight:600;color:#333;word-break:break-all;line-height:1.4;}',
|
||||
'.split-link-copy-modal .split-domain-status{display:flex;flex-direction:column;align-items:flex-start;gap:4px;}',
|
||||
'.split-link-copy-modal .split-domain-status .label{font-size:10px;font-weight:normal;padding:2px 6px;line-height:1.3;white-space:nowrap;margin:0;display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;}',
|
||||
'.split-link-copy-modal .split-domain-empty{margin:0;padding:20px 12px;color:#999;text-align:center;line-height:1.6;grid-column:1/-1;}',
|
||||
'.split-link-copy-modal .split-tip-box{margin:12px 0;padding:10px 12px;background:#f8f9fa;border-left:3px solid #337ab7;border-radius:0 4px 4px 0;line-height:1.6;color:#666;}',
|
||||
'.split-link-copy-modal .split-generated-url{font-size:12px;}',
|
||||
'.split-link-copy-modal .split-modal-footer{margin-top:16px;padding-top:12px;border-top:1px solid #eee;}'
|
||||
].join('');
|
||||
$('<style id="split-link-copy-modal-style" type="text/css"></style>').text(css).appendTo('head');
|
||||
},
|
||||
injectPixelModalStyles: function () {
|
||||
if (Controller.api.pixelModalStyleInjected) {
|
||||
return;
|
||||
}
|
||||
Controller.api.pixelModalStyleInjected = true;
|
||||
var css = [
|
||||
'.split-pixel-layer .layui-layer-content{padding:0;overflow:hidden;max-height:calc(86vh - 108px);}',
|
||||
'.split-pixel-layer .layui-layer-btn{border-top:1px solid #e8e8e8;background:#fafafa;}',
|
||||
'.split-pixel-modal{padding:18px 22px 14px;box-sizing:border-box;display:flex;flex-direction:column;min-height:480px;height:calc(86vh - 108px);max-height:720px;}',
|
||||
'.split-pixel-modal .split-pixel-tip{margin:0 0 14px;padding:10px 14px;background:#f0f7ff;border-left:3px solid #337ab7;border-radius:0 4px 4px 0;color:#555;font-size:13px;line-height:1.65;}',
|
||||
'.split-pixel-modal .split-pixel-tabs{margin-bottom:0;border-bottom:1px solid #ddd;}',
|
||||
'.split-pixel-modal .split-pixel-tabs>li>a{padding:9px 18px;font-weight:600;color:#666;}',
|
||||
'.split-pixel-modal .split-pixel-tabs>li.active>a{color:#337ab7;border-bottom-color:#fff;}',
|
||||
'.split-pixel-modal .split-pixel-tab-content{flex:1;display:flex;flex-direction:column;min-height:0;padding-top:14px;}',
|
||||
'.split-pixel-modal .split-pixel-tab-content>.tab-pane{display:none;flex:1;flex-direction:column;min-height:0;}',
|
||||
'.split-pixel-modal .split-pixel-tab-content>.tab-pane.active{display:flex;}',
|
||||
'.split-pixel-modal .split-pixel-list{flex:1;display:flex;flex-direction:column;min-height:0;}',
|
||||
'.split-pixel-modal .split-pixel-toolbar{margin-bottom:12px;display:flex;align-items:center;justify-content:space-between;flex-shrink:0;}',
|
||||
'.split-pixel-modal .split-pixel-toolbar .btn-add-pixel-row{font-weight:600;padding:6px 14px;}',
|
||||
'.split-pixel-modal .split-pixel-table-wrap{flex:1;min-height:320px;overflow:auto;border:1px solid #dce3eb;border-radius:6px;background:#fff;box-shadow:inset 0 1px 2px rgba(0,0,0,.03);}',
|
||||
'.split-pixel-modal .split-pixel-table{margin-bottom:0;font-size:13px;table-layout:auto;width:100%;}',
|
||||
'.split-pixel-modal .split-pixel-table thead th{background:linear-gradient(180deg,#f8fafc 0%,#eef2f6 100%);white-space:nowrap;vertical-align:middle;text-align:center;font-weight:600;color:#444;border-bottom:2px solid #dce3eb;padding:10px 8px;position:sticky;top:0;z-index:3;box-shadow:0 1px 0 #dce3eb;}',
|
||||
'.split-pixel-modal .split-pixel-table tbody td{vertical-align:middle;padding:10px 8px;border-color:#edf1f5;}',
|
||||
'.split-pixel-modal .split-pixel-table tbody tr.split-pixel-row:hover{background:#f7fbff;}',
|
||||
'.split-pixel-modal .split-pixel-table tbody tr.split-pixel-row:nth-child(even){background:#fbfcfd;}',
|
||||
'.split-pixel-modal .split-pixel-table tbody tr.split-pixel-row:nth-child(even):hover{background:#f7fbff;}',
|
||||
'.split-pixel-modal .split-pixel-table .form-control{min-width:0;height:32px;line-height:1.42857143;padding:6px 10px;border-radius:4px;}',
|
||||
'.split-pixel-modal .split-pixel-table .pixel-id{min-width:130px;}',
|
||||
'.split-pixel-modal .split-pixel-table .pixel-access-token{min-width:150px;}',
|
||||
'.split-pixel-modal .split-pixel-table .pixel-test-code{min-width:100px;}',
|
||||
'.split-pixel-modal .split-pixel-table th.pixel-event-col,.split-pixel-modal .split-pixel-table td.pixel-event-cell{min-width:148px;width:148px;}',
|
||||
'.split-pixel-modal .split-pixel-table .pixel-event{width:100%;min-width:132px;max-width:none;padding-right:28px;text-overflow:clip;overflow:visible;white-space:nowrap;cursor:pointer;}',
|
||||
'.split-pixel-modal .split-pixel-empty-row td{padding:48px 16px;color:#999;text-align:center;font-size:13px;background:#fafbfc;}',
|
||||
'.split-pixel-modal .split-pixel-sort-group{width:118px;margin:0 auto;}',
|
||||
'.split-pixel-modal .split-pixel-sort-group .form-control{text-align:center;padding-left:4px;padding-right:4px;}',
|
||||
'.split-pixel-modal .pixel-switch-wrap{text-align:center;}',
|
||||
'.split-pixel-modal .pixel-switch-wrap input[type=checkbox]{width:17px;height:17px;margin:0;cursor:pointer;vertical-align:middle;}',
|
||||
'.split-pixel-modal .pixel-row-index{display:inline-block;min-width:26px;height:26px;line-height:26px;border-radius:13px;background:#e8eef5;color:#4a6785;font-weight:600;font-size:12px;}',
|
||||
'.split-pixel-modal .btn-pixel-row-remove{padding:4px 8px;border-radius:4px;}',
|
||||
'.split-pixel-modal .col-token{min-width:160px;}'
|
||||
].join('');
|
||||
$('<style id="split-pixel-modal-style" type="text/css"></style>').text(css).appendTo('head');
|
||||
},
|
||||
formatter: {
|
||||
/**
|
||||
* 回复语:列表最多 50 字 + ...,悬停保留换行显示全文
|
||||
*/
|
||||
autoReplyText: function (value, row, index) {
|
||||
var full = (row.auto_reply != null && row.auto_reply !== '') ? String(row.auto_reply) : '';
|
||||
if (full === '') {
|
||||
return '<span class="text-muted">-</span>';
|
||||
}
|
||||
var preview = value != null && value !== '' ? String(value) : full;
|
||||
var safePreview = Fast.api.escape(preview);
|
||||
var encFull = encodeURIComponent(full);
|
||||
return '<span class="split-auto-reply-preview" data-full="' + encFull + '" style="display:inline-block;max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;cursor:default;">'
|
||||
+ safePreview + '</span>';
|
||||
},
|
||||
/**
|
||||
* 分流链接列:链接样式 + COPY 图标,点击链接打开弹窗
|
||||
*/
|
||||
linkCode: function (value) {
|
||||
value = value == null ? '' : value.toString();
|
||||
if (value === '') {
|
||||
return '-';
|
||||
}
|
||||
var safe = Fast.api.escape(value);
|
||||
return '<span class="split-link-code-cell">'
|
||||
+ '<a href="javascript:;" class="btn-copy-split-link split-link-code-link" data-link-code="' + safe + '" style="font-weight:600;color:#337ab7;text-decoration:underline;">' + safe + '</a>'
|
||||
+ ' <a href="javascript:;" class="btn-copy-link-code-inline text-primary" data-link-code="' + safe + '" title="' + __('Copy') + '"><i class="fa fa-copy"></i></a>'
|
||||
+ '</span>';
|
||||
}
|
||||
},
|
||||
openCopyModal: function (linkCode) {
|
||||
Controller.api.loadCopyModalData(function (data) {
|
||||
Controller.api.renderCopyModal(linkCode, data);
|
||||
});
|
||||
},
|
||||
/** 回复语列悬停提示(保留换行) */
|
||||
autoReplyTipIndex: null,
|
||||
bindAutoReplyPreviewTips: function (table) {
|
||||
table.off('mouseenter.splitAutoReply mouseleave.splitAutoReply')
|
||||
.on('mouseenter.splitAutoReply', '.split-auto-reply-preview', function () {
|
||||
var enc = $(this).attr('data-full');
|
||||
if (!enc) {
|
||||
return;
|
||||
}
|
||||
var full = '';
|
||||
try {
|
||||
full = decodeURIComponent(enc);
|
||||
} catch (e) {
|
||||
return;
|
||||
}
|
||||
var html = '<div style="white-space:pre-wrap;word-break:break-word;padding:10px 12px;line-height:1.6;max-width:420px;font-size:13px;text-align:left;">'
|
||||
+ Controller.api.escapeHtmlWithNewlines(full) + '</div>';
|
||||
Controller.api.autoReplyTipIndex = Layer.tips(html, this, {
|
||||
tips: [1, ''],
|
||||
time: 0,
|
||||
maxWidth: 450
|
||||
});
|
||||
})
|
||||
.on('mouseleave.splitAutoReply', '.split-auto-reply-preview', function () {
|
||||
if (Controller.api.autoReplyTipIndex != null) {
|
||||
Layer.close(Controller.api.autoReplyTipIndex);
|
||||
Controller.api.autoReplyTipIndex = null;
|
||||
}
|
||||
});
|
||||
},
|
||||
escapeHtmlWithNewlines: function (text) {
|
||||
return $('<div/>').text(text).html().replace(/\n/g, '<br>');
|
||||
},
|
||||
/**
|
||||
* 打开自动回复弹窗
|
||||
*
|
||||
* @param {object} row 列表行数据
|
||||
*/
|
||||
openAutoReplyModal: function (row) {
|
||||
Fast.api.ajax({
|
||||
url: 'split.link/autoreply/ids/' + row.id,
|
||||
type: 'get'
|
||||
}, function (data, ret) {
|
||||
var info = ret.data || data || {};
|
||||
Controller.api.renderAutoReplyModal(row.id, info);
|
||||
return false;
|
||||
});
|
||||
},
|
||||
renderAutoReplyModal: function (linkId, info) {
|
||||
var linkCode = Fast.api.escape(info.link_code || '');
|
||||
var autoReply = info.auto_reply || '';
|
||||
var html = [
|
||||
'<div class="split-auto-reply-modal" style="padding:16px 20px;">',
|
||||
' <div class="form-group">',
|
||||
' <label class="control-label">' + __('Link_code') + '</label>',
|
||||
' <p class="form-control-static" style="font-size:16px;font-weight:600;color:#337ab7;margin:0;">' + linkCode + '</p>',
|
||||
' </div>',
|
||||
' <div class="form-group" style="margin-bottom:0;">',
|
||||
' <label class="control-label" for="split-auto-reply-text">' + __('Reply statements') + '</label>',
|
||||
' <p class="help-block" style="margin-top:0;">' + __('Reply statements tip') + '</p>',
|
||||
' <textarea id="split-auto-reply-text" class="form-control" rows="10" placeholder="">' + Fast.api.escape(autoReply) + '</textarea>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
Layer.open({
|
||||
type: 1,
|
||||
title: __('Auto reply'),
|
||||
area: ['520px', 'auto'],
|
||||
shadeClose: false,
|
||||
content: html,
|
||||
btn: [__('OK'), __('Close')],
|
||||
yes: function (index, layero) {
|
||||
var text = layero.find('#split-auto-reply-text').val();
|
||||
Fast.api.ajax({
|
||||
url: 'split.link/autoreply/ids/' + linkId,
|
||||
type: 'post',
|
||||
data: {auto_reply: text}
|
||||
}, function () {
|
||||
Layer.close(index);
|
||||
Toastr.success(__('Auto reply saved'));
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
pixelRowUid: function (prefix) {
|
||||
return prefix + '_' + Date.now().toString(36) + '_' + Math.random().toString(36).slice(2, 8);
|
||||
},
|
||||
openPixelModal: function (row) {
|
||||
Fast.api.ajax({
|
||||
url: 'split.link/pixel/ids/' + row.id,
|
||||
type: 'get'
|
||||
}, function (data, ret) {
|
||||
var info = ret.data || data || {};
|
||||
Controller.api.renderPixelModal(row.id, info);
|
||||
return false;
|
||||
});
|
||||
},
|
||||
renderPixelModal: function (linkId, info) {
|
||||
Controller.api.injectPixelModalStyles();
|
||||
var eventOptions = $.isArray(info.event_options) ? info.event_options : [
|
||||
'PageView', 'Lead', 'Contact', 'AddToCart', 'Purchase', 'Subscribe'
|
||||
];
|
||||
var fbRows = $.isArray(info.facebook) ? info.facebook : [];
|
||||
var tkRows = $.isArray(info.tiktok) ? info.tiktok : [];
|
||||
|
||||
var html = [
|
||||
'<div class="split-pixel-modal">',
|
||||
' <div class="split-pixel-tip">' + __('Pixel config tip') + '</div>',
|
||||
' <ul class="nav nav-tabs split-pixel-tabs" role="tablist">',
|
||||
' <li role="presentation" class="active"><a href="#split-pixel-fb" role="tab" data-toggle="tab"><i class="fa fa-facebook-square"></i> ' + __('Facebook Pixel') + '</a></li>',
|
||||
' <li role="presentation"><a href="#split-pixel-tk" role="tab" data-toggle="tab"><i class="fa fa-music"></i> ' + __('TikTok Pixel') + '</a></li>',
|
||||
' </ul>',
|
||||
' <div class="tab-content split-pixel-tab-content">',
|
||||
' <div role="tabpanel" class="tab-pane active" id="split-pixel-fb">',
|
||||
Controller.api.buildPixelListShell('facebook', __('Add FB Pixel')),
|
||||
' </div>',
|
||||
' <div role="tabpanel" class="tab-pane" id="split-pixel-tk">',
|
||||
Controller.api.buildPixelListShell('tiktok', __('Add TK Pixel')),
|
||||
' </div>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
Layer.open({
|
||||
type: 1,
|
||||
title: __('Pixel config') + ' - ' + Fast.api.escape(info.link_code || ''),
|
||||
area: ['1140px', '86vh'],
|
||||
maxmin: true,
|
||||
shadeClose: false,
|
||||
content: html,
|
||||
btn: [__('OK'), __('Close')],
|
||||
success: function (layero) {
|
||||
layero.addClass('split-pixel-layer');
|
||||
var $box = layero.find('.split-pixel-modal');
|
||||
var fillRows = function (platform, rows) {
|
||||
var $list = $box.find('.split-pixel-list[data-platform="' + platform + '"]');
|
||||
var $body = $list.find('tbody.split-pixel-list-body');
|
||||
$body.find('tr.split-pixel-row').remove();
|
||||
$.each(rows, function (_, rowData) {
|
||||
$body.append(Controller.api.buildPixelRowHtml(platform, rowData, eventOptions));
|
||||
});
|
||||
Controller.api.syncPixelListEmpty($list);
|
||||
};
|
||||
fillRows('facebook', fbRows);
|
||||
fillRows('tiktok', tkRows);
|
||||
|
||||
$box.on('click', '.btn-add-pixel-row', function () {
|
||||
var platform = $(this).data('platform');
|
||||
var $list = $box.find('.split-pixel-list[data-platform="' + platform + '"]');
|
||||
var $body = $list.find('tbody.split-pixel-list-body');
|
||||
var sortVal = $body.find('tr.split-pixel-row').length;
|
||||
$body.append(Controller.api.buildPixelRowHtml(platform, {
|
||||
id: Controller.api.pixelRowUid(platform === 'facebook' ? 'fb' : 'tk'),
|
||||
enabled: 1,
|
||||
server_postback: 0,
|
||||
pixel_id: '',
|
||||
access_token: '',
|
||||
test_code: '',
|
||||
event: 'PageView',
|
||||
sort: sortVal
|
||||
}, eventOptions));
|
||||
Controller.api.syncPixelListEmpty($list);
|
||||
var $wrap = $list.find('.split-pixel-table-wrap');
|
||||
if ($wrap.length) {
|
||||
$wrap.scrollTop($wrap[0].scrollHeight);
|
||||
}
|
||||
});
|
||||
|
||||
$box.on('click', '.btn-pixel-sort-up', function () {
|
||||
var $row = $(this).closest('tr.split-pixel-row');
|
||||
var $input = $row.find('.pixel-sort-input');
|
||||
$input.val(Math.max(0, (parseInt($input.val(), 10) || 0) + 1));
|
||||
});
|
||||
$box.on('click', '.btn-pixel-sort-down', function () {
|
||||
var $row = $(this).closest('tr.split-pixel-row');
|
||||
var $input = $row.find('.pixel-sort-input');
|
||||
$input.val(Math.max(0, (parseInt($input.val(), 10) || 0) - 1));
|
||||
});
|
||||
$box.on('click', '.btn-pixel-row-remove', function () {
|
||||
var $row = $(this).closest('tr.split-pixel-row');
|
||||
var $list = $row.closest('.split-pixel-list');
|
||||
$row.remove();
|
||||
Controller.api.syncPixelListEmpty($list);
|
||||
});
|
||||
$box.on('change', '.pixel-event', function () {
|
||||
var val = $(this).val() || '';
|
||||
$(this).attr('title', val);
|
||||
});
|
||||
},
|
||||
yes: function (index, layero) {
|
||||
var payload = Controller.api.collectPixelPayload(layero.find('.split-pixel-modal'));
|
||||
var invalid = false;
|
||||
$.each(payload.facebook.concat(payload.tiktok), function (_, item) {
|
||||
if (!$.trim(item.pixel_id)) {
|
||||
invalid = true;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (invalid) {
|
||||
Toastr.error(__('Pixel ID required'));
|
||||
return false;
|
||||
}
|
||||
Fast.api.ajax({
|
||||
url: 'split.link/pixel/ids/' + linkId,
|
||||
type: 'post',
|
||||
data: {pixel_config: payload}
|
||||
}, function () {
|
||||
Layer.close(index);
|
||||
Toastr.success(__('Pixel config saved'));
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
},
|
||||
buildPixelListShell: function (platform, addBtnText) {
|
||||
return [
|
||||
'<div class="split-pixel-list" data-platform="' + platform + '">',
|
||||
' <div class="split-pixel-toolbar">',
|
||||
' <button type="button" class="btn btn-success btn-sm btn-add-pixel-row" data-platform="' + platform + '">',
|
||||
' <i class="fa fa-plus"></i> ' + addBtnText,
|
||||
' </button>',
|
||||
' </div>',
|
||||
' <div class="table-responsive split-pixel-table-wrap">',
|
||||
' <table class="table table-bordered table-hover split-pixel-table">',
|
||||
' <thead>',
|
||||
' <tr>',
|
||||
' <th width="52">' + __('Pixel row index') + '</th>',
|
||||
' <th width="58" title="' + __('Pixel enabled') + '">' + __('Pixel enabled') + '</th>',
|
||||
' <th width="78" title="' + __('Server postback') + '">' + __('Server postback') + '</th>',
|
||||
' <th width="140">' + __('Pixel ID') + ' <span class="text-danger">*</span></th>',
|
||||
' <th class="pixel-event-col">' + __('Pixel event') + '</th>',
|
||||
' <th class="col-token">' + __('Access Token') + '</th>',
|
||||
' <th width="108">' + __('Test code') + '</th>',
|
||||
' <th width="124">' + __('Pixel sort') + '</th>',
|
||||
' <th width="58">' + __('Operate') + '</th>',
|
||||
' </tr>',
|
||||
' </thead>',
|
||||
' <tbody class="split-pixel-list-body">',
|
||||
' <tr class="split-pixel-empty-row"><td colspan="9"><i class="fa fa-inbox" style="margin-right:6px;opacity:.5;"></i>' + __('Pixel list empty') + '</td></tr>',
|
||||
' </tbody>',
|
||||
' </table>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('');
|
||||
},
|
||||
syncPixelListEmpty: function ($list) {
|
||||
var $body = $list.find('tbody.split-pixel-list-body');
|
||||
var $rows = $body.find('tr.split-pixel-row');
|
||||
$body.find('tr.split-pixel-empty-row').toggle($rows.length === 0);
|
||||
$rows.each(function (idx) {
|
||||
$(this).find('.pixel-row-index').text(String(idx + 1));
|
||||
});
|
||||
},
|
||||
buildPixelRowHtml: function (platform, row, eventOptions) {
|
||||
row = row || {};
|
||||
var id = row.id || Controller.api.pixelRowUid(platform === 'facebook' ? 'fb' : 'tk');
|
||||
var enabled = parseInt(row.enabled, 10) === 1;
|
||||
var serverPostback = parseInt(row.server_postback, 10) === 1;
|
||||
var eventOpts = '';
|
||||
$.each(eventOptions, function (_, ev) {
|
||||
eventOpts += '<option value="' + ev + '"' + (row.event === ev ? ' selected' : '') + '>' + ev + '</option>';
|
||||
});
|
||||
var tokenPlaceholder = __('Optional');
|
||||
var tokenHint = row.has_access_token ? ' placeholder="' + tokenPlaceholder + ' (' + __('Optional') + ')"' : ' placeholder="' + tokenPlaceholder + '"';
|
||||
var selectedEvent = row.event || 'PageView';
|
||||
|
||||
return [
|
||||
'<tr class="split-pixel-row" data-row-id="' + Fast.api.escape(id) + '">',
|
||||
' <td class="text-center"><span class="pixel-row-index">-</span></td>',
|
||||
' <td class="pixel-switch-wrap"><input type="checkbox" class="pixel-enabled" title="' + __('Pixel enabled') + '" ' + (enabled ? 'checked' : '') + '></td>',
|
||||
' <td class="pixel-switch-wrap"><input type="checkbox" class="pixel-server-postback" title="' + __('Server postback') + '" ' + (serverPostback ? 'checked' : '') + '></td>',
|
||||
' <td><input type="text" class="form-control input-sm pixel-id" value="' + Fast.api.escape(row.pixel_id || '') + '" placeholder="' + __('Pixel ID') + '"></td>',
|
||||
' <td class="pixel-event-cell"><select class="form-control input-sm pixel-event" title="' + Fast.api.escape(selectedEvent) + '">' + eventOpts + '</select></td>',
|
||||
' <td class="col-token"><input type="text" class="form-control input-sm pixel-access-token" value=""' + tokenHint + '></td>',
|
||||
' <td><input type="text" class="form-control input-sm pixel-test-code" value="' + Fast.api.escape(row.test_code || '') + '" placeholder="' + tokenPlaceholder + '"></td>',
|
||||
' <td>',
|
||||
' <div class="input-group input-group-sm split-pixel-sort-group">',
|
||||
' <span class="input-group-btn"><button type="button" class="btn btn-default btn-pixel-sort-down" title="-1"><i class="fa fa-minus"></i></button></span>',
|
||||
' <input type="number" min="0" class="form-control pixel-sort-input" value="' + (parseInt(row.sort, 10) || 0) + '" title="' + __('Pixel sort') + '">',
|
||||
' <span class="input-group-btn"><button type="button" class="btn btn-default btn-pixel-sort-up" title="+1"><i class="fa fa-plus"></i></button></span>',
|
||||
' </div>',
|
||||
' </td>',
|
||||
' <td class="text-center">',
|
||||
' <button type="button" class="btn btn-danger btn-xs btn-pixel-row-remove" title="' + __('Remove row') + '"><i class="fa fa-trash"></i></button>',
|
||||
' </td>',
|
||||
'</tr>'
|
||||
].join('');
|
||||
},
|
||||
collectPixelPayload: function ($box) {
|
||||
var readList = function (platform) {
|
||||
var rows = [];
|
||||
$box.find('.split-pixel-list[data-platform="' + platform + '"] tbody .split-pixel-row').each(function () {
|
||||
var $row = $(this);
|
||||
rows.push({
|
||||
id: $row.attr('data-row-id') || Controller.api.pixelRowUid(platform === 'facebook' ? 'fb' : 'tk'),
|
||||
enabled: $row.find('.pixel-enabled').prop('checked') ? 1 : 0,
|
||||
server_postback: $row.find('.pixel-server-postback').prop('checked') ? 1 : 0,
|
||||
pixel_id: $.trim($row.find('.pixel-id').val()),
|
||||
access_token: $.trim($row.find('.pixel-access-token').val()),
|
||||
test_code: $.trim($row.find('.pixel-test-code').val()),
|
||||
event: $row.find('.pixel-event').val() || 'PageView',
|
||||
sort: Math.max(0, parseInt($row.find('.pixel-sort-input').val(), 10) || 0)
|
||||
});
|
||||
});
|
||||
return rows;
|
||||
};
|
||||
return {
|
||||
facebook: readList('facebook'),
|
||||
tiktok: readList('tiktok')
|
||||
};
|
||||
},
|
||||
loadCopyModalData: function (callback) {
|
||||
Fast.api.ajax({
|
||||
url: 'split.link/copyinfo',
|
||||
type: 'get'
|
||||
}, function (data, ret) {
|
||||
callback(ret.data || data || {});
|
||||
return false;
|
||||
});
|
||||
},
|
||||
renderCopyModal: function (linkCode, data) {
|
||||
Controller.api.injectModalStyles();
|
||||
|
||||
var platformDomains = $.isArray(data.platform_domains) ? data.platform_domains : [];
|
||||
if (!platformDomains.length && data.platform_domain) {
|
||||
var rawSingle = $.trim(data.platform_domain);
|
||||
platformDomains = rawSingle.split(/[\r\n,]+/).map(function (d) {
|
||||
return $.trim(d);
|
||||
}).filter(function (d) {
|
||||
return d.length > 0;
|
||||
});
|
||||
}
|
||||
var myDomains = $.isArray(data.my_domains) ? data.my_domains : [];
|
||||
var domainIndexUrl = Controller.api.normalizeAdminRouteUrl(data.domain_index_url, 'domain');
|
||||
var domainAddUrl = Controller.api.normalizeAdminRouteUrl(data.domain_add_url, 'domain/add');
|
||||
var configIndexUrl = data.config_index_url || 'general/config/index';
|
||||
var defaultType = platformDomains.length ? 'platform' : 'my';
|
||||
var defaultDomain = platformDomains.length ? platformDomains[0] : (myDomains.length ? myDomains[0].domain : '');
|
||||
var activeTab = defaultType === 'platform' ? 'platform' : 'my';
|
||||
|
||||
var platformHtml = '';
|
||||
if (platformDomains.length) {
|
||||
var platformItems = [];
|
||||
$.each(platformDomains, function (i, domain) {
|
||||
platformItems.push(Controller.api.buildDomainRadio({
|
||||
domain: domain,
|
||||
type: 'platform',
|
||||
checked: defaultType === 'platform' && domain === defaultDomain,
|
||||
showStatus: false
|
||||
}));
|
||||
});
|
||||
platformHtml = '<div class="split-domain-list">' + platformItems.join('') + '</div>';
|
||||
} else {
|
||||
platformHtml = '<p class="split-domain-empty">'
|
||||
+ __('Split platform domain empty')
|
||||
+ ' <a href="javascript:;" class="btn-goto-config">' + __('Go system config') + '</a>'
|
||||
+ '</p>';
|
||||
}
|
||||
|
||||
var myDomainsHtml = '';
|
||||
if (myDomains.length) {
|
||||
var items = [];
|
||||
$.each(myDomains, function (i, item) {
|
||||
items.push(Controller.api.buildDomainRadio({
|
||||
domain: item.domain,
|
||||
type: 'my',
|
||||
checked: defaultType === 'my' && item.domain === defaultDomain,
|
||||
nsText: item.ns_status_text || '',
|
||||
dnsText: item.dns_status_text || '',
|
||||
nsStatus: item.ns_status || '',
|
||||
dnsStatus: item.dns_status || '',
|
||||
showStatus: true
|
||||
}));
|
||||
});
|
||||
myDomainsHtml = '<div class="split-domain-list">' + items.join('') + '</div>';
|
||||
} else {
|
||||
myDomainsHtml = '<p class="split-domain-empty">' + __('Split my domain empty') + '</p>';
|
||||
}
|
||||
|
||||
var initialUrl = Controller.api.buildSplitUrl(defaultDomain, linkCode);
|
||||
var safeLinkCode = Fast.api.escape(linkCode);
|
||||
var html = [
|
||||
'<div class="split-link-copy-modal">',
|
||||
' <div class="form-group">',
|
||||
' <label class="control-label">' + __('Link_code') + '</label>',
|
||||
' <div class="split-link-code-row">',
|
||||
' <a href="javascript:;" class="split-link-code-value" data-link-code="' + safeLinkCode + '">' + safeLinkCode + '</a>',
|
||||
' <button type="button" class="btn btn-default btn-sm btn-copy-link-code" data-link-code="' + safeLinkCode + '" title="' + __('Copy') + '"><i class="fa fa-copy"></i></button>',
|
||||
' <button type="button" class="btn btn-default btn-sm btn-manage-domain">' + __('Manage my domains') + '</button>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div class="form-group">',
|
||||
' <label class="control-label">' + __('Select main domain') + '</label>',
|
||||
' <ul class="nav nav-tabs split-domain-tabs" role="tablist">',
|
||||
' <li role="presentation"' + (activeTab === 'platform' ? ' class="active"' : '') + '>',
|
||||
' <a href="#split-tab-platform" role="tab" data-toggle="tab">' + __('Platform assigned domain') + '</a>',
|
||||
' </li>',
|
||||
' <li role="presentation"' + (activeTab === 'my' ? ' class="active"' : '') + '>',
|
||||
' <a href="#split-tab-my" role="tab" data-toggle="tab">' + __('My domains') + '</a>',
|
||||
' </li>',
|
||||
' </ul>',
|
||||
' <div class="tab-content split-domain-tab-box">',
|
||||
' <div role="tabpanel" class="tab-pane' + (activeTab === 'platform' ? ' active' : '') + '" id="split-tab-platform">' + platformHtml + '</div>',
|
||||
' <div role="tabpanel" class="tab-pane' + (activeTab === 'my' ? ' active' : '') + '" id="split-tab-my">' + myDomainsHtml + '</div>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div class="split-tip-box">',
|
||||
__('Split domain prefix tip'),
|
||||
' <button type="button" class="btn btn-xs btn-primary btn-go-add-domain">' + __('Go add domain') + '</button>',
|
||||
' </div>',
|
||||
' <div class="form-group" style="margin-bottom:0;">',
|
||||
' <label class="control-label">' + __('Generated result') + '</label>',
|
||||
' <div class="input-group">',
|
||||
' <input type="text" class="form-control split-generated-url" readonly value="' + Fast.api.escape(initialUrl) + '">',
|
||||
' <span class="input-group-btn">',
|
||||
' <button type="button" class="btn btn-default btn-copy-generated-url"><i class="fa fa-copy"></i> ' + __('Copy') + '</button>',
|
||||
' </span>',
|
||||
' </div>',
|
||||
' </div>',
|
||||
' <div class="text-center split-modal-footer">',
|
||||
' <button type="button" class="btn btn-success btn-open-test"' + (initialUrl ? '' : ' disabled') + '>' + __('Open test') + '</button>',
|
||||
' <button type="button" class="btn btn-default btn-close-copy-modal">' + __('Close') + '</button>',
|
||||
' </div>',
|
||||
'</div>'
|
||||
].join('');
|
||||
|
||||
Layer.open({
|
||||
type: 1,
|
||||
title: __('Copy split link'),
|
||||
area: ['780px', 'auto'],
|
||||
maxmin: false,
|
||||
resize: false,
|
||||
shadeClose: true,
|
||||
content: html,
|
||||
success: function (layero, index) {
|
||||
var $box = layero.find('.split-link-copy-modal');
|
||||
|
||||
var refreshGeneratedUrl = function () {
|
||||
var $checked = $box.find('input[name="split_main_domain"]:checked');
|
||||
var domain = $.trim($checked.val() || '');
|
||||
var url = Controller.api.buildSplitUrl(domain, linkCode);
|
||||
$box.find('.split-generated-url').val(url);
|
||||
$box.find('.btn-open-test').prop('disabled', url === '');
|
||||
$box.find('.split-domain-item').removeClass('is-checked');
|
||||
$checked.closest('.split-domain-item').addClass('is-checked');
|
||||
};
|
||||
|
||||
var ensureTabSelection = function ($pane) {
|
||||
var $radios = $pane.find('input[name="split_main_domain"]');
|
||||
if ($radios.length && !$radios.filter(':checked').length) {
|
||||
$radios.first().prop('checked', true);
|
||||
}
|
||||
};
|
||||
|
||||
$box.on('change', 'input[name="split_main_domain"]', refreshGeneratedUrl);
|
||||
|
||||
$box.on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
|
||||
var target = $(e.target).attr('href');
|
||||
if (target) {
|
||||
ensureTabSelection($box.find(target));
|
||||
refreshGeneratedUrl();
|
||||
}
|
||||
});
|
||||
|
||||
$box.on('click', '.btn-copy-link-code', function (e) {
|
||||
e.preventDefault();
|
||||
Controller.api.copyText(linkCode);
|
||||
});
|
||||
|
||||
$box.on('click', '.btn-manage-domain', function (e) {
|
||||
e.preventDefault();
|
||||
Layer.close(index);
|
||||
Backend.api.addtabs(Fast.api.fixurl(domainIndexUrl), __('Domain management'), 'fa fa-globe');
|
||||
});
|
||||
|
||||
$box.on('click', '.btn-go-add-domain', function (e) {
|
||||
e.preventDefault();
|
||||
Layer.close(index);
|
||||
Backend.api.addtabs(Fast.api.fixurl(domainAddUrl), __('Domain management'), 'fa fa-plus');
|
||||
});
|
||||
|
||||
$box.on('click', '.btn-goto-config', function (e) {
|
||||
e.preventDefault();
|
||||
Layer.close(index);
|
||||
Backend.api.addtabs(Fast.api.fixurl(configIndexUrl), __('System config'), 'fa fa-cogs');
|
||||
});
|
||||
|
||||
$box.on('click', '.btn-copy-generated-url', function (e) {
|
||||
e.preventDefault();
|
||||
var url = $.trim($box.find('.split-generated-url').val());
|
||||
if (!url) {
|
||||
Toastr.error(__('Split url empty'));
|
||||
return;
|
||||
}
|
||||
Controller.api.copyText(url);
|
||||
});
|
||||
|
||||
$box.on('click', '.btn-open-test', function (e) {
|
||||
e.preventDefault();
|
||||
var url = $.trim($box.find('.split-generated-url').val());
|
||||
if (url) {
|
||||
window.open(url, '_blank');
|
||||
}
|
||||
});
|
||||
|
||||
$box.on('click', '.btn-close-copy-modal', function (e) {
|
||||
e.preventDefault();
|
||||
Layer.close(index);
|
||||
});
|
||||
|
||||
ensureTabSelection($box.find('.tab-pane.active'));
|
||||
refreshGeneratedUrl();
|
||||
}
|
||||
});
|
||||
},
|
||||
buildDomainRadio: function (options) {
|
||||
var domain = Fast.api.escape(options.domain || '');
|
||||
var type = options.type || 'my';
|
||||
var checked = options.checked ? ' checked' : '';
|
||||
var checkedClass = options.checked ? ' is-checked' : '';
|
||||
var statusHtml = '';
|
||||
if (options.showStatus) {
|
||||
statusHtml = '<span class="split-domain-status">'
|
||||
+ '<span class="label ' + Controller.api.statusLabelClass(options.nsStatus) + '">' + __('NS') + ':' + Fast.api.escape(options.nsText || '-') + '</span>'
|
||||
+ '<span class="label ' + Controller.api.statusLabelClass(options.dnsStatus, true) + '">' + __('DNS') + ':' + Fast.api.escape(options.dnsText || '-') + '</span>'
|
||||
+ '</span>';
|
||||
}
|
||||
return '<div class="split-domain-item' + checkedClass + '">'
|
||||
+ '<label class="split-domain-item-label">'
|
||||
+ '<input type="radio" name="split_main_domain" value="' + domain + '" data-type="' + type + '"' + checked + '>'
|
||||
+ '<span class="split-domain-item-body">'
|
||||
+ '<span class="split-domain-name">' + domain + '</span>'
|
||||
+ statusHtml
|
||||
+ '</span>'
|
||||
+ '</label>'
|
||||
+ '</div>';
|
||||
},
|
||||
statusLabelClass: function (status, isDns) {
|
||||
if (isDns) {
|
||||
if (status === 'created') {
|
||||
return 'label-success';
|
||||
}
|
||||
if (status === 'failed') {
|
||||
return 'label-danger';
|
||||
}
|
||||
return 'label-warning';
|
||||
}
|
||||
if (status === 'verified') {
|
||||
return 'label-success';
|
||||
}
|
||||
if (status === 'failed') {
|
||||
return 'label-danger';
|
||||
}
|
||||
return 'label-warning';
|
||||
},
|
||||
buildSplitUrl: function (domain, linkCode) {
|
||||
domain = $.trim(domain || '').replace(/^https?:\/\//i, '').replace(/\/+$/, '');
|
||||
linkCode = $.trim(linkCode || '');
|
||||
if (!domain || !linkCode) {
|
||||
return '';
|
||||
}
|
||||
return 'https://' + domain + '/s/' + linkCode;
|
||||
},
|
||||
copyText: function (text) {
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
navigator.clipboard.writeText(text).then(function () {
|
||||
Toastr.success(__('Copy success'));
|
||||
}).catch(function () {
|
||||
Controller.api.copyTextFallback(text);
|
||||
});
|
||||
return;
|
||||
}
|
||||
Controller.api.copyTextFallback(text);
|
||||
},
|
||||
copyTextFallback: function (text) {
|
||||
var $temp = $('<textarea>').css({position: 'fixed', left: '-9999px', top: '0'}).val(text);
|
||||
$('body').append($temp);
|
||||
$temp[0].select();
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
Toastr.success(__('Copy success'));
|
||||
} catch (e) {
|
||||
Toastr.error(__('Copy failed'));
|
||||
}
|
||||
$temp.remove();
|
||||
},
|
||||
bindLinkCodeInput: function () {
|
||||
var $input = $('#c-link_code');
|
||||
if (!$input.length || $input.prop('readonly')) {
|
||||
return;
|
||||
}
|
||||
$input.on('input', function () {
|
||||
var val = $(this).val().replace(/[^a-zA-Z]/g, '').toLowerCase().slice(0, 9);
|
||||
if ($(this).val() !== val) {
|
||||
$(this).val(val);
|
||||
}
|
||||
});
|
||||
},
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+221
@@ -0,0 +1,221 @@
|
||||
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");
|
||||
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
sortOrder: 'desc',
|
||||
fixedColumns: true,
|
||||
fixedRightNumber: 1,
|
||||
columns: [
|
||||
[
|
||||
{checkbox: 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'},
|
||||
{
|
||||
field: 'number_type',
|
||||
title: __('Number_type'),
|
||||
searchList: Config.numberTypeList,
|
||||
formatter: Table.api.formatter.normal
|
||||
},
|
||||
{field: 'visit_count', title: __('Visit_count'), operate: false, sortable: true},
|
||||
{field: 'inbound_count', title: __('Inbound_count'), operate: false, sortable: true},
|
||||
{
|
||||
field: 'platform_status',
|
||||
title: __('Platform_status'),
|
||||
searchList: Config.platformStatusList,
|
||||
formatter: Controller.api.formatter.platformStatus
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: __('Status'),
|
||||
searchList: Config.statusList,
|
||||
formatter: Table.api.formatter.toggle,
|
||||
yes: 'normal',
|
||||
no: 'hidden'
|
||||
},
|
||||
{
|
||||
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);
|
||||
});
|
||||
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
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>';
|
||||
}
|
||||
},
|
||||
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;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+393
@@ -0,0 +1,393 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'split.ticket/index' + location.search,
|
||||
add_url: 'split.ticket/add',
|
||||
edit_url: 'split.ticket/edit',
|
||||
del_url: 'split.ticket/del',
|
||||
multi_url: 'split.ticket/multi',
|
||||
table: 'split_ticket',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
sortOrder: 'desc',
|
||||
fixedColumns: true,
|
||||
fixedRightNumber: 1,
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{
|
||||
field: 'ticket_type',
|
||||
title: __('Ticket_type'),
|
||||
searchList: Config.ticketTypeList,
|
||||
operate: false,
|
||||
formatter: Controller.api.formatter.ticketTypePlain
|
||||
},
|
||||
{field: 'ticket_name', title: __('Ticket_name'), operate: 'LIKE'},
|
||||
{
|
||||
field: 'link_code_text',
|
||||
title: __('Split_link_id'),
|
||||
operate: false,
|
||||
formatter: Controller.api.formatter.splitLinkCode
|
||||
},
|
||||
{
|
||||
field: 'start_time_text',
|
||||
title: __('Start_time'),
|
||||
operate: 'RANGE',
|
||||
addclass: 'datetimerange',
|
||||
autocomplete: false,
|
||||
sortable: true
|
||||
},
|
||||
{
|
||||
field: 'end_time_text',
|
||||
title: __('End_time'),
|
||||
operate: 'RANGE',
|
||||
addclass: 'datetimerange',
|
||||
autocomplete: false,
|
||||
sortable: true
|
||||
},
|
||||
{field: 'order_limit', title: __('Order_limit'), operate: false},
|
||||
{field: 'assign_ratio', title: __('Assign_ratio'), operate: false},
|
||||
{field: 'ticket_total', title: __('Ticket_total'), operate: false, sortable: true},
|
||||
{field: 'complete_count', title: __('Complete_count'), operate: false, sortable: true},
|
||||
{
|
||||
field: 'ticket_progress_text',
|
||||
title: __('Ticket_progress'),
|
||||
operate: false,
|
||||
formatter: Table.api.formatter.content
|
||||
},
|
||||
{
|
||||
field: 'inbound_ratio_text',
|
||||
title: __('Inbound_ratio'),
|
||||
operate: false,
|
||||
formatter: Table.api.formatter.content
|
||||
},
|
||||
{
|
||||
field: 'speed_per_hour',
|
||||
title: __('Speed_per_hour'),
|
||||
operate: false,
|
||||
formatter: Controller.api.formatter.speedPerHour
|
||||
},
|
||||
{
|
||||
field: 'number_count',
|
||||
title: __('Number_count'),
|
||||
operate: false,
|
||||
formatter: Controller.api.formatter.numberCount
|
||||
},
|
||||
{
|
||||
field: 'sync_display_text',
|
||||
title: __('Sync_status'),
|
||||
operate: false,
|
||||
formatter: Controller.api.formatter.syncDisplay
|
||||
},
|
||||
{
|
||||
field: 'status',
|
||||
title: __('Status'),
|
||||
searchList: Config.statusList,
|
||||
formatter: Table.api.formatter.toggle,
|
||||
yes: 'normal',
|
||||
no: 'hidden'
|
||||
},
|
||||
{
|
||||
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.api.bindevent(table);
|
||||
Controller.api.syncingTicketIds = [];
|
||||
window.__splitTicketPendingPostAddSyncIds = window.__splitTicketPendingPostAddSyncIds || [];
|
||||
|
||||
table.on('load-success.bs.table', function () {
|
||||
var pendingIds = window.__splitTicketPendingPostAddSyncIds;
|
||||
if (!pendingIds || !pendingIds.length) {
|
||||
return;
|
||||
}
|
||||
window.__splitTicketPendingPostAddSyncIds = [];
|
||||
Controller.api.startBackgroundSync(table, pendingIds, false);
|
||||
});
|
||||
|
||||
table.on('check.bs.table uncheck.bs.table check-all.bs.table uncheck-all.bs.table', function () {
|
||||
var ids = Table.api.selectedids(table);
|
||||
$('.btn-sync').toggleClass('btn-disabled disabled', ids.length === 0);
|
||||
});
|
||||
|
||||
$('.btn-sync').on('click', function (e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var ids = Table.api.selectedids(table);
|
||||
if (!ids.length) {
|
||||
Toastr.error(__('Please select at least one record'));
|
||||
return false;
|
||||
}
|
||||
var syncConfirmMsg = (typeof Config.syncConfirmMsg !== 'undefined' && Config.syncConfirmMsg)
|
||||
? Config.syncConfirmMsg
|
||||
: '确定同步所选工单吗?任务将在后台执行,完成后自动提示结果。';
|
||||
var syncBackgroundMsg = (typeof Config.syncBackgroundStartedMsg !== 'undefined' && Config.syncBackgroundStartedMsg)
|
||||
? Config.syncBackgroundStartedMsg
|
||||
: '同步任务已在后台执行,请稍候…';
|
||||
Layer.confirm(syncConfirmMsg, {icon: 3, title: __('Sync_status_btn')}, function (index) {
|
||||
Layer.close(index);
|
||||
Toastr.info(syncBackgroundMsg);
|
||||
Controller.api.startBackgroundSync(table, ids, true);
|
||||
});
|
||||
return false;
|
||||
});
|
||||
},
|
||||
add: function () {
|
||||
Form.api.bindevent($('form[role=form]'), function (data, ret) {
|
||||
var ticketId = ret.data && ret.data.id ? parseInt(ret.data.id, 10) : 0;
|
||||
var syncTicketMsg = (typeof Config.syncTicketStartedMsg !== 'undefined' && Config.syncTicketStartedMsg)
|
||||
? Config.syncTicketStartedMsg
|
||||
: '正在同步工单';
|
||||
if (ticketId > 0) {
|
||||
parent.__splitTicketPendingPostAddSyncIds = parent.__splitTicketPendingPostAddSyncIds || [];
|
||||
parent.__splitTicketPendingPostAddSyncIds.push(ticketId);
|
||||
}
|
||||
if (parent && parent.Toastr) {
|
||||
parent.Toastr.info(syncTicketMsg);
|
||||
}
|
||||
parent.$('.btn-refresh').trigger('click');
|
||||
if (window.name) {
|
||||
var layerIndex = parent.Layer.getFrameIndex(window.name);
|
||||
parent.Layer.close(layerIndex);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
Controller.api.fixSelectPlaceholder();
|
||||
Controller.api.bindNumberTypeToggle();
|
||||
Controller.api.bindEndTimeCheck();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
/** @type {number[]} 正在手动同步的工单 ID */
|
||||
syncingTicketIds: [],
|
||||
|
||||
/**
|
||||
* 后台同步:标记「同步中」并请求 sync 接口
|
||||
*
|
||||
* @param {object} table bootstrapTable 实例
|
||||
* @param {number[]} ids 工单 ID
|
||||
* @param {boolean} disableSyncBtn 是否禁用工具栏同步按钮
|
||||
*/
|
||||
startBackgroundSync: function (table, ids, disableSyncBtn) {
|
||||
ids = (ids || []).map(function (id) {
|
||||
return parseInt(id, 10);
|
||||
}).filter(function (id) {
|
||||
return !isNaN(id) && id > 0;
|
||||
});
|
||||
if (!ids.length) {
|
||||
return;
|
||||
}
|
||||
Controller.api.markTicketsSyncing(table, ids);
|
||||
if (disableSyncBtn) {
|
||||
$('.btn-sync').addClass('btn-disabled disabled');
|
||||
}
|
||||
Fast.api.ajax({
|
||||
url: 'split.ticket/sync',
|
||||
data: {ids: ids.join(',')},
|
||||
loading: false
|
||||
}, function () {
|
||||
Controller.api.finishTicketsSync(table);
|
||||
}, function () {
|
||||
Controller.api.finishTicketsSync(table);
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* 将选中工单标记为「同步中」并刷新列表展示(不请求后端)
|
||||
*/
|
||||
markTicketsSyncing: function (table, ids) {
|
||||
Controller.api.syncingTicketIds = (ids || []).map(function (id) {
|
||||
return parseInt(id, 10);
|
||||
}).filter(function (id) {
|
||||
return !isNaN(id) && id > 0;
|
||||
});
|
||||
var data = table.bootstrapTable('getData');
|
||||
table.bootstrapTable('load', data);
|
||||
},
|
||||
|
||||
/**
|
||||
* 同步结束:清除标记并刷新列表数据
|
||||
*/
|
||||
finishTicketsSync: function (table) {
|
||||
Controller.api.syncingTicketIds = [];
|
||||
table.bootstrapTable('refresh');
|
||||
var ids = Table.api.selectedids(table);
|
||||
$('.btn-sync').toggleClass('btn-disabled disabled', ids.length === 0);
|
||||
},
|
||||
|
||||
formatter: {
|
||||
/**
|
||||
* 工单类型:纯文本展示,无链接/标签样式
|
||||
*/
|
||||
ticketTypePlain: function (value, row) {
|
||||
var text = row.ticket_type_text != null && row.ticket_type_text !== ''
|
||||
? String(row.ticket_type_text)
|
||||
: (value != null ? String(value) : '');
|
||||
if (text === '') {
|
||||
return '<span class="text-muted">-</span>';
|
||||
}
|
||||
return '<span class="split-ticket-type-plain">' + Fast.api.escape(text) + '</span>';
|
||||
},
|
||||
/**
|
||||
* 分流链接:纯文本 + 边框背景标记,不可点击
|
||||
*/
|
||||
splitLinkCode: function (value) {
|
||||
value = value == null ? '' : String(value);
|
||||
if ($.trim(value) === '') {
|
||||
return '<span class="text-muted">-</span>';
|
||||
}
|
||||
var safe = Fast.api.escape(value);
|
||||
return '<span class="split-ticket-link-badge" style="display:inline-block;max-width:100%;padding:2px 8px;font-size:12px;line-height:1.5;color:#555;background:#f5f5f5;border:1px solid #ddd;border-radius:3px;word-break:break-all;">'
|
||||
+ safe + '</span>';
|
||||
},
|
||||
speedPerHour: function (value) {
|
||||
var num = parseFloat(value);
|
||||
if (isNaN(num)) {
|
||||
return '0.00';
|
||||
}
|
||||
return num.toFixed(2);
|
||||
},
|
||||
numberCount: function (value, row) {
|
||||
var total = parseInt(value, 10) || 0;
|
||||
var offline = parseInt(row.number_offline_count, 10) || 0;
|
||||
var banned = parseInt(row.number_banned_count, 10) || 0;
|
||||
var tip = __('Number_count_detail').replace('%s', offline).replace('%s', banned);
|
||||
if (offline > 0 || banned > 0) {
|
||||
return '<span data-toggle="tooltip" title="' + Fast.api.escape(tip) + '">' + total + '</span>';
|
||||
}
|
||||
return String(total);
|
||||
},
|
||||
syncDisplay: function (value, row) {
|
||||
var rowId = parseInt(row.id, 10);
|
||||
if (Controller.api.syncingTicketIds.indexOf(rowId) !== -1) {
|
||||
return Controller.api.formatter.syncingDisplayHtml();
|
||||
}
|
||||
var text = value || '';
|
||||
var color = 'danger';
|
||||
if (row.sync_status === 'success') {
|
||||
color = 'success';
|
||||
} else if (row.sync_status === 'pending') {
|
||||
color = 'muted';
|
||||
}
|
||||
return '<span class="text-' + color + '">' + Fast.api.escape(text) + '</span>';
|
||||
},
|
||||
syncingDisplayHtml: function () {
|
||||
var label = (typeof Config.syncInProgressMsg !== 'undefined' && Config.syncInProgressMsg)
|
||||
? Config.syncInProgressMsg
|
||||
: '同步中';
|
||||
return '<span class="split-ticket-sync-pending">'
|
||||
+ '<i class="fa fa-refresh fa-spin"></i>'
|
||||
+ '<span class="split-ticket-sync-label">' + Fast.api.escape(label) + '</span>'
|
||||
+ '</span>';
|
||||
}
|
||||
},
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($('form[role=form]'));
|
||||
Controller.api.fixSelectPlaceholder();
|
||||
Controller.api.bindNumberTypeToggle();
|
||||
Controller.api.bindEndTimeCheck();
|
||||
},
|
||||
/**
|
||||
* selectpicker 空选项文案改为中文「请选择」
|
||||
*/
|
||||
fixSelectPlaceholder: function () {
|
||||
var text = __('Please select');
|
||||
if (!text || text === 'Please select' || text === 'Please Select') {
|
||||
text = '请选择';
|
||||
}
|
||||
$('#c-ticket_type, #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');
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* 号码类型为 custom 时显示自定义输入框
|
||||
*/
|
||||
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');
|
||||
$custom.val('');
|
||||
}
|
||||
if ($custom.data('validator')) {
|
||||
$custom.trigger('validate');
|
||||
}
|
||||
};
|
||||
$type.on('changed.bs.select change', toggle);
|
||||
toggle();
|
||||
},
|
||||
/**
|
||||
* 前端预校验:到期时间须晚于开始时间(后端为准)
|
||||
*/
|
||||
bindEndTimeCheck: function () {
|
||||
var $form = $('form[role=form]');
|
||||
var $start = $('#c-start_time');
|
||||
var $end = $('#c-end_time');
|
||||
if (!$start.length || !$end.length) {
|
||||
return;
|
||||
}
|
||||
var parseTs = function (str) {
|
||||
str = $.trim(str || '');
|
||||
if (!str) {
|
||||
return 0;
|
||||
}
|
||||
var d = new Date(str.replace(/-/g, '/'));
|
||||
return isNaN(d.getTime()) ? 0 : Math.floor(d.getTime() / 1000);
|
||||
};
|
||||
$form.on('submit', function (e) {
|
||||
var s = parseTs($start.val());
|
||||
var en = parseTs($end.val());
|
||||
if (s > 0 && en > 0 && en <= s) {
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
Layer.msg(__('End time must after start'));
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+114
@@ -0,0 +1,114 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'jstree'], function ($, undefined, Backend, Table, Form, undefined) {
|
||||
//读取选中的条目
|
||||
$.jstree.core.prototype.get_all_checked = function (full) {
|
||||
var obj = this.get_selected(), i, j;
|
||||
for (i = 0, j = obj.length; i < j; i++) {
|
||||
obj = obj.concat(this.get_node(obj[i]).parents);
|
||||
}
|
||||
obj = $.grep(obj, function (v, i, a) {
|
||||
return v != '#';
|
||||
});
|
||||
obj = obj.filter(function (itm, i, a) {
|
||||
return i == a.indexOf(itm);
|
||||
});
|
||||
return full ? $.map(obj, $.proxy(function (i) {
|
||||
return this.get_node(i);
|
||||
}, this)) : obj;
|
||||
};
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'user/group/index',
|
||||
add_url: 'user/group/add',
|
||||
edit_url: 'user/group/edit',
|
||||
del_url: 'user/group/del',
|
||||
multi_url: 'user/group/multi',
|
||||
table: 'user_group',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'id',
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'name', title: __('Name')},
|
||||
{field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
{field: 'updatetime', title: __('Updatetime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status},
|
||||
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"), null, null, function () {
|
||||
if ($("#treeview").length > 0) {
|
||||
var r = $("#treeview").jstree("get_all_checked");
|
||||
$("input[name='row[rules]']").val(r.join(','));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
//渲染权限节点树
|
||||
//销毁已有的节点树
|
||||
$("#treeview").jstree("destroy");
|
||||
Controller.api.rendertree(nodeData);
|
||||
//全选和展开
|
||||
$(document).on("click", "#checkall", function () {
|
||||
$("#treeview").jstree($(this).prop("checked") ? "check_all" : "uncheck_all");
|
||||
});
|
||||
$(document).on("click", "#expandall", function () {
|
||||
$("#treeview").jstree($(this).prop("checked") ? "open_all" : "close_all");
|
||||
});
|
||||
$("select[name='row[pid]']").trigger("change");
|
||||
},
|
||||
rendertree: function (content) {
|
||||
$("#treeview")
|
||||
.on('redraw.jstree', function (e) {
|
||||
$(".layer-footer").attr("domrefresh", Math.random());
|
||||
})
|
||||
.jstree({
|
||||
"themes": {"stripes": true},
|
||||
"checkbox": {
|
||||
"keep_selected_style": false,
|
||||
},
|
||||
"types": {
|
||||
"root": {
|
||||
"icon": "fa fa-folder-open",
|
||||
},
|
||||
"menu": {
|
||||
"icon": "fa fa-folder-open",
|
||||
},
|
||||
"file": {
|
||||
"icon": "fa fa-file-o",
|
||||
}
|
||||
},
|
||||
"plugins": ["checkbox", "types"],
|
||||
"core": {
|
||||
'check_callback': true,
|
||||
"data": content
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+130
@@ -0,0 +1,130 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'user/rule/index',
|
||||
add_url: 'user/rule/add',
|
||||
edit_url: 'user/rule/edit',
|
||||
del_url: 'user/rule/del',
|
||||
multi_url: 'user/rule/multi',
|
||||
table: 'user_rule',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'weigh',
|
||||
escape: true,
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'id', title: __('Id')},
|
||||
{field: 'pid', title: __('Pid'), visible: false},
|
||||
{field: 'title', title: __('Title'), align: 'left', formatter: Controller.api.formatter.title},
|
||||
{field: 'name', title: __('Name'), align: 'left', formatter: Controller.api.formatter.name},
|
||||
{field: 'remark', title: __('Remark')},
|
||||
// {field: 'ismenu', title: __('Ismenu'), formatter: Table.api.formatter.toggle},
|
||||
{field: 'createtime', title: __('Createtime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true, visible: false},
|
||||
{field: 'updatetime', title: __('Updatetime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true, visible: false},
|
||||
{field: 'weigh', title: __('Weigh')},
|
||||
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status},
|
||||
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
|
||||
]
|
||||
],
|
||||
pagination: false,
|
||||
search: false,
|
||||
commonSearch: false,
|
||||
rowAttributes: function (row, index) {
|
||||
return row.pid == 0 ? {} : {style: "display:none"};
|
||||
}
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
|
||||
table.on('post-body.bs.table', function (e, settings, json, xhr) {
|
||||
//显示隐藏子节点
|
||||
$(">tbody>tr[data-index] > td", this).on('click', "a.btn-node-sub", function () {
|
||||
var status = $(this).data("shown") ? true : false;
|
||||
$("a[data-pid='" + $(this).data("id") + "']").each(function () {
|
||||
$(this).closest("tr").toggle(!status);
|
||||
});
|
||||
if (status) {
|
||||
$("a[data-pid='" + $(this).data("id") + "']").trigger("collapse");
|
||||
}
|
||||
$(this).data("shown", !status);
|
||||
$("i", this).toggleClass("fa-caret-down").toggleClass("fa-caret-right");
|
||||
return false;
|
||||
});
|
||||
});
|
||||
|
||||
//隐藏子节点
|
||||
$(document).on("collapse", ".btn-node-sub", function () {
|
||||
if ($("i", this).length > 0) {
|
||||
$("a[data-pid='" + $(this).data("id") + "']").trigger("collapse");
|
||||
}
|
||||
$("i", this).removeClass("fa-caret-down").addClass("fa-caret-right");
|
||||
$(this).data("shown", false);
|
||||
$(this).closest("tr").toggle(false);
|
||||
});
|
||||
|
||||
//展开隐藏一级
|
||||
$(document.body).on("click", ".btn-toggle", function (e) {
|
||||
$("a[data-id][data-pid][data-pid!=0].disabled").closest("tr").hide();
|
||||
var that = this;
|
||||
var show = $("i", that).hasClass("fa-chevron-down");
|
||||
$("i", that).toggleClass("fa-chevron-down", !show).toggleClass("fa-chevron-up", show);
|
||||
$("a[data-id][data-pid][data-pid!=0]").not('.disabled').closest("tr").toggle(show);
|
||||
$(".btn-node-sub[data-pid=0]").data("shown", show);
|
||||
});
|
||||
|
||||
//展开隐藏全部
|
||||
$(document.body).on("click", ".btn-toggle-all", function (e) {
|
||||
var that = this;
|
||||
var show = $("i", that).hasClass("fa-plus");
|
||||
$("i", that).toggleClass("fa-plus", !show).toggleClass("fa-minus", show);
|
||||
$(".btn-node-sub:not([data-pid=0])").closest("tr").toggle(show);
|
||||
$(".btn-node-sub").data("shown", show);
|
||||
$(".btn-node-sub > i").toggleClass("fa-caret-down", show).toggleClass("fa-caret-right", !show);
|
||||
});
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
formatter: {
|
||||
title: function (value, row, index) {
|
||||
value = value.toString().replace(/(&|&)nbsp;/g, ' ');
|
||||
var caret = row.haschild == 1 || row.ismenu == 1 ? '<i class="fa fa-caret-right"></i>' : '';
|
||||
value = value.indexOf(" ") > -1 ? value.replace(/(.*) /, "$1" + caret) : caret + value;
|
||||
|
||||
value = !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||
return '<a href="javascript:;" data-id="' + row.id + '" data-pid="' + row.pid + '" class="'
|
||||
+ (row.haschild == 1 || row.ismenu == 1 ? 'text-primary' : 'disabled') + ' btn-node-sub">' + value + '</a>';
|
||||
},
|
||||
name: function (value, row, index) {
|
||||
return !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||
},
|
||||
},
|
||||
bindevent: function () {
|
||||
$(document).on('click', "input[name='row[ismenu]']", function () {
|
||||
var name = $("input[name='row[name]']");
|
||||
name.prop("placeholder", $(this).val() == 1 ? name.data("placeholder-menu") : name.data("placeholder-node"));
|
||||
});
|
||||
$("input[name='row[ismenu]']:checked").trigger("click");
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
|
||||
|
||||
var Controller = {
|
||||
index: function () {
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'user/user/index',
|
||||
add_url: 'user/user/add',
|
||||
edit_url: 'user/user/edit',
|
||||
del_url: 'user/user/del',
|
||||
multi_url: 'user/user/multi',
|
||||
table: 'user',
|
||||
}
|
||||
});
|
||||
|
||||
var table = $("#table");
|
||||
|
||||
// 初始化表格
|
||||
table.bootstrapTable({
|
||||
url: $.fn.bootstrapTable.defaults.extend.index_url,
|
||||
pk: 'id',
|
||||
sortName: 'user.id',
|
||||
fixedColumns: true,
|
||||
fixedRightNumber: 1,
|
||||
columns: [
|
||||
[
|
||||
{checkbox: true},
|
||||
{field: 'id', title: __('Id'), sortable: true},
|
||||
{field: 'group.name', title: __('Group')},
|
||||
{field: 'username', title: __('Username'), operate: 'LIKE'},
|
||||
{field: 'nickname', title: __('Nickname'), operate: 'LIKE'},
|
||||
{field: 'email', title: __('Email'), operate: 'LIKE'},
|
||||
{field: 'mobile', title: __('Mobile'), operate: 'LIKE'},
|
||||
{field: 'avatar', title: __('Avatar'), events: Table.api.events.image, formatter: Table.api.formatter.image, operate: false},
|
||||
{field: 'level', title: __('Level'), operate: 'BETWEEN', sortable: true},
|
||||
{field: 'gender', title: __('Gender'), visible: false, searchList: {1: __('Male'), 0: __('Female')}},
|
||||
{field: 'score', title: __('Score'), operate: 'BETWEEN', sortable: true},
|
||||
{field: 'successions', title: __('Successions'), visible: false, operate: 'BETWEEN', sortable: true},
|
||||
{field: 'maxsuccessions', title: __('Maxsuccessions'), visible: false, operate: 'BETWEEN', sortable: true},
|
||||
{field: 'logintime', title: __('Logintime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
{field: 'loginip', title: __('Loginip'), formatter: Table.api.formatter.search},
|
||||
{field: 'jointime', title: __('Jointime'), formatter: Table.api.formatter.datetime, operate: 'RANGE', addclass: 'datetimerange', sortable: true},
|
||||
{field: 'joinip', title: __('Joinip'), formatter: Table.api.formatter.search},
|
||||
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status, searchList: {normal: __('Normal'), hidden: __('Hidden')}},
|
||||
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
Reference in New Issue
Block a user