- 框架初始化
 - 安装插件
 - 修复PHP8.4报错
This commit is contained in:
2025-04-19 17:21:20 +08:00
commit c6a4e1f5f6
5306 changed files with 967782 additions and 0 deletions

View File

@@ -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;
});

View File

@@ -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;
});

View File

@@ -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;
});

View File

@@ -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(/(&|&amp;)nbsp;/g, '&nbsp;');
}
},
{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;
});

View File

@@ -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(/(&|&amp;)nbsp;/g, '&nbsp;');
var caret = row.haschild == 1 || row.ismenu == 1 ? '<i class="fa fa-caret-right"></i>' : '';
value = value.indexOf("&nbsp;") > -1 ? value.replace(/(.*)&nbsp;/, "$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;
});

View File

@@ -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(/(&|&amp;)nbsp;/g, '&nbsp;');
}
},
{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;
});

View File

@@ -0,0 +1,234 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'template'], function ($, undefined, Backend, Table, Form, Template) {
var Controller = {
index: function () {
// 初始化表格参数配置
Table.api.init({
extend: {
index_url: 'command/index',
add_url: 'command/add',
edit_url: '',
del_url: 'command/del',
multi_url: 'command/multi',
table: 'command',
}
});
var table = $("#table");
// 初始化表格
table.bootstrapTable({
url: $.fn.bootstrapTable.defaults.extend.index_url,
pk: 'id',
sortName: 'id',
columns: [
[
{checkbox: true},
{field: 'id', title: __('Id')},
{field: 'type', title: __('Type'), formatter: Table.api.formatter.search},
{field: 'type_text', title: __('Type')},
{
field: 'command', title: __('Command'), renderDefault: false, formatter: function (value, row, index) {
return '<input type="text" class="form-control" value="' + value + '">';
}
},
{
field: 'executetime',
title: __('Executetime'),
operate: 'RANGE',
addclass: 'datetimerange',
formatter: Table.api.formatter.datetime
},
{
field: 'createtime',
title: __('Createtime'),
operate: 'RANGE',
addclass: 'datetimerange',
formatter: Table.api.formatter.datetime
},
{
field: 'updatetime',
title: __('Updatetime'),
operate: 'RANGE',
addclass: 'datetimerange',
formatter: Table.api.formatter.datetime
},
{
field: 'status',
title: __('Status'),
table: table,
custom: {"successed": 'success', "failured": 'danger'},
searchList: {"successed": __('Successed'), "failured": __('Failured')},
formatter: Table.api.formatter.status
},
{
field: 'operate',
title: __('Operate'),
buttons: [
{
name: 'execute',
title: __('Execute again'),
text: __('Execute again'),
url: 'command/execute',
icon: 'fa fa-repeat',
classname: 'btn btn-success btn-xs btn-execute btn-ajax',
success: function (data) {
Layer.alert("<textarea class='form-control' cols='60' rows='5'>" + data.result + "</textarea>", {
title: __("执行结果"),
shadeClose: true
});
table.bootstrapTable('refresh');
return false;
}
},
{
name: 'execute',
title: __('Detail'),
text: __('Detail'),
url: 'command/detail',
icon: 'fa fa-list',
classname: 'btn btn-info btn-xs btn-execute btn-dialog'
}
],
table: table,
events: Table.api.events.operate,
formatter: Table.api.formatter.operate
}
]
]
});
// 为表格绑定事件
Table.api.bindevent(table);
},
add: function () {
require(['bootstrap-select', 'bootstrap-select-lang']);
var mainfields = [];
var relationfields = {};
var maintable = [];
var relationtable = [];
var relationmode = ["belongsto", "hasone"];
var renderselect = function (select, data) {
var html = [];
for (var i = 0; i < data.length; i++) {
html.push("<option value='" + data[i] + "'>" + data[i] + "</option>");
}
$(select).html(html.join(""));
select.trigger("change");
if (select.data("selectpicker")) {
select.selectpicker('refresh');
}
return select;
};
$("select[name=table] option").each(function () {
maintable.push($(this).val());
});
$(document).on('change', "input[name='isrelation']", function () {
$("#relation-zone").toggleClass("hide", !$(this).prop("checked"));
});
$(document).on('change', "select[name='table']", function () {
var that = this;
Fast.api.ajax({
url: "command/get_field_list",
data: {table: $(that).val()},
}, function (data, ret) {
mainfields = data.fieldlist;
$("#relation-zone .relation-item").remove();
renderselect($("#fields"), mainfields);
return false;
});
return false;
});
$(document).on('click', "a.btn-newrelation", function () {
var that = this;
var index = parseInt($(that).data("index")) + 1;
var content = Template("relationtpl", {index: index});
content = $(content.replace(/\[index\]/, index));
$(this).data("index", index);
$(content).insertBefore($(that).closest(".row"));
$('select', content).selectpicker();
var exists = [$("select[name='table']").val()];
$("select.relationtable").each(function () {
exists.push($(this).val());
});
relationtable = [];
$.each(maintable, function (i, j) {
if ($.inArray(j, exists) < 0) {
relationtable.push(j);
}
});
renderselect($("select.relationtable", content), relationtable);
$("select.relationtable", content).trigger("change");
});
$(document).on('click', "a.btn-removerelation", function () {
$(this).closest(".row").remove();
});
$(document).on('change', "#relation-zone select.relationmode", function () {
var table = $("select.relationtable", $(this).closest(".row")).val();
var that = this;
Fast.api.ajax({
url: "command/get_field_list",
data: {table: table},
}, function (data, ret) {
renderselect($(that).closest(".row").find("select.relationprimarykey"), $(that).val() == 'belongsto' ? data.fieldlist : mainfields);
renderselect($(that).closest(".row").find("select.relationforeignkey"), $(that).val() == 'hasone' ? data.fieldlist : mainfields);
return false;
});
});
$(document).on('change', "#relation-zone select.relationtable", function () {
var that = this;
Fast.api.ajax({
url: "command/get_field_list",
data: {table: $(that).val()},
}, function (data, ret) {
renderselect($(that).closest(".row").find("select.relationmode"), relationmode);
renderselect($(that).closest(".row").find("select.relationfields"), mainfields)
renderselect($(that).closest(".row").find("select.relationforeignkey"), data.fieldlist)
renderselect($(that).closest(".row").find("select.relationfields"), data.fieldlist)
return false;
});
});
$(document).on('click', ".btn-command", function () {
var form = $(this).closest("form");
var textarea = $("textarea[rel=command]", form);
textarea.val('');
Fast.api.ajax({
url: "command/command/action/command",
data: form.serialize(),
}, function (data, ret) {
textarea.val(data.command);
return false;
});
});
$(document).on('click', ".btn-execute", function () {
var form = $(this).closest("form");
var textarea = $("textarea[rel=result]", form);
textarea.val('');
Fast.api.ajax({
url: "command/command/action/execute",
data: form.serialize(),
}, function (data, ret) {
textarea.val(data.result);
window.parent.$(".toolbar .btn-refresh").trigger('click');
top.window.Fast.api.refreshmenu();
return false;
}, function () {
window.parent.$(".toolbar .btn-refresh").trigger('click');
});
});
$("select[name='table']").trigger("change");
Controller.api.bindevent();
},
edit: function () {
Controller.api.bindevent();
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
}
};
return Controller;
});

View File

@@ -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;
});

View File

@@ -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;
});

View File

@@ -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;
});

View File

@@ -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;
});

View File

@@ -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;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,244 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
activity_id: new URLSearchParams(location.search).get('activity_id'),
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
status: 'all',
user: { field: 'user_id', value: '' },
'goods.title': '',
},
tools: {
user: {
type: 'tinputprepend',
label: '团长信息',
placeholder: '请输入查询内容',
value: {
field: 'user_id',
value: '',
},
options: {
data: [
{
label: '团长ID',
value: 'user_id',
},
{
label: '团长昵称',
value: 'user.nickname',
},
{
label: '团长手机号',
value: 'user.mobile',
},
],
}
},
'goods.title': {
type: 'tinput',
label: '商品名称',
value: '',
},
},
condition: {},
},
statusList: [{
name: '全部',
type: 'all',
},
{
name: '进行中',
type: 'ing',
},
{
name: '已成团',
type: 'finish',
},
{
name: '虚拟成团',
type: 'finish_fictitious',
},
{
name: '已过期',
type: 'invalid ',
}],
statusClass: {
ing: 'warning',
finish: 'success',
finish_fictitious: 'success',
invalid: 'danger',
},
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
tempSearch.activity_id = state.activity_id
let search = composeFilter(tempSearch, {
'user.nickname': 'like',
'goods.title': 'like',
});
Fast.api.ajax({
url: 'shopro/activity/groupon',
type: 'GET',
data: {
type: state.type,
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
function onChangeTab() {
pagination.page = 1
getData()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onDetail(id) {
Fast.api.open(`shopro/activity/groupon/detail/id/${id}?id=${id}`, "详情", {
callback() {
getData()
}
})
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
onChangeTab,
pagination,
onDetail,
}
}
}
createApp('index', index);
},
detail: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const detail = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
data: {},
statusClass: {
ing: 'warning',
finish: 'success',
finish_fictitious: 'success',
invalid: 'danger',
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/activity/groupon/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onInvalid() {
Fast.api.ajax({
url: `shopro/activity/groupon/invalid/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
getDetail()
}, function (ret, res) { })
}
function onAddUser() {
Fast.api.ajax({
url: 'shopro/data/fake_user/getRandom',
type: 'GET',
}, function (ret, res) {
state.data.groupon_logs.push({
avatar: res.data.avatar,
nickname: res.data.nickname,
is_fictitious: 1,
is_temp: true,
});
return false
}, function (ret, res) { })
}
function onConfirm(item) {
Fast.api.ajax({
url: `shopro/activity/groupon/addUser/id/${state.id}`,
type: 'POST',
data: {
avatar: item.avatar,
nickname: item.nickname,
}
}, function (ret, res) {
getDetail()
}, function (ret, res) { })
}
function onCancel(index) {
state.data.groupon_logs.splice(index, 1);
}
onMounted(() => {
getDetail()
})
return {
state,
onInvalid,
onAddUser,
onConfirm,
onCancel,
}
}
}
createApp('detail', detail);
},
};
return Controller;
});

View File

@@ -0,0 +1,145 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ($, undefined, Backend, Table, Form, Moment) {
var Controller = {
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted } = Vue
const addEdit = {
setup() {
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
title: new URLSearchParams(location.search).get('title'),
})
const form = reactive({
model: {
type: 0,
name: '',
price_type: 1,
third_party_appid: '',
price: '',
price2: '',
cover_img_url: '',
},
rules: {
name: [{ validator: checkTitle, trigger: 'change' }],
cover_img_url: [{ required: true, message: '请选择商品封面', trigger: 'change' }],
},
});
const goods = reactive({
id: '', // 商品id
image: '', // 商品图片
title: '', // 商品名称
});
function checkTitle(rule, value, callback) {
if (!value) {
return callback(new Error('请输入商品名称'));
}
const length =
value.match(/[^ -~]/g) == null ? value.length : value.length + value.match(/[^ -~]/g).length;
if (length < 6 || length > 28) {
callback(new Error('直播标题必须为3-14个字一个字等于两个英文字符或特殊字符'));
} else {
callback();
}
}
//选择商品
function selectGoods() {
let id = '';
Fast.api.open(`shopro/goods/goods/select`, "选择商品", {
callback(data) {
console.log(data, 'data');
goods.image = data.image;
goods.title = data.title;
goods.id = data.id;
form.model.cover_img_url = data.image;
form.model.name = data.title;
form.model.url = 'pages/goods/index?id=' + goods.id;
if (data.price.length === 2) {
form.model.price_type = 2;
form.model.price = data.price[0];
form.model.price2 = data.price[1];
} else {
if (Number(data.original_price)) {
form.model.price_type = 3;
form.model.price = data.original_price;
form.model.price2 = data.price[0];
} else {
form.model.price_type = 1;
form.model.price = data.price[0];
}
}
form.model.goods_id = data.id;
}
})
}
// 获取商品信息
function getGoodsList(id) {
Fast.api.ajax({
url: `shopro/goods/goods/select`,
type: 'GET',
data: {
type: 'select',
search: JSON.stringify({ id }),
},
}, function (ret, res) {
goods.image = res.data[0].image;
goods.title = res.data[0].title;
return false
}, function (ret, res) { })
}
//获取详情
function getDetail() {
Fast.api.ajax({
url: `shopro/app/mplive/goods/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
getGoodsList(form.model.goods_id);
return false
}, function (ret, res) { })
}
function onConfirm() {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/app/mplive/goods/add' : `shopro/app/mplive/goods/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
goods,
form,
onConfirm,
getDetail,
checkTitle,
selectGoods,
getGoodsList
}
}
}
createApp('addEdit', addEdit);
},
};
return Controller;
});

View File

@@ -0,0 +1,260 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ($, undefined, Backend, Table, Form, Moment) {
var Controller = {
index: () => {
const { reactive, onMounted, ref, watch } = Vue
const index = {
setup() {
const state = reactive({
status: 0,
data: [],
filter: {
drawer: false,
data: {
name: '',
},
tools: {
name: {
type: 'tinput',
field: 'name',
value: '',
label: '商品名称',
placeholder: '请输入商品名称',
},
},
condition: {}
}
})
const dispatchType = ref('live');
// 直播间表格
const live = reactive({
data: [],
order: '',
sort: '',
selected: [],
});
//商品库表格
const goods = reactive({
data: [],
order: '',
sort: '',
});
// 获取直播间数据
function getLiveData() {
Fast.api.ajax({
url: 'shopro/app/mplive/room',
type: 'GET',
data: {
sort: live.sort,
order: live.order
},
}, function (ret, res) {
live.data = res.data;
return false
}, function (ret, res) { })
}
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
name: 'like',
});
Fast.api.ajax({
url: 'shopro/app/mplive/goods',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
goods.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function formatPrice(price, type) {
if (type === 1) {
return '';
} else if (type === 2) {
return '~' + price + '元';
} else {
return price + '元';
}
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function addRow() {
Fast.api.open(`shopro/app/mplive/room/add?type=add`, "添加直播间", {
callback() {
getLiveData()
}
})
}
function editRow(id) {
Fast.api.open(`shopro/app/mplive/room/edit?type=edit&id=${id}`, "编辑直播间", {
callback() {
getLiveData()
}
})
}
function deleteApi(id) {
Fast.api.ajax({
url: `shopro/app/mplive/room/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getLiveData()
}, function (ret, res) { })
}
//表格排序
function onChangeSort({ prop, order }) {
live.order = order == 'ascending' ? 'asc' : 'desc';
live.sort = prop;
getLiveData();
}
//推流地址
async function pushUrl(id) {
Fast.api.open(`shopro/app/mplive/room/pushUrl?id=${id}`, "推流地址", {
callback() {
getLiveData()
}
})
}
//分享二维码
async function shareQrcode(id) {
Fast.api.open(`shopro/app/mplive/room/qrcode?id=${id}`, "分享二维码", {
callback() {
getLiveData()
}
})
}
//同步直播间
function sync() {
Fast.api.ajax({
url: `shopro/app/mplive/room/sync`,
type: 'GET',
}, function (ret, res) {
live.data = res.data;
}, function (ret, res) { })
}
//直播回放
function playBack(id) {
Fast.api.open(`shopro/app/mplive/room/playback?id=${id}`, "直播回放列表", {
callback() {
getLiveData()
}
})
}
//添加商品
function addGoods() {
Fast.api.open(`shopro/app/mplive/goods/add?type=add`, "添加商品", {
callback() {
getData()
}
})
}
//编辑商品
function editGoods(id) {
Fast.api.open(`shopro/app/mplive/goods/edit?type=edit&id=${id}`, "编辑商品", {
callback() {
getData()
}
})
}
// 删除商品
function deleteGoods(id) {
Fast.api.ajax({
url: `shopro/app/mplive/goods/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
// 获取状态
function getStatus(id) {
Fast.api.ajax({
url: `shopro/app/mplive/goods/status/id/${id}`,
type: 'GET',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
//审核
function check(id, act) {
Fast.api.ajax({
url: `shopro/app/mplive/goods/audit/id/${id}`,
type: 'POST',
data: {
act
},
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
watch(() => dispatchType.value, () => {
if (dispatchType.value === 'live') {
getLiveData()
} else {
getData()
}
})
onMounted(() => {
getLiveData()
})
return {
state,
live,
goods,
dispatchType,
getData,
onOpenFilter,
onChangeFilter,
pagination,
formatPrice,
getLiveData,
addRow,
editRow,
deleteApi,
Moment,
sync,
playBack,
shareQrcode,
pushUrl,
addGoods,
editGoods,
deleteGoods,
check,
getStatus,
onChangeSort
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,329 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ($, undefined, Backend, Table, Form, Moment) {
var Controller = {
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, ref } = Vue
const addEdit = {
setup() {
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
title: new URLSearchParams(location.search).get('title'),
})
const form = reactive({
model: {
way: 'column',
type: 0,
name: '',
date_time: '',
anchor_name: '',
anchor_wechat: '',
sub_anchor_wechat: '',
is_feeds_public: 1,
close_kf: 0,
close_replay: 0,
close_comment: 0,
close_goods: 0,
close_like: 0,
feeds_img: '',
share_img: '',
cover_img: '',
},
rules: {
type: [{ required: true, message: '请选择直播类型', trigger: 'change' }],
way: [{ required: true, message: '请选择播放方式', trigger: 'change' }],
feeds_img: [{ required: true, message: '请选择封面图', trigger: 'change' }],
share_img: [{ required: true, message: '请选择分享图', trigger: 'change' }],
cover_img: [{ required: true, message: '请选择背景图', trigger: 'change' }],
date_time: [{ required: true, message: '请选择开播时间', trigger: 'change' }],
name: [{ required: true, message: '请输入直播间标题', trigger: 'blur' }, { validator: checkTitle, trigger: 'change' }],
anchor_name: [{ required: true, message: '请输入主播昵称', trigger: 'blur' }, { validator: checkNickname, trigger: 'change' }],
anchor_wechat: [{ required: true, message: '请输入主播微信账号', trigger: 'blur' }],
},
});
//获取默认开始时间为当前时间后40分钟
const defaultTime = ref([
new Date(new Date().getTime() + 40 * 60 * 1000),
new Date(2000, 2, 1, 23, 59, 59),
]);
// 禁止时间
function disabledDate(time) {
return time.getTime() < Date.now() - 86400000;
}
// 获取详情
function getDetail() {
Fast.api.ajax({
url: `shopro/app/mplive/room/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
form.model.date_time = [
Moment(res.data.start_time * 1000).format('YYYY-MM-DD HH:mm:ss'),
Moment(res.data.end_time * 1000).format('YYYY-MM-DD HH:mm:ss'),
];
return false
}, function (ret, res) { })
}
function onConfirm() {
let submitForm = {
...form.model,
start_time: Number(new Date(form.model.date_time[0]).getTime() / 1000),
end_time: Number(new Date(form.model.date_time[1]).getTime() / 1000),
}
delete submitForm.date_time
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/app/mplive/room/add' : `shopro/app/mplive/room/edit/id/${state.id}`,
type: 'POST',
data: submitForm,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
function checkTitle(rule, value, callback) {
if (!value) {
return callback(new Error('请输入直播间标题'));
}
const length =
value.match(/[^ -~]/g) == null ? value.length : value.length + value.match(/[^ -~]/g).length;
if (length < 6 || length > 34) {
callback(new Error('直播标题必须为3-17个字一个字等于两个英文字符或特殊字符'));
} else {
callback();
}
}
function checkNickname(rule, value, callback) {
if (!value) {
return callback(new Error('请输入主播昵称'));
}
const length =
value.match(/[^ -~]/g) == null ? value.length : value.length + value.match(/[^ -~]/g).length;
if (length < 4 || length > 30) {
callback(new Error('直播标题必须为2-15个字一个字等于两个英文字符或特殊字符'));
} else {
callback();
}
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
disabledDate,
onConfirm,
getDetail,
checkTitle,
checkNickname,
defaultTime
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { reactive, onMounted } = Vue
const select = {
setup() {
const state = reactive({
data: [],
selected: [],
});
function getData() {
Fast.api.ajax({
url: 'shopro/app/mplive/room/select',
type: 'GET',
}, function (ret, res) {
state.data = res.data;
return false
}, function (ret, res) { })
}
function isSelectable(row) {
return row.status === 101 || row.status === 102 || row.status === 103
}
function onSelectionChange(val) {
state.selected = val
}
function onConfirm() {
Fast.api.close(state.selected)
}
onMounted(() => {
getData()
})
return {
Moment,
state,
isSelectable,
onSelectionChange,
onConfirm,
}
}
}
createApp('select', select);
},
pushurl: () => {
const { reactive, onMounted } = Vue
const pushUrl = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
pushUrl: '', // 推流地址
serverAddress: '', // 服务器地址
key: '', // 串流密钥
})
function getDetail() {
Fast.api.ajax({
url: `shopro/app/mplive/room/pushUrl/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.pushUrl = res.data.pushAddr;
state.serverAddress = state.pushUrl.split('/live/')[0] + '/live/';
state.key = state.pushUrl.split('/live/')[1];
return false
}, function (ret, res) { })
}
function onJump() {
window.open('https://docs.qq.com/doc/DV0hoWHZRdm9oT2pp');
}
onMounted(() => {
getDetail()
})
return {
state,
getDetail,
onClipboard,
onJump
}
}
}
createApp('pushUrl', pushUrl);
},
qrcode: () => {
const { reactive, onMounted } = Vue
const qrcode = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
cdnUrl: '', // 小程序码
path: '', // 页面路径
key: '', // 串流密钥
})
function getDetail() {
Fast.api.ajax({
url: `shopro/app/mplive/room/qrcode/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.cdnUrl = res.data.cdnUrl;
state.path = res.data.pagePath;
return false
}, function (ret, res) { })
}
function saveImg() {
window.open(state.cdnUrl);
}
function onJump() {
window.open(
'https://developers.weixin.qq.com/miniprogram/dev/platform-capabilities/industry/liveplayer/live-player-plugin.html',
);
}
onMounted(() => {
getDetail()
})
return {
state,
getDetail,
onClipboard,
saveImg,
onJump
}
}
}
createApp('qrcode', qrcode);
},
playback: () => {
const { reactive, onMounted } = Vue
const playback = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
})
// 表格状态
const table = reactive({
data: [],
order: '',
sort: '',
selected: [],
});
function getData() {
Fast.api.ajax({
url: `shopro/app/mplive/room/playback/id/${state.id}`,
type: 'GET',
// data: {
// page: pagination.page,
// list_rows: pagination.list_rows,
// order: state.order,
// sort: state.sort,
// },
}, function (ret, res) {
table.data = res.data
table.data.forEach((item, index) => {
table.data[index].index = index + 1;
});
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function play(url) {
window.open(url);
}
onMounted(() => {
getData()
})
return {
state,
getData,
pagination,
table,
play
}
}
}
createApp('playback', playback);
},
};
return Controller;
});

View File

@@ -0,0 +1,396 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
keyword: { field: 'title', value: '' },
},
tools: {
keyword: {
type: 'tinputprepend',
label: '查询内容',
placeholder: '请输入查询内容',
value: {
field: 'title',
value: '',
},
options: {
data: [{
label: '商品名称',
value: 'title',
},
{
label: '商品副标题',
value: 'subtitle',
}],
},
},
},
condition: {}
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
title: 'like',
subtitle: 'like',
});
Fast.api.ajax({
url: 'shopro/app/score_shop',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
let expandRowKeys = reactive([]);
function expandRow(id) {
if (expandRowKeys.includes(id)) {
expandRowKeys.length = 0;
} else {
expandRowKeys.length = 0;
expandRowKeys.push(id);
getSkuPrices(id);
}
}
const skuPrices = reactive({
data: [],
});
function getSkuPrices(goods_id) {
Fast.api.ajax({
url: `shopro/app/score_shop/skuPrices/goods_id/${goods_id}`,
type: 'GET',
}, function (ret, res) {
skuPrices.data = res.data;
return false
}, function (ret, res) { })
}
function onAdd() {
Fast.api.open(`shopro/goods/goods/select?data_type=score_shop`, "选择商品", {
callback(data) {
Fast.api.open(`shopro/app/score_shop/add?type=add&goods_id=${data.id}&title=${data.title}`, "添加", {
callback() {
getData()
}
})
}
})
}
function onEdit(item) {
Fast.api.open(`shopro/app/score_shop/edit?type=edit&goods_id=${item.id}&title=${item.title}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/app/score_shop/delete/goods_id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onRecyclebin() {
Fast.api.open(`shopro/app/score_shop/recyclebin`, "回收站", {
callback() {
getData()
}
})
}
onMounted(() => {
getData()
})
return {
state,
getData,
onOpenFilter,
onChangeFilter,
pagination,
expandRowKeys,
expandRow,
skuPrices,
getSkuPrices,
onAdd,
onEdit,
onDelete,
onRecyclebin,
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted } = Vue
const addEdit = {
setup() {
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
goods_id: new URLSearchParams(location.search).get('goods_id'),
title: new URLSearchParams(location.search).get('title'),
})
const goods = reactive({
skus: [],
sku_prices: [],
score_sku_prices: [],
})
function getSkus() {
Fast.api.ajax({
url: `shopro/app/score_shop/skus/goods_id/${state.goods_id}`,
type: 'GET',
}, function (ret, res) {
goods.skus = res.data.skus;
goods.sku_prices = res.data.sku_prices;
goods.score_sku_prices = res.data.score_sku_prices;
return false
}, function (ret, res) { })
}
function onConfirm() {
let submitForm = {
sku_prices: goods.score_sku_prices,
}
if (state.type == 'add') {
submitForm = {
goods_id: state.goods_id,
...submitForm,
}
}
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/app/score_shop/add' : `shopro/app/score_shop/edit/goods_id/${state.goods_id}`,
type: 'POST',
data: submitForm,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
onMounted(() => {
getSkus()
})
return {
state,
goods,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { reactive, onMounted } = Vue
const select = {
setup() {
const state = reactive({
multiple: new URLSearchParams(location.search).get('multiple') || false,
data: [],
select: [],
})
function getData() {
Fast.api.ajax({
url: 'shopro/app/score_shop/select',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onChangeSelection(val) {
state.select = val
}
function onSelect(item) {
Fast.api.close(item)
}
function onConfirm() {
Fast.api.close(state.select)
}
onMounted(() => {
getData()
})
return {
state,
getData,
pagination,
onChangeSelection,
onSelect,
onConfirm
}
}
}
createApp('select', select);
},
recyclebin: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const recyclebin = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/app/score_shop/recyclebin',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'restore':
onRestore(ids.join(','))
break;
case 'destroy':
ElMessageBox.confirm('此操作将销毁, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy(ids.join(','))
});
break;
case 'all':
ElMessageBox.confirm('此操作将清空回收站, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy('all')
});
break;
}
}
function onRestore(id) {
Fast.api.ajax({
url: `shopro/app/score_shop/restore/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onDestroy(id) {
Fast.api.ajax({
url: `shopro/app/score_shop/destroy/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onRestore,
onDestroy,
}
}
}
createApp('recyclebin', recyclebin);
},
};
return Controller;
});

View File

@@ -0,0 +1,373 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
name: '',
},
tools: {
name: {
type: 'tinput',
label: '分类名称',
placeholder: '请输入分类名称',
value: '',
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
name: 'like',
});
Fast.api.ajax({
url: 'shopro/category',
type: 'GET',
data: {
...search,
},
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
getData()
state.filter.drawer && (state.filter.drawer = false)
}
function onAdd() {
Fast.api.open("shopro/category/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/category/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/category/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onOpenFilter,
onChangeFilter,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { ref,reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const id = ref(0)
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
styleList: {
1: [{ type: 'first_one', name: '一' },
{ type: 'first_two', name: '二' }],
2: [{ type: 'second_one', name: '一' }],
3: [{ type: 'third_one', name: '一' }],
},
level: 1,
multIndex: 1,
treeData: [],
})
const form = reactive({
model: {
style: 'first_one',
name: '',
description: '',
weigh: 0,
status: 'normal',
},
rules: {
name: [{ required: true, message: '请输入分类名称', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/category/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data.category;
state.treeData = res.data.categories;
if (form.model.style.substring(0, 1) == 'f') {
state.level = 1;
} else if (form.model.style.substring(0, 1) == 's') {
state.level = 2;
} else {
state.level = 3;
}
return false
}, function (ret, res) { })
}
function onChangeLevel() {
form.model.style = '';
loopChildren(state.treeData);
}
function loopChildren(data, level = 1) {
state.multIndex = 1;
loopLevel(state.treeData);
if (state.multIndex <= state.level) {
level += 1;
if (data.length == 0) {
level -= 1;
if (level <= state.level) {
data.push({
id: 'new' + (id.value++),
name: '',
image: '',
description: '',
weigh: 0,
status: 'normal',
});
loopChildren(data, level);
}
} else {
if (level <= state.level) {
data.forEach((k) => {
if (!k.children) {
k.children = [
{
id: 'new' + (id.value++),
name: '',
image: '',
description: '',
weigh: 0,
status: 'normal',
},
];
}
loopChildren(k.children, level);
});
}
}
} else if (state.multIndex > state.level) {
data.forEach((l) => {
if (level == state.level) {
delete l.children;
} else {
level += 1;
if (l.children && l.children.length > 0) {
loopChildren(l.children, level);
}
}
});
}
}
function loopLevel(arr) {
arr.forEach((a) => {
if (a.children) {
state.multIndex += 1;
loopLevel(a.children);
}
});
}
function onAdd() {
state.treeData.unshift({
id: 'new' + (id.value++),
name: '',
description: '',
image: '',
weigh: 0,
status: 'normal',
children: [],
});
}
function onAppend(data) {
const newChild = {
id: 'new' + (id.value++),
name: '',
description: '',
image: '',
weigh: 0,
status: 'normal',
};
if (!data.children) {
data.children = [];
}
data.children.unshift(newChild);
}
function onRemove(node, data) {
const parent = node.parent;
const children = parent.data.children || parent.data;
const index = children.findIndex((d) => d.id == data.id);
if (children[index].children) {
children[index].deleted = 1;
children[index].children.forEach((i) => {
i.deleted = 1;
if (i.children) {
i.children.forEach((j) => {
j.deleted = 1;
});
}
});
} else {
children[index].deleted = 1;
}
}
function onConfirm() {
const submitForm = JSON.parse(JSON.stringify(form.model))
state.treeData.forEach(i => {
if (i.id?.toString().substring(0, 3) === 'new') {
delete i.id
}
if (i.children) {
i.children.forEach(j => {
if (j.id?.toString().substring(0, 3) === 'new') {
delete j.id
}
if (j.children) {
j.children.forEach(k => {
if (k.id?.toString().substring(0, 3) === 'new') {
delete k.id
}
})
}
})
}
})
submitForm.categories = JSON.stringify(state.treeData)
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/category/add' : `shopro/category/edit/id/${state.id}`,
type: 'POST',
data: submitForm
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
if (state.type == 'add') {
loopChildren(state.treeData);
}
if (state.type == 'edit') {
getDetail()
}
})
return {
state,
form,
onChangeLevel,
onAdd,
onAppend,
onRemove,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const select = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
from: new URLSearchParams(location.search).get('from'),
multiple: new URLSearchParams(location.search).get('multiple') || false,
data: [],
selectedIds: []
})
function getData() {
Fast.api.ajax({
url: 'shopro/category/select',
type: 'GET',
}, function (ret, res) {
state.data = res.data;
if (state.from == 'page-category') {
state.data.forEach((item) => {
item?.children && delete item.children;
});
}
if (state.from == 'coupon' || state.from == 'page-goods') {
state.data.forEach((item) => {
item.disabled = true;
});
}
return false
}, function (ret, res) { })
}
function onConfirm() {
let data = [];
proxy.$refs['categoryRef'].checkedNodes.forEach((c) => {
data.push(c.data);
});
Fast.api.close({
ids: state.selectedIds,
data: data,
})
}
onMounted(() => {
getData()
})
return {
state,
onConfirm
}
}
}
createApp('select', select);
}
};
return Controller;
});

View File

@@ -0,0 +1,290 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
user: { field: 'id', value: '' },
room_id: '',
},
tools: {
user: {
type: 'tinputprepend',
label: '查询内容',
placeholder: '请输入查询内容',
value: {
field: 'id',
value: '',
},
options: {
data: [{
label: 'ID',
value: 'id',
},
{
label: '名称',
value: 'name',
}],
}
},
room_id: {
type: 'tselect',
label: '客服分类',
value: '',
options: {
data: [],
props: {
label: 'name'
}
},
},
},
condition: {},
}
})
function getChatConfig() {
Fast.api.ajax({
url: `shopro/chat/index/init`,
type: 'GET',
}, function (ret, res) {
state.filter.tools.room_id.options.data = res.data.default_rooms
return false
}, function (ret, res) { })
}
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
name: 'like',
});
Fast.api.ajax({
url: 'shopro/chat/common_word',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
default:
Fast.api.ajax({
url: `shopro/chat/common_word/edit/id/${ids.join(',')}`,
type: 'POST',
data: {
status: type
}
}, function (ret, res) {
getData()
}, function (ret, res) { })
break;
}
}
function onAdd() {
Fast.api.open("shopro/chat/common_word/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/chat/common_word/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/chat/common_word/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getChatConfig()
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance, nextTick } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
room_id: '',
name: '',
content: '',
status: 'normal',
weigh: 0,
},
rules: {
room_id: [{ required: true, message: '请选择客服分类', trigger: ['blur', 'change'] }],
name: [{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }],
content: [{ required: true, message: '请输入问题内容', trigger: ['blur', 'change'] }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/chat/common_word/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
nextTick(() => {
Controller.api.bindevent();
$('#commonWordContent').html(form.model.content)
})
return false
}, function (ret, res) { })
}
const chat = reactive({
config: {}
})
function getChatConfig() {
Fast.api.ajax({
url: `shopro/chat/index/init`,
type: 'GET',
}, function (ret, res) {
chat.config = res.data
return false
}, function (ret, res) { })
}
function onConfirm() {
form.model.content = $("#commonWordContent").val();
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/chat/common_word/add' : `shopro/chat/common_word/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
getChatConfig()
if (state.type == 'add') {
nextTick(() => {
Controller.api.bindevent();
})
} else if (state.type == 'edit') {
getDetail()
}
})
return {
state,
form,
chat,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
},
},
};
return Controller;
});

View File

@@ -0,0 +1,288 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
user: { field: 'id', value: '' },
room_id: '',
},
tools: {
user: {
type: 'tinputprepend',
label: '查询内容',
placeholder: '请输入查询内容',
value: {
field: 'id',
value: '',
},
options: {
data: [{
label: 'ID',
value: 'id',
},
{
label: '客服名称',
value: 'name',
}],
}
},
room_id: {
type: 'tselect',
label: '客服分类',
value: '',
options: {
data: [],
props: {
label: 'name'
}
},
},
},
condition: {},
}
})
function getChatConfig() {
Fast.api.ajax({
url: `shopro/chat/index/init`,
type: 'GET',
}, function (ret, res) {
state.filter.tools.room_id.options.data = res.data.default_rooms
return false
}, function (ret, res) { })
}
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
name: 'like',
});
Fast.api.ajax({
url: 'shopro/chat/customer_service',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
}
}
function onAdd() {
Fast.api.open("shopro/chat/customer_service/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/chat/customer_service/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/chat/customer_service/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getChatConfig()
getData()
})
return {
Fast,
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
room_id: '',
auth: 'admin',
auth_id: '',
name: '',
avatar: '',
max_num: 0,
},
rules: {
room_id: [{ required: true, message: '请选择客服分类', trigger: ['blur', 'change'] }],
auth_id: [{ required: true, message: '请选择所属管理员', trigger: ['blur', 'change'] }],
name: [{ required: true, message: '请输入客服名称', trigger: ['blur', 'change'] }],
avatar: [{ required: true, message: '请选择客服头像', trigger: ['blur', 'change'] }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/chat/customer_service/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data
form.model.auth = res.data.customer_service_user?.auth;
form.model.auth_id = res.data.customer_service_user?.auth_id;
getCustomerServiceSelect()
return false
}, function (ret, res) { })
}
const chat = reactive({
config: {}
})
function getChatConfig() {
Fast.api.ajax({
url: `shopro/chat/index/init`,
type: 'GET',
}, function (ret, res) {
chat.config = res.data
return false
}, function (ret, res) { })
}
const customerService = reactive({
select: []
})
function getCustomerServiceSelect() {
Fast.api.ajax({
url: `shopro/chat/customer_service/select`,
type: 'GET',
data: {
id: state.id,
room_id: form.model.room_id,
},
}, function (ret, res) {
customerService.select = res.data
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/chat/customer_service/add' : `shopro/chat/customer_service/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
getChatConfig()
state.type == 'edit' && getDetail()
})
return {
state,
form,
chat,
customerService,
getCustomerServiceSelect,
onConfirm
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,290 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
user: { field: 'id', value: '' },
room_id: '',
},
tools: {
user: {
type: 'tinputprepend',
label: '查询内容',
placeholder: '请输入查询内容',
value: {
field: 'id',
value: '',
},
options: {
data: [{
label: 'ID',
value: 'id',
},
{
label: '标题',
value: 'title',
}],
}
},
room_id: {
type: 'tselect',
label: '客服分类',
value: '',
options: {
data: [],
props: {
label: 'name'
}
},
},
},
condition: {},
}
})
function getChatConfig() {
Fast.api.ajax({
url: `shopro/chat/index/init`,
type: 'GET',
}, function (ret, res) {
state.filter.tools.room_id.options.data = res.data.default_rooms
return false
}, function (ret, res) { })
}
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
title: 'like',
});
Fast.api.ajax({
url: 'shopro/chat/question',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
default:
Fast.api.ajax({
url: `shopro/chat/question/edit/id/${ids.join(',')}`,
type: 'POST',
data: {
status: type
}
}, function (ret, res) {
getData()
}, function (ret, res) { })
break;
}
}
function onAdd() {
Fast.api.open("shopro/chat/question/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/chat/question/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/chat/question/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getChatConfig()
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance, nextTick } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
room_id: '',
title: '',
content: '',
status: 'normal',
weigh: 0,
},
rules: {
room_id: [{ required: true, message: '请选择客服分类', trigger: ['blur', 'change'] }],
title: [{ required: true, message: '请输入标题', trigger: ['blur', 'change'] }],
content: [{ required: true, message: '请输入问题内容', trigger: ['blur', 'change'] }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/chat/question/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
nextTick(() => {
Controller.api.bindevent();
$('#questionContent').html(form.model.content)
})
return false
}, function (ret, res) { })
}
const chat = reactive({
config: {}
})
function getChatConfig() {
Fast.api.ajax({
url: `shopro/chat/index/init`,
type: 'GET',
}, function (ret, res) {
chat.config = res.data
return false
}, function (ret, res) { })
}
function onConfirm() {
form.model.content = $("#questionContent").val();
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/chat/question/add' : `shopro/chat/question/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
getChatConfig()
if (state.type == 'add') {
nextTick(() => {
Controller.api.bindevent();
})
} else if (state.type == 'edit') {
getDetail()
}
})
return {
state,
form,
chat,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
},
},
};
return Controller;
});

View File

@@ -0,0 +1,223 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment', 'moment/locale/zh-cn'], function ($, undefined, Backend, Table, Form, Moment) {
var Controller = {
index: () => {
const { unref, reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
nickname: new URLSearchParams(location.search).get('nickname'),
room_id: 'admin',
room_name: '',
data: [],
})
const chat = reactive({
config: {}
})
function getChatConfig() {
Fast.api.ajax({
url: `shopro/chat/index/init`,
type: 'GET',
}, function (ret, res) {
chat.config = res.data
onCommand()
return false
}, function (ret, res) { })
}
function getData() {
pagination.page += 1;
pagination.loadStatus = 'loading';
Fast.api.ajax({
url: 'shopro/chat/record',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
search: JSON.stringify({
chat_user_id: state.id,
room_id: state.room_id,
}),
},
}, function (ret, res) {
if (pagination.page == 1) {
state.data = []
}
res.data.data.forEach((item) => {
state.data.unshift(item);
});
pagination.page = res.data.current_page;
pagination.lastPage = res.data.last_page;
pagination.loadStatus = pagination.page < pagination.lastPage ? 'loadmore' : 'nomore';
if (pagination.last_id == 0) {
pagination.last_id = res.data.data.length > 0 ? res.data.data[0].id : 0;
}
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 0,
list_rows: 10,
total: 0,
last_id: 0,
lastPage: 0,
loadStatus: 'loadmore',
})
function onLoadMore() {
pagination.page < pagination.lastPage && getData();
}
function onCommand(room_id = state.room_id) {
state.room_id = room_id
state.room_name = chat.config.default_rooms?.find(item => item.value == state.room_id).name
pagination.page = 0
pagination.last_id = 0
pagination.lastPage = 0
pagination.loadStatus = 'loadmore'
getData()
}
const loadingMap = {
loadmore: {
title: '查看更多',
},
nomore: {
title: '没有更多了',
},
loading: {
title: '加载中... ',
},
};
function replaceEmoji(data) {
let newData = data;
if (typeof newData != 'object') {
let reg = /\[(.+?)\]/g; // [] 中括号
let zhEmojiName = newData.match(reg);
if (zhEmojiName) {
zhEmojiName.forEach((item) => {
let emojiFile = selEmojiFile(item);
newData = newData.replace(
item,
`<img class="record-emoji" src="${Fast.api.cdnurl(`/assets/addons/shopro/img/chat/emoji/${emojiFile}`)}" />`,
);
});
}
}
return newData;
}
function selEmojiFile(name) {
let emojiData = [
{ "name": "[笑掉牙]", "file": "xiaodiaoya.png" },
{ "name": "[可爱]", "file": "keai.png" },
{ "name": "[冷酷]", "file": "lengku.png" },
{ "name": "[闭嘴]", "file": "bizui.png" },
{ "name": "[生气]", "file": "shengqi.png" },
{ "name": "[惊恐]", "file": "jingkong.png" },
{ "name": "[瞌睡]", "file": "keshui.png" },
{ "name": "[大笑]", "file": "daxiao.png" },
{ "name": "[爱心]", "file": "aixin.png" },
{ "name": "[坏笑]", "file": "huaixiao.png" },
{ "name": "[飞吻]", "file": "feiwen.png" },
{ "name": "[疑问]", "file": "yiwen.png" },
{ "name": "[开心]", "file": "kaixin.png" },
{ "name": "[发呆]", "file": "fadai.png" },
{ "name": "[流泪]", "file": "liulei.png" },
{ "name": "[汗颜]", "file": "hanyan.png" },
{ "name": "[惊悚]", "file": "jingshu.png" },
{ "name": "[困~]", "file": "kun.png" },
{ "name": "[心碎]", "file": "xinsui.png" },
{ "name": "[天使]", "file": "tianshi.png" },
{ "name": "[晕]", "file": "yun.png" },
{ "name": "[啊]", "file": "a.png" },
{ "name": "[愤怒]", "file": "fennu.png" },
{ "name": "[睡着]", "file": "shuizhuo.png" },
{ "name": "[面无表情]", "file": "mianwubiaoqing.png" },
{ "name": "[难过]", "file": "nanguo.png" },
{ "name": "[犯困]", "file": "fankun.png" },
{ "name": "[好吃]", "file": "haochi.png" },
{ "name": "[呕吐]", "file": "outu.png" },
{ "name": "[龇牙]", "file": "ziya.png" },
{ "name": "[懵比]", "file": "mengbi.png" },
{ "name": "[白眼]", "file": "baiyan.png" },
{ "name": "[饿死]", "file": "esi.png" },
{ "name": "[凶]", "file": "xiong.png" },
{ "name": "[感冒]", "file": "ganmao.png" },
{ "name": "[流汗]", "file": "liuhan.png" },
{ "name": "[笑哭]", "file": "xiaoku.png" },
{ "name": "[流口水]", "file": "liukoushui.png" },
{ "name": "[尴尬]", "file": "ganga.png" },
{ "name": "[惊讶]", "file": "jingya.png" },
{ "name": "[大惊]", "file": "dajing.png" },
{ "name": "[不好意思]", "file": "buhaoyisi.png" },
{ "name": "[大闹]", "file": "danao.png" },
{ "name": "[不可思议]", "file": "bukesiyi.png" },
{ "name": "[爱你]", "file": "aini.png" },
{ "name": "[红心]", "file": "hongxin.png" },
{ "name": "[点赞]", "file": "dianzan.png" },
{ "name": "[恶魔]", "file": "emo.png" }
]
for (let index in emojiData) {
if (emojiData[index].name == name) {
return emojiData[index].file;
}
}
return false;
}
function showTime(item, index) {
if (state.data[index + 1]) {
let dateString = Moment(state.data[index + 1].createtime * 1000).fromNow();
if (dateString == Moment(item.createtime * 1000).fromNow()) {
return false;
} else {
dateString = Moment(item.createtime * 1000).fromNow();
return true;
}
}
return false;
};
// 格式化时间
function formatTime(time) {
let diffTime = Moment().unix() - time;
if (diffTime > 28 * 24 * 60) {
return Moment(time * 1000).format('MM/DD HH:mm');
}
if (diffTime > 360 * 28 * 24 * 60) {
return Moment(time * 1000).format('YYYY/MM/DD HH:mm');
}
return Moment(time * 1000).fromNow();
};
onMounted(() => {
getChatConfig()
})
return {
Fast,
state,
chat,
getData,
pagination,
onLoadMore,
onCommand,
loadingMap,
replaceEmoji,
showTime,
formatTime,
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,154 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
user: { field: 'id', value: '' },
},
tools: {
user: {
type: 'tinputprepend',
label: '查询内容',
placeholder: '请输入查询内容',
value: {
field: 'id',
value: '',
},
options: {
data: [{
label: 'ID',
value: 'id',
},
{
label: '昵称',
value: 'nickname',
},
{
label: '手机号',
value: 'user.mobile',
}],
}
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
nickname: 'like',
'user.mobile': 'like',
});
Fast.api.ajax({
url: 'shopro/chat/user',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
}
}
function onRecord(item) {
Fast.api.open(`shopro/chat/record/index?id=${item.id}&nickname=${item.nickname}`, "聊天记录", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/chat/user/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
Fast,
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onRecord,
onDelete
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,506 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
data: () => {
return {
statusStyle: {
normal: { label: '正常', color: '#52c41a' },
pending: { label: '审核中', color: '#faad14' },
reject: { label: '拒绝', color: '#f56c6c' },
freeze: { label: '冻结', color: '#409eff' },
forbidden: { label: '禁用', color: '#999999' },
}
}
},
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
tabActive: 'all',
user: { field: 'user_id', value: '' },
level: '',
status: '',
createtime: [],
},
tools: {
user: {
type: 'tinputprepend',
label: '会员信息',
placeholder: '请输入查询内容',
value: {
field: 'user_id',
value: '',
},
options: {
data: [{
label: '用户ID',
value: 'user_id',
},
{
label: '用户昵称',
value: 'user.nickname',
},
{
label: '用户手机号',
value: 'user.mobile',
}]
}
},
level: {
type: 'tselect',
label: '分销商等级',
value: '',
options: {
data: [],
props: {
label: 'name',
value: 'level',
},
},
},
status: {
type: 'tselect',
label: '审核状态',
value: '',
options: {
data: [{
value: 'normal',
label: '正常',
},
{
value: 'forbidden',
label: '禁用',
},
{
value: 'pending',
label: '审核中',
},
{
value: 'freeze',
label: '冻结',
},
{
value: 'reject',
label: '拒绝',
}],
},
},
createtime: {
type: 'tdatetimerange',
label: '更新时间',
value: [],
},
},
condition: {},
}
})
const type = reactive({
data: {
status: [{
type: 'all',
name: '分销商',
},
{
type: 'pending',
name: '待审核',
},
{
type: '0',
name: '待升级',
}],
}
})
function getLevelSelect() {
Fast.api.ajax({
url: `shopro/commission/level/select`,
type: 'GET',
}, function (ret, res) {
state.filter.tools.level.options.data = res.data;
return false
}, function (ret, res) { })
}
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'user.nickname': 'like',
'user.mobile': 'like',
createtime: 'range',
});
let temp = JSON.parse(search.search);
if (temp && temp.tabActive) {
if (temp.tabActive[0] == 'pending') {
temp.status = ['pending', '='];
delete temp.tabActive;
} else if (temp.tabActive[0] == '0') {
temp.level_status = ['0', '>'];
delete temp.tabActive;
}
}
search = { search: JSON.stringify(temp) };
Fast.api.ajax({
url: 'shopro/commission/agent',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
function onChangeTab() {
pagination.page = 1
getData()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onEdit(id, data) {
Fast.api.ajax({
url: `shopro/commission/agent/edit/id/${id}`,
type: 'POST',
data: data,
}, function (ret, res) {
getData();
}, function (ret, res) { })
}
function onDetail(id) {
Fast.api.open(`shopro/commission/agent/detail/id/${id}?id=${id}`, "详情", {
callback() {
getData()
}
})
}
onMounted(() => {
getLevelSelect()
getData()
})
return {
...Controller.data(),
state,
type,
getData,
onOpenFilter,
onChangeFilter,
onChangeTab,
pagination,
onEdit,
onDetail,
}
}
}
createApp('index', index);
},
detail: () => {
const { reactive, onMounted } = Vue
const detail = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
data: {},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/commission/agent/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.data = res.data
applyInfo.data = JSON.parse(JSON.stringify(state.data.apply_info))
getLog()
return false
}, function (ret, res) { })
}
function onChangeStatus(status) {
onEdit({ status });
}
function onChangeLevel() {
Fast.api.open(`shopro/commission/level/select?level=${state.data.level}`, "更换分销等级", {
callback(level) {
onEdit({ level });
}
})
}
function onChangeParentUser() {
Fast.api.open(`shopro/commission/agent/select?id=${state.data.user_id}`, "更换上级分销商", {
callback() {
getDetail()
}
})
}
const applyInfo = reactive({
flag: false,
data: []
})
function onCancelApplyInfo() {
applyInfo.data = JSON.parse(JSON.stringify(state.data.apply_info));
applyInfo.flag = false;
}
function onSaveApplyInfo() {
onEdit({ apply_info: applyInfo.data });
applyInfo.flag = false;
}
function onDeleteApplyInfo(index) {
applyInfo.data.splice(index, 1);
}
function onEdit(data) {
Fast.api.ajax({
url: `shopro/commission/agent/edit/id/${state.id}`,
type: 'POST',
data,
}, function (ret, res) {
getDetail()
}, function (ret, res) { })
}
function onTeam() {
Fast.api.open(`shopro/commission/agent/team?id=${state.id}`, "查看团队")
}
const log = reactive({
tabActive: 'log',
data: [],
status: {
0: 'info',
1: 'success',
'-1': 'warning',
'-2': 'danger',
}
})
function getLog() {
let search = composeFilter({ agent_id: state.id });
Fast.api.ajax({
url: `shopro/commission/${log.tabActive}`,
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
if (log.tabActive == 'order') {
log.data = res.data.list.data;
pagination.total = res.data.list.total;
} else {
log.data = res.data.data;
pagination.total = res.data.total;
}
return false
}, function (ret, res) { })
}
function onChangeTab() {
pagination.page = 1
log.data = []
getLog()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function countCommission(item) {
if (item) {
let commission = 0;
let commissioned = 0;
item.forEach((r) => {
if (r.status == 1) {
commissioned += Number(r.commission);
}
commission += Number(r.commission);
});
return `${commission}元/${commissioned}`;
}
}
onMounted(() => {
getDetail()
})
return {
...Controller.data(),
state,
getDetail,
onChangeStatus,
onChangeLevel,
onChangeParentUser,
applyInfo,
onCancelApplyInfo,
onSaveApplyInfo,
onDeleteApplyInfo,
onEdit,
onTeam,
log,
getLog,
onChangeTab,
pagination,
countCommission,
}
}
}
createApp('detail', detail);
},
select: () => {
const { reactive, onMounted } = Vue
const { ElMessage } = ElementPlus
const select = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
data: [],
filter: {
data: {
user: { field: 'user_id', value: '' },
},
},
userDetail: {},
parent_user_id: ''
})
async function getUserDetail() {
Fast.api.ajax({
url: `shopro/user/user/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.userDetail = res.data;
state.parent_user_id = state.userDetail?.parent_user_id;
return false
}, function (ret, res) { })
}
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'user.nickname': 'like',
'user.mobile': 'like',
});
Fast.api.ajax({
url: 'shopro/commission/agent/select',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onSelect(row) {
state.parent_user_id = row.user_id;
}
async function onConfirm() {
if (state.parent_user_id == -1) {
ElMessage.info('请选择上级');
return;
}
Fast.api.ajax({
url: `shopro/commission/agent/changeParentUser/id/${state.id}`,
type: 'POST',
data: {
parent_user_id: state.parent_user_id,
},
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
onMounted(() => {
getUserDetail()
getData()
})
return {
...Controller.data(),
state,
getData,
pagination,
onSelect,
onConfirm,
}
}
}
createApp('select', select);
},
team: () => {
const { reactive, onMounted } = Vue
const team = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
data: {},
})
async function getTeam(id) {
Fast.api.ajax({
url: `shopro/commission/agent/team/id/${id}`,
type: 'GET',
}, function (ret, res) {
state.data = res.data;
return false
}, function (ret, res) { })
}
onMounted(() => {
getTeam(state.id)
})
return {
...Controller.data(),
state,
getTeam,
}
}
}
createApp('team', team);
},
};
return Controller;
});

View File

@@ -0,0 +1,435 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
keyword: { field: 'id', value: '' },
'commission_goods.status': '',
},
tools: {
keyword: {
type: 'tinputprepend',
label: '商品信息',
placeholder: '请输入查询内容',
value: {
field: 'id',
value: '',
},
options: {
data: [{
label: '商品ID',
value: 'id',
},
{
label: '商品名称',
value: 'title',
},
{
label: '商品副标题',
value: 'subtitle',
}],
}
},
'commission_goods.status': {
type: 'tselect',
label: '分销状态',
value: '',
options: {
data: [{
label: '不参与',
value: '0',
},
{
label: '参与中',
value: '1',
}],
},
},
},
condition: {},
},
goodsStatusStyle: {
0: 'danger',
1: 'success',
},
statusStyle: {
up: 'success',
down: 'danger',
hidden: 'info',
},
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
title: 'like',
subtitle: 'like',
});
Fast.api.ajax({
url: 'shopro/commission/goods',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'edit':
onEdit(ids.join(','), 'batch')
break;
}
}
function onEdit(ids, rulesType = '') {
Fast.api.open(`shopro/commission/goods/edit?type=edit&id=${ids}&rulesType=${rulesType}`, "设置佣金", {
callback() {
getData()
}
})
}
onMounted(() => {
getData()
})
return {
state,
getData,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onEdit,
}
}
}
createApp('index', index);
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted } = Vue
const { ElMessage } = ElementPlus
const addEdit = {
setup() {
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
rulesType: new URLSearchParams(location.search).get('rulesType'),
detailData: {},
commission_goods: {
status: 1,
self_rules: new URLSearchParams(location.search).get('rulesType') == 'batch' ? 2 : 0,
commission_order_status: 1,
commission_config: {},
commission_rules: {},
},
defaultCommissionConfig: {
status: 0,
level: 2,
self_buy: 0,
reward_type: 'goods_price',
reward_event: 'paid',
},
commission_config_temp: {},
commission_rules: {},
levelData: [],
})
function getDetail() {
Fast.api.ajax({
url: `shopro/commission/goods/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.data = res.data;
if (state.rulesType != 'batch') {
state.detailData = state.data.goods[0];
}
Object.keys(state.defaultCommissionConfig).forEach((key) => {
if (key != 'status') state.defaultCommissionConfig[key] = state.data.config[key];
});
state.commission_config_temp = JSON.parse(JSON.stringify(state.defaultCommissionConfig));
if (isEmpty(state.detailData.commission_goods)) {
initCommission(state.commission_goods.self_rules);
} else {
state.commission_goods = state.detailData.commission_goods;
if (
state.detailData.commission_goods.commission_config &&
state.detailData.commission_goods.commission_config.status
) {
state.commission_config_temp = state.detailData.commission_goods.commission_config;
}
initCommission(state.detailData.commission_goods.self_rules);
}
return false
}, function (ret, res) { })
}
function getLevelSelect() {
Fast.api.ajax({
url: `shopro/commission/level/select`,
type: 'GET',
data: {
sort: 'level',
order: 'asc',
}
}, function (ret, res) {
state.levelData = res.data;
state.type == 'edit' && getDetail()
return false
}, function (ret, res) { })
}
function initCommission(type) {
let rate_money = {
1: {
rate: '',
money: '',
},
2: {
rate: '',
money: '',
},
3: {
rate: '',
money: '',
},
};
if (!isObject(state.commission_goods.commission_rules)) {
state.commission_goods.commission_rules = {};
}
if (type == 0) {
state.commission_goods.commission_rules = null;
} else if (type == 1) {
state.detailData.sku_prices.forEach((i) => {
if (state.commission_goods.commission_rules[i.id]) {
state.levelData.forEach((j) => {
if (state.commission_goods.commission_rules[i.id][j.level]) {
for (let key in state.commission_goods.commission_rules[i.id][j.level]) {
if (!state.commission_goods.commission_rules[i.id][j.level][key].rate) {
state.commission_goods.commission_rules[i.id][j.level][key].rate = '';
} else if (!state.commission_goods.commission_rules[i.id][j.level][key].money) {
state.commission_goods.commission_rules[i.id][j.level][key].money = '';
}
}
} else {
state.commission_goods.commission_rules[i.id][j.level] = JSON.parse(JSON.stringify(rate_money));
}
});
for (var level in state.commission_goods.commission_rules[i.id]) {
let index = state.levelData.findIndex((l) => Number(l.level) == Number(level));
if (index == -1) {
delete state.commission_goods.commission_rules[i.id][level];
}
}
} else {
state.commission_goods.commission_rules[i.id] = {};
state.levelData.forEach((l) => {
state.commission_goods.commission_rules[i.id][l.level] = JSON.parse(JSON.stringify(rate_money));
});
}
});
for (var sku in state.commission_goods.commission_rules) {
let index = state.detailData.sku_prices.findIndex((s) => Number(s.id) == Number(sku));
if (index == -1) {
delete state.commission_goods.commission_rules[sku];
}
}
} else if (type == 2) {
state.levelData.forEach((l) => {
if (state.commission_goods.commission_rules[l.level]) {
} else {
state.commission_goods.commission_rules[l.level] = JSON.parse(JSON.stringify(rate_money));
}
});
for (var level in state.commission_goods.commission_rules) {
let index = state.levelData.findIndex((l) => Number(l.level) == Number(level));
if (index == -1) {
delete state.commission_goods.commission_rules[level];
}
}
}
}
function onChangeSelfRules(self_rules) {
if (self_rules == 1 || self_rules == 2) {
state.commission_goods.commission_rules = {};
if (state.commission_config_temp.status == 0) {
state.commission_config_temp = JSON.parse(JSON.stringify(state.defaultCommissionConfig));
}
} else if (self_rules == 0) {
state.commission_goods.commission_rules = null;
state.commission_config_temp = JSON.parse(JSON.stringify(state.defaultCommissionConfig));
}
initCommission(self_rules);
}
function onChangeCommissionConfigStatus(val) {
if (val == 0) {
// 默认
state.commission_config_temp = JSON.parse(JSON.stringify(state.defaultCommissionConfig));
} else {
// 自定义
if (
state.detailData.commission_goods &&
state.detailData.commission_goods.commission_config
) {
state.commission_config_temp = state.detailData.commission_goods.commission_config;
}
state.commission_config_temp.status = 1;
}
}
const commissionPopover = reactive({
flag: {},
form: {
money: '',
rate: '',
},
});
function onConfirmCommissionPopover(cl) {
if (state.commission_goods.self_rules == 1) {
for (let sku in state.commission_goods.commission_rules) {
for (let level in state.commission_goods.commission_rules[sku]) {
state.commission_goods.commission_rules[sku][level][cl] = JSON.parse(JSON.stringify(commissionPopover.form))
}
}
} else if (state.commission_goods.self_rules == 2) {
for (let level in state.commission_goods.commission_rules) {
state.commission_goods.commission_rules[level][cl] = JSON.parse(JSON.stringify(commissionPopover.form))
}
}
onCancelCommissionPopover(cl);
}
function onCancelCommissionPopover(cl) {
commissionPopover.flag[cl] = false;
commissionPopover.form = {
money: '',
rate: '',
};
}
function onConfirm() {
const commission_goods = {
...state.commission_goods,
};
commission_goods.commission_config = JSON.stringify({
...state.commission_config_temp,
});
let flag = true
if (commission_goods.self_rules == 1) {
for (var key1 in commission_goods.commission_rules) {
for (var key2 in commission_goods.commission_rules[key1]) {
for (var key3 in commission_goods.commission_rules[key1][key2]) {
if (key3 <= state.commission_config_temp.level) {
if ((commission_goods.commission_rules[key1][key2][key3].rate === '' || commission_goods.commission_rules[key1][key2][key3].rate < 0)
&& (commission_goods.commission_rules[key1][key2][key3].money === '' || commission_goods.commission_rules[key1][key2][key3].money < 0)) {
flag = false
}
}
}
}
}
}
if (commission_goods.self_rules == 2) {
for (var key1 in commission_goods.commission_rules) {
for (var key2 in commission_goods.commission_rules[key1]) {
if (key2 <= state.commission_config_temp.level) {
if (commission_goods.commission_rules[key1][key2].rate === '' || commission_goods.commission_rules[key1][key2].rate < 0) {
flag = false
}
}
}
}
}
if (!flag) {
ElMessage({
message: '请将数据填写完整',
type: 'warning',
})
return false
}
Fast.api.ajax({
url: `shopro/commission/goods/edit/id/${state.id}`,
type: 'POST',
data: JSON.parse(JSON.stringify(commission_goods))
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
onMounted(() => {
getLevelSelect()
})
return {
state,
onChangeSelfRules,
onChangeCommissionConfigStatus,
commissionPopover,
onConfirmCommissionPopover,
onCancelCommissionPopover,
onConfirm,
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,401 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
})
function getData() {
Fast.api.ajax({
url: 'shopro/commission/level',
type: 'GET',
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onAdd() {
Fast.api.open(`shopro/commission/level/add?type=add`, "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/commission/level/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/commission/level/delete/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData();
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onAdd,
onEdit,
onDelete,
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
level: null,
name: '',
image: '',
commission_rules: {
commission_1: '0.00',
commission_2: '0.00',
commission_3: '0.00',
},
upgrade_type: 0,
upgrade_rules: {},
},
rules: {
level: [{ required: true, message: '请选择等级权重', trigger: 'blur' }],
name: [{ required: true, message: '请输入等级名称', trigger: 'blur' }],
commission_rules: {
commission: [{ required: true, message: '佣金比例', trigger: 'blur' }],
},
upgrade_rules: [
{
validator: (rule, value, callback) => {
if (isEmpty(value)) {
callback(new Error('请填写升级条件'));
} else {
callback();
}
},
trigger: 'blur',
},
],
upgrade_rules_inner: {
rules: [{ required: true, message: '请输入', trigger: 'blur' }],
level: [{ required: true, message: '请选择分销商等级', trigger: 'blur' }],
},
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/commission/level/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
if (!isObject(form.model.upgrade_rules)) form.model.upgrade_rules = {};
// level=1时 等级权重不可修改
if (form.model.level == 1) {
level.data = [
{
name: '一级',
level: 1,
},
];
level.existLevel = [];
level.data.forEach((e) => {
level.existLevel.push(e.level);
});
} else {
level.data = JSON.parse(JSON.stringify(defaultLevel));
}
let index = level.existLevel.findIndex((l) => l == form.model.level);
level.existLevel.splice(index, 1);
return false
}, function (ret, res) { })
}
const defaultLevel = [
{
name: '一级',
level: 1,
},
{
name: '二级',
level: 2,
},
{
name: '三级',
level: 3,
},
{
name: '四级',
level: 4,
},
{
name: '五级',
level: 5,
},
{
name: '六级',
level: 6,
},
{
name: '七级',
level: 7,
},
{
name: '八级',
level: 8,
},
{
name: '九级',
level: 9,
},
{
name: '十级',
level: 10,
},
];
function onSelectLevel(l) {
if (!level.existLevel.includes(l)) {
form.model.level = l;
// 清空规则
form.model.upgrade_rules = {};
}
}
const level = reactive({
data: [],
select: [],
existLevel: [],
});
function getLevelSelect() {
Fast.api.ajax({
url: `shopro/commission/level/select`,
type: 'GET',
}, function (ret, res) {
level.select = res.data;
level.select.forEach((e) => {
level.existLevel.push(e.level);
});
return false
}, function (ret, res) { })
}
const upgradeCondition = {
user: {
total_consume: {
name: '用户消费金额',
},
child_user_count_1: {
name: '一级用户人数',
},
child_user_count_2: {
name: '二级用户人数',
},
child_user_count_all: {
name: '团队用户人数',
},
},
order_money: {
child_order_money_0: {
name: '自购分销订单总金额',
},
child_order_money_1: {
name: '一级分销订单金额',
},
child_order_money_2: {
name: '二级分销订单金额',
},
child_order_money_all: {
name: '团队分销订单金额',
},
},
order_count: {
child_order_count_0: {
name: '自购分销订单数量',
},
child_order_count_1: {
name: '一级分销订单数量',
},
child_order_count_2: {
name: '二级分销订单数量',
},
child_order_count_all: {
name: '团队分销订单数量',
},
},
agent_count: {
child_agent_count_1: {
name: '一级分销商人数',
},
child_agent_count_2: {
name: '二级分销商人数',
},
child_agent_count_all: {
name: '团队分销商人数',
},
},
agent_level: {
child_agent_level_all: {
name: '团队分销商等级统计',
},
child_agent_level_1: {
name: '一级分销商等级统计',
},
},
};
function onSelectUpgradeCondition(key) {
form.model.upgrade_rules[key] = '';
if (key == 'child_agent_level_all' || key == 'child_agent_level_1') {
form.model.upgrade_rules[key] = [
{
level: '',
count: '',
},
];
}
}
function onAddUpgradeRules(key) {
form.model.upgrade_rules[key].push({
level: '',
count: '',
});
}
function onDeleteRules(key, index) {
if (key == 'child_agent_level_all' || key == 'child_agent_level_1') {
form.model.upgrade_rules[key].splice(index, 1);
if (form.model.upgrade_rules[key].length == 0) delete form.model.upgrade_rules[key];
} else {
delete form.model.upgrade_rules[key];
}
}
function initUnit(key) {
if (key.includes('child_user_count') || key.includes('child_agent_count')) {
return '人';
}
if (key.includes('total_consume') || key.includes('child_order_money')) {
return '元';
}
if (key.includes('child_order_count')) {
return '单';
}
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/commission/level/add' : `shopro/commission/level/edit/id/${state.id}`,
type: 'POST',
data: JSON.parse(JSON.stringify(form.model))
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
getLevelSelect()
if (state.type == 'add') {
level.data = JSON.parse(JSON.stringify(defaultLevel));
} else if (state.type == 'edit') {
getDetail()
}
})
return {
state,
form,
onSelectLevel,
defaultLevel,
level,
getLevelSelect,
upgradeCondition,
onSelectUpgradeCondition,
onAddUpgradeRules,
onDeleteRules,
initUnit,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { reactive, onMounted } = Vue
const select = {
setup() {
const state = reactive({
level: new URLSearchParams(location.search).get('level'),
data: [],
})
function getData() {
Fast.api.ajax({
url: 'shopro/commission/level/select',
type: 'GET',
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onSelect(level) {
state.level = level;
}
function onConfirm() {
Fast.api.close(state.level)
}
onMounted(() => {
getData()
})
return {
state,
getData,
onSelect,
onConfirm,
}
}
}
createApp('select', select);
},
};
return Controller;
});

View File

@@ -0,0 +1,109 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
event: '',
},
tools: {
event: {
type: 'tselect',
label: '动态类型',
value: '',
options: {
data: [{
label: '分销商',
value: 'agent',
},
{
label: '佣金',
value: 'reward',
},
{
label: '推荐',
value: 'share',
},
{
label: '绑定',
value: 'bind',
}],
},
},
},
condition: {},
},
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch);
Fast.api.ajax({
url: 'shopro/commission/log',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const really = reactive({
reallyStatus: 0,
reallyTimer: '',
})
function onChangeReallyStatus(val) {
clearInterval(really.reallyTimer);
if (val == 1) {
really.reallyTimer = setInterval(() => {
getData();
}, 3000);
}
}
onMounted(() => {
getData()
})
return {
state,
getData,
onOpenFilter,
onChangeFilter,
pagination,
really,
onChangeReallyStatus
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,405 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted, ref } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
buyer: { field: 'buyer_id', value: '' },
agent: { field: 'agent_id', value: '' },
reward: { field: 'reward.agent_id', value: '' },
'order.order_sn': '',
'order_item.goods_title': '',
'order.createtime': [],
commission_time: [],
commission_order_status: '',
commission_reward_status: '',
},
tools: {
buyer: {
type: 'tinputprepend',
label: '下单用户',
placeholder: '请输入查询内容',
value: {
field: 'buyer_id',
value: '',
},
options: {
data: [{
label: '用户ID',
value: 'buyer_id',
},
{
label: '用户昵称',
value: 'buyer.nickname',
},
{
label: '用户手机号',
value: 'buyer.mobile',
}],
}
},
agent: {
type: 'tinputprepend',
label: '推广分销商',
placeholder: '请输入查询内容',
value: {
field: 'agent_id',
value: '',
},
options: {
data: [{
label: '推广ID',
value: 'agent_id',
},
{
label: '推广昵称',
value: 'agent.nickname',
},
{
label: '推广手机号',
value: 'agent.mobile',
}],
}
},
reward: {
type: 'tinputprepend',
label: '结算分销商',
placeholder: '请输入查询内容',
value: {
field: 'reward.agent_id',
value: '',
},
options: {
data: [{
label: '结算ID',
value: 'reward.agent_id',
},
{
label: '结算昵称',
value: 'reward.agent_nickname',
},
{
label: '结算手机号',
value: 'reward.agent_mobile',
}],
}
},
'order.order_sn': {
type: 'tinput',
label: '订单号',
placeholder: '请输入查询内容',
value: '',
},
'order_item.goods_title': {
type: 'tinput',
label: '商品名称',
placeholder: '请输入查询内容',
value: '',
},
'order.createtime': {
type: 'tdatetimerange',
label: '下单时间',
value: [],
},
commission_time: {
type: 'tdatetimerange',
label: '分佣时间',
value: [],
},
commission_order_status: {
type: 'tselect',
label: '订单结算状态',
value: '',
options: {
data: [{
label: '已扣除',
value: '-2',
},
{
label: '已取消',
value: '-1',
},
{
label: '不计入',
value: '0',
},
{
label: '已计入',
value: '1',
}],
},
},
commission_reward_status: {
type: 'tselect',
label: '佣金结算状态',
value: '',
options: {
data: [{
label: '已退回',
value: '-2',
},
{
label: '已取消',
value: '-1',
},
{
label: '未结算',
value: '0',
},
{
label: '已结算',
value: '1',
}],
},
},
},
condition: {},
},
count: {},
statusStyle: {
'-2': 'danger',
'-1': 'warning',
0: 'info',
1: 'success',
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'buyer.nickname': 'like',
'buyer.mobile': 'like',
'agent.nickname': 'like',
'agent.mobile': 'like',
'reward.agent_nickname': 'like',
'reward.agent_mobile': 'like',
'order.order_sn': 'like',
'order_item.goods_title': 'like',
'order.createtime': 'range',
commission_time: 'range',
});
Fast.api.ajax({
url: 'shopro/commission/order',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.count = res.data.count;
state.data = res.data.list.data
pagination.total = res.data.list.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const arraySpanMethod = ({ row, column, rowIndex, columnIndex }) => {
if (columnIndex == 1) {
return [1, 6];
} else if (
columnIndex == 3 ||
columnIndex == 4 ||
columnIndex == 5 ||
columnIndex == 6 ||
columnIndex == 7
) {
return [0, 0];
}
};
function countRewards(row) {
let commission = 0;
let commissioned = 0;
row.forEach((r) => {
if (r.status == 1) {
commissioned += Number(r.commission);
}
commission += Number(r.commission);
});
return `${commission.toFixed(2)}元/${commissioned.toFixed(2)}`;
}
const rewardsPopover = reactive({
flag: {},
commission: '',
});
function onConfirmRewardsPopover(index, id) {
Fast.api.ajax({
url: 'shopro/commission/order/edit',
type: 'POST',
data: {
commission_reward_id: id,
commission: rewardsPopover.commission,
},
}, function (ret, res) {
onCancelRewardsPopover(index)
getData()
}, function (ret, res) { })
}
function onCancelRewardsPopover(index) {
rewardsPopover.flag[index] = false;
rewardsPopover.commission = '';
}
const commissionPopover = reactive({
flag: {},
type: null,
isDelete: '1',
});
function onConfirmCommissionPopover(index, id) {
let params = { commission_order_id: id };
if (commissionPopover.type == 'confirm') {
onConfirm(params);
}
if (commissionPopover.type == 'cancel') {
params = { ...params, deduct_order_money: commissionPopover.isDelete };
onCancel(params);
}
if (commissionPopover.type == 'back') {
params = { ...params, deduct_order_money: commissionPopover.isDelete };
onBack(params);
}
onCancelCommissionPopover(index);
}
function onCancelCommissionPopover(index) {
commissionPopover.flag[index] = false;
commissionPopover.isDelete = '1';
}
function onConfirm(data) {
Fast.api.ajax({
url: 'shopro/commission/order/confirm',
type: 'POST',
data: data,
}, function (ret, res) {
getData();
}, function (ret, res) { })
}
function onCancel(data) {
Fast.api.ajax({
url: 'shopro/commission/order/cancel',
type: 'POST',
data: data,
}, function (ret, res) {
getData();
}, function (ret, res) { })
}
function onBack(data) {
Fast.api.ajax({
url: 'shopro/commission/order/back',
type: 'POST',
data: data,
}, function (ret, res) {
getData();
}, function (ret, res) { })
}
function onOpenGoodsDetail(id) {
Fast.api.open(`shopro/goods/goods/add?type=edit&id=${id}`, "商品详情", {
callback() {
getData()
}
})
}
function onOpenOrderDetail(id) {
Fast.api.open(`shopro/order/order/detail?id=${id}`, "订单详情", {
callback() {
getData()
}
})
}
const exportLoading = ref(false);
function onExport(type) {
exportLoading.value = true;
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'buyer.nickname': 'like',
'buyer.mobile': 'like',
'agent.nickname': 'like',
'agent.mobile': 'like',
'reward.agent_nickname': 'like',
'reward.agent_mobile': 'like',
'order.order_sn': 'like',
'order_item.goods_title': 'like',
'order.createtime': 'range',
commission_time: 'range',
});
if (Config.save_type == 'download') {
window.location.href = `${Config.moduleurl}/shopro/commission/order/${type}?page=${pagination.page}&list_rows=${pagination.list_rows}&search=${search.search}`;
exportLoading.value = false;
} else if (Config.save_type == 'save') {
Fast.api.ajax({
url: `shopro/commission/order/${type}`,
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
exportLoading.value = false;
}, function (ret, res) { })
}
}
onMounted(() => {
getData()
})
return {
onClipboard,
state,
getData,
onOpenFilter,
onChangeFilter,
pagination,
arraySpanMethod,
countRewards,
rewardsPopover,
onConfirmRewardsPopover,
onCancelRewardsPopover,
commissionPopover,
onConfirmCommissionPopover,
onCancelCommissionPopover,
onConfirm,
onCancel,
onBack,
onOpenGoodsDetail,
onOpenOrderDetail,
exportLoading,
onExport,
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,201 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted, ref } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
buyer: { field: 'buyer_id', value: '' },
agent: { field: 'agent_id', value: '' },
'order.order_sn': '',
commission_time: [],
status: '',
},
tools: {
buyer: {
type: 'tinputprepend',
label: '下单用户',
placeholder: '请输入查询内容',
value: {
field: 'buyer_id',
value: '',
},
options: {
data: [{
label: '用户ID',
value: 'buyer_id',
},
{
label: '用户昵称',
value: 'buyer.nickname',
},
{
label: '用户手机号',
value: 'buyer.mobile',
}],
}
},
agent: {
type: 'tinputprepend',
label: '结算分销商',
placeholder: '请输入查询内容',
value: {
field: 'agent_id',
value: '',
},
options: {
data: [{
label: '结算ID',
value: 'agent_id',
},
{
label: '结算昵称',
value: 'agent.nickname',
},
{
label: '结算手机号',
value: 'agent.mobile',
}],
}
},
'order.order_sn': {
type: 'tinput',
label: '订单号',
placeholder: '请输入查询内容',
value: '',
},
commission_time: {
type: 'tdatetimerange',
label: '分佣时间',
value: [],
},
status: {
type: 'tselect',
label: '入账状态',
value: '',
options: {
data: [{
label: '已退回',
value: '-2',
},
{
label: '已取消',
value: '-1',
},
{
label: '未结算',
value: '0',
},
{
label: '已结算',
value: '1',
}],
},
},
},
condition: {},
},
statusStyle: {
'-2': 'danger',
'-1': 'warning',
0: 'info',
1: 'success',
},
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'buyer.nickname': 'like',
'buyer.mobile': 'like',
'agent.nickname': 'like',
'agent.mobile': 'like',
'order.order_sn': 'like',
commission_time: 'range',
});
Fast.api.ajax({
url: 'shopro/commission/reward',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const exportLoading = ref(false);
function onExport(type) {
exportLoading.value = true;
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'buyer.nickname': 'like',
'buyer.mobile': 'like',
'agent.nickname': 'like',
'agent.mobile': 'like',
'order.order_sn': 'like',
commission_time: 'range',
});
if (Config.save_type == 'download') {
window.location.href = `${Config.moduleurl}/shopro/commission/reward/${type}?page=${pagination.page}&list_rows=${pagination.list_rows}&search=${search.search}`;
exportLoading.value = false;
} else if (Config.save_type == 'save') {
Fast.api.ajax({
url: `shopro/commission/reward/${type}`,
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
exportLoading.value = false;
}, function (ret, res) { })
}
}
onMounted(() => {
getData()
})
return {
state,
getData,
onOpenFilter,
onChangeFilter,
pagination,
exportLoading,
onExport,
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,645 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const index = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
data: [],
tabActive: null,
configis_upgrade: false,
})
const type = reactive({
data: {
api: Config.configList.filter((item) => {
if (item.status) return item;
})
}
})
const form = reactive({
model: {},
rules: {
rechargewithdraw: {
recharge: {
quick_amounts: {
money: [{ required: true, message: '请输入金额', trigger: 'blur' }],
gift: [{ required: true, message: '请输入内容', trigger: 'blur' }],
}
}
},
commission: {
agent_form: {
background_image: [{ required: true, message: '请选择表单背景图', trigger: 'blur' }],
content: {
type: [{ required: true, message: '表单类型', trigger: 'change' }],
name: [{ required: true, message: '表单名称', trigger: 'blur' }],
},
},
}
},
})
function getData() {
if (!state.tabActive) return;
if (state.tabActive == 'shopro/config/platform') {
getPlatformStatus()
} else if (state.tabActive == 'shopro/pay_config') {
getPayConfig()
} else {
Fast.api.ajax({
url: state.tabActive,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
// 用户配置
if (state.tabActive == 'shopro/config/user') {
getGroupSelect()
}
if (state.tabActive == 'shopro/config/dispatch') {
form.model.sender.area_arr = []
form.model.sender.area_arr.push(form.model.sender.province_name)
form.model.sender.area_arr.push(form.model.sender.city_name)
form.model.sender.area_arr.push(form.model.sender.district_name)
express.form.model = form.model.kdniao.express
getExpressSelect()
getAreaSelect()
}
if (state.tabActive == 'shopro/config/commission') {
if (form.model.become_agent.type == 'goods') {
getGoodsList(form.model.become_agent.value);
}
if (!Config.is_pro) {
state.configis_upgrade = true
}
}
if (state.tabActive == 'shopro/config/chat') {
getChatConfig()
}
return false
}, function (ret, res) { })
}
}
// 基础配置
function onSelectRichtext(type) {
Fast.api.open(`shopro/data/richtext/select`, '选择富文本', {
callback(data) {
form.model[type].id = data.id;
form.model[type].title = data.title;
}
})
}
// 用户配置
const group = reactive({
select: []
})
function getGroupSelect() {
Fast.api.ajax({
url: 'shopro/user/group/select',
type: 'GET',
}, function (ret, res) {
group.select = res.data
return false
}, function (ret, res) { })
}
// 平台配置
const platform = reactive({
data: [{
value: 'H5',
label: 'H5',
color: '#fc800e',
},
{
value: 'WechatOfficialAccount',
label: '微信公众号',
color: '#07c160',
},
{
value: 'WechatMiniProgram',
label: '微信小程序',
color: '#6f74e9',
},
{
value: 'App',
label: 'App',
color: '#806af6',
}],
status: {},
})
function getPlatformStatus() {
Fast.api.ajax({
url: 'shopro/config/platformStatus',
type: 'GET',
}, function (ret, res) {
platform.status = res.data
return false
}, function (ret, res) { })
}
function onEditPlatform(item) {
Fast.api.open(`shopro/config/platform/platform/${item.value}?platform=${item.value}&label=${item.label}`, `平台-${item.label}`, {
callback() {
getData()
}
})
}
// 物流配置
const area = reactive({
select: []
})
function getAreaSelect() {
Fast.api.ajax({
url: 'shopro/data/area/select',
type: 'GET',
}, function (ret, res) {
area.select = res.data;
return false
}, function (ret, res) { })
}
const express = reactive({
form: {
model: {}
},
})
const deliverCompany = reactive({
loading: false,
select: [],
pagination: {
page: 1,
list_rows: 10,
total: 0,
}
})
function getExpressSelect(keyword) {
let search = {};
if (keyword) {
search = { keyword: keyword };
}
Fast.api.ajax({
url: 'shopro/data/express',
type: 'GET',
data: {
page: deliverCompany.pagination.page,
list_rows: deliverCompany.pagination.list_rows,
search: JSON.stringify(search),
}
}, function (ret, res) {
deliverCompany.select = res.data.data
deliverCompany.pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeExpressCode(code) {
express.form.model = {}
express.form.model.code = code
express.form.model.name = proxy.$refs[`express-${code}`][0].label;
}
function remoteMethod(keyword) {
deliverCompany.loading = true;
setTimeout(() => {
deliverCompany.loading = false;
getExpressSelect(keyword);
}, 200);
}
function onThinkApi() {
window.open('https://docs.topthink.com/think-api/1835396');
}
// 充值提现
function onAddTemplate() {
form.model.recharge.quick_amounts.push({
money: '',
gift: '',
});
}
function onDeleteTemplate(index) {
form.model.recharge.quick_amounts.splice(index, 1);
}
// 分销配置
function onChangeBecomeAgentType(type) {
if (type === 'user') {
form.model.invite_lock = 'share';
}
if (type === 'apply') {
form.model.agent_form.status = '1';
}
if (type === 'goods') {
tempGoods.list = [];
}
form.model.become_agent.value = '';
}
const tempGoods = reactive({
list: [],
});
async function getGoodsList(ids) {
Fast.api.ajax({
url: 'shopro/goods/goods/select',
type: 'GET',
data: {
type: 'select',
search: JSON.stringify({ id: [ids, 'in'] }),
},
}, function (ret, res) {
tempGoods.list = res.data;
return false
}, function (ret, res) { })
}
function onSelectGoods() {
let ids = [];
tempGoods.list.forEach((i) => {
ids.push(i.id);
});
Fast.api.open(`shopro/goods/goods/select?multiple=true&ids=${ids.join(',')}`, "选择商品", {
callback(data) {
tempGoods.list = data;
let ids = [];
tempGoods.list.forEach((item) => {
ids.push(item.id);
});
form.model.become_agent.value = ids.join(',');
}
})
}
function onDeleteGoods(index) {
tempGoods.list.splice(index, 1);
let ids = [];
tempGoods.list.forEach((gl) => {
ids.push(gl.id);
});
form.model.become_agent.value = ids.join(',');
}
const become_register_options = [
{
value: 'text',
label: '文本内容',
},
{
value: 'number',
label: '纯数字',
},
{
value: 'image',
label: '上传图片',
},
];
function onAddContent() {
form.model.agent_form.content.push({
type: '',
name: '',
});
}
function onDeleteContent(index) {
form.model.agent_form.content.splice(index, 1);
}
// 支付配置
const payConfig = reactive({
data: []
})
function getPayConfig() {
Fast.api.ajax({
url: 'shopro/pay_config',
type: 'GET',
}, function (ret, res) {
payConfig.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onCommandPayConfig(item) {
Fast.api.ajax({
url: `shopro/pay_config/edit/id/${item.id}`,
type: 'POST',
data: {
status: item.type
}
}, function (ret, res) {
getPayConfig()
}, function (ret, res) { })
}
function onAddPayConfig() {
Fast.api.open('shopro/pay_config/add?type=add', "添加", {
callback() {
getPayConfig()
}
})
}
function onEditPayConfig(id) {
Fast.api.open(`shopro/pay_config/edit?type=edit&id=${id}`, "编辑", {
callback() {
getPayConfig()
}
})
}
function onDeletePayConfig(id) {
Fast.api.ajax({
url: `shopro/pay_config/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getPayConfig()
}, function (ret, res) { })
}
function onRecyclebinPayConfig() {
Fast.api.open(`shopro/pay_config/recyclebin`, "回收站", {
callback() {
getPayConfig()
}
})
}
// 客服配置
const chat = reactive({
config: {}
})
function getChatConfig() {
Fast.api.ajax({
url: `shopro/chat/index/init`,
type: 'GET',
}, function (ret, res) {
chat.config = res.data
return false
}, function (ret, res) { })
}
function onConfirm() {
const submitForm = JSON.parse(JSON.stringify(form.model))
if (state.tabActive == 'shopro/config/dispatch') {
if (submitForm.sender.area_arr) {
submitForm.sender.province_name = submitForm.sender.area_arr[0]
submitForm.sender.city_name = submitForm.sender.area_arr[1]
submitForm.sender.district_name = submitForm.sender.area_arr[2]
delete submitForm.sender.area_arr
} else {
submitForm.sender.province_name = ''
submitForm.sender.city_name = ''
submitForm.sender.district_name = ''
}
submitForm.kdniao.express = express.form.model
}
if (state.tabActive == 'shopro/config/redis') {
if (submitForm.empty_password) {
delete submitForm.password
}
}
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.tabActive,
type: 'POST',
data: submitForm,
}, function (ret, res) {
}, function (ret, res) { })
}
});
}
function onOper(type) {
switch (type) {
case 'close':
state.configis_upgrade = false
break;
case 'refresh':
window.location.reload();
break;
case 'upgrade':
window.open("https://www.fastadmin.net/store/shopro.html")
break;
}
}
onMounted(() => {
state.tabActive = type.data.api.length ? type.data.api[0].name : null;
getData()
})
return {
onClipboard,
state,
type,
form,
getData,
onSelectRichtext,
group,
platform,
onEditPlatform,
area,
express,
deliverCompany,
getExpressSelect,
onChangeExpressCode,
remoteMethod,
onThinkApi,
onAddTemplate,
onDeleteTemplate,
onChangeBecomeAgentType,
tempGoods,
onSelectGoods,
onDeleteGoods,
become_register_options,
onAddContent,
onDeleteContent,
payConfig,
pagination,
onCommandPayConfig,
onAddPayConfig,
onEditPayConfig,
onDeletePayConfig,
onRecyclebinPayConfig,
chat,
onConfirm,
onOper
}
}
}
createApp('index', index);
},
platform: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const platform = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
platform: new URLSearchParams(location.search).get('platform'),
label: new URLSearchParams(location.search).get('label'),
})
const form = reactive({
model: {
app_id: '',
secret: '',
status: '',
payment: {
alipay: '',
wechat: '',
methods: [],
},
share: {
methods: [],
forwardInfo: {
title: '',
subtitle: '',
image: '',
},
linkAddress: '',
posterInfo: {
user_bg: '',
goods_bg: '',
groupon_bg: '',
},
},
download: {
android: '',
ios: '',
local: '',
},
},
rules: {}
})
function getDetail() {
Fast.api.ajax({
url: `shopro/config/platform/platform/${state.platform}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
if (isEmpty(form.model.share)) {
form.model.share = {
methods: [],
forwardInfo: {
title: '',
subtitle: '',
image: '',
},
linkAddress: '',
posterInfo: {
user_bg: '',
goods_bg: '',
groupon_bg: '',
},
};
}
if (isEmpty(form.model.download)) {
form.model.download = {
android: '',
ios: '',
local: '',
};
}
if (state.platform != 'H5' && !form.model.share.methods.includes('forward')) {
form.model.share.methods.push('forward');
}
if (form.model.payment.wechat === 0) {
form.model.payment.wechat = ''
}
if (form.model.payment.alipay === 0) {
form.model.payment.alipay = ''
}
return false
}, function (ret, res) { })
}
function onConfiguration() {
if (state.platform == 'H5') {
window.open('https://pay.weixin.qq.com/wiki/doc/apiv3/open/pay/chapter2_6_1.shtml');
}
if (state.platform == 'App') {
window.open('https://open.weixin.qq.com/');
}
}
const payConfig = reactive({
select: {
alipay: [],
wechat: [],
}
})
function getPayConfigSelect() {
Fast.api.ajax({
url: 'shopro/pay_config/select',
type: 'GET',
}, function (ret, res) {
payConfig.select.alipay = []
payConfig.select.wechat = []
res.data.forEach(item => {
if (item.type == 'alipay') {
payConfig.select.alipay.push(item)
}
if (item.type == 'wechat') {
payConfig.select.wechat.push(item)
}
})
return false
}, function (ret, res) { })
}
function onAddPayConfig() {
Fast.api.open('shopro/pay_config/add?type=add', "添加", {
callback() {
getPayConfigSelect()
}
})
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/config/platform/platform/${state.platform}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
getPayConfigSelect()
getDetail()
})
return {
state,
form,
onConfiguration,
payConfig,
onAddPayConfig,
onConfirm,
}
}
}
createApp('platform', platform);
},
};
return Controller;
});

View File

@@ -0,0 +1,556 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
keyword: '',
type: '',
use_scope: '',
},
tools: {
keyword: {
type: 'tinput',
label: '查询内容',
placeholder: '请输入查询内容',
value: '',
},
type: {
type: 'tselect',
label: '类型',
value: '',
options: {
data: [{
label: '满减券',
value: 'reduce',
},
{
label: '折扣券',
value: 'discount',
}],
},
},
use_scope: {
type: 'tselect',
label: '可用范围',
value: '',
options: {
data: [{
label: '全场通用',
value: 'all_use',
},
{
label: '指定商品可用',
value: 'goods',
},
{
label: '指定商品不可用',
value: 'disabled_goods',
},
{
label: '指定分类可用',
value: 'category',
}],
},
},
},
condition: {},
},
dashboard: {
total_num: {
name: '总发券量/张',
num: '',
tip: '用户领取的优惠券的总张数,包含已经被后台删除的优惠券'
},
expire_num: {
name: '已过期/张',
num: '',
tip: '用户已领取的并且已经超过可使用日期的未使用优惠券'
},
use_num: {
name: '已使用/张',
num: '',
tip: '用户已领取并且已使用的优惠券',
},
use_percent: {
name: '使用率',
num: '',
tip: '用户已使用优惠和总发券量的比例'
},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
keyword: 'like',
});
Fast.api.ajax({
url: 'shopro/coupon',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.coupons.data
pagination.total = res.data.coupons.total
for (var key in state.dashboard) {
state.dashboard[key].num = res.data[key]
}
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
async function onCommand(item) {
Fast.api.ajax({
url: `shopro/coupon/edit/id/${item.id}`,
type: 'POST',
data: {
status: item.type
},
}, function (ret, res) {
getData();
}, function (ret, res) { })
}
function onAdd() {
Fast.api.open(`shopro/coupon/add?type=add`, "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/coupon/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/coupon/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onRecyclebin() {
Fast.api.open(`shopro/coupon/recyclebin`, "回收站", {
callback() {
getData()
}
})
}
function onCoupon(id) {
Fast.api.addtabs(`shopro/user/coupon?coupon_id=${id}`, '领取记录')
}
function onSend(id) {
Fast.api.open(`shopro/user/user/select?id=${id}`, '选择用户', {
callback() {
getData()
}
})
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
onCommand,
onAdd,
onEdit,
onDelete,
onRecyclebin,
onCoupon,
onSend,
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const { ElMessage } = ElementPlus
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
})
const form = reactive({
model: {
name: '',
type: 'reduce', // 优惠券类型:reduce=满减券,discount=折扣券
use_scope: 'all_use', // 可用范围:all=全场通用,goods=指定商品可用,disabled_goods=指定商品不可用,category=指定分类可用
items: '',
items_value: [],
amount: '',
max_amount: '',
enough: '',
stock: '',
limit_num: '',
get_time: '',
use_time_type: 'days',
use_time: '',
start_days: '',
days: '',
is_double_discount: '',
description: '',
status: 'normal', // 状态:normal=公开,hidden=后台发放,disabled=禁用
},
rules: {
name: [{ required: true, message: '请输入券名称', trigger: 'blur' }],
type: [{ required: true, message: '请选择券类型', trigger: 'blur' }],
enough: [{ required: true, message: '请输入消费门槛', trigger: 'blur' }],
amount: [{ required: true, message: '请输入使用面额', trigger: 'blur' }],
max_amount: [{ required: true, message: '请输入最大优惠', trigger: 'blur' }],
stock: [{ required: true, message: '请输入发券总量', trigger: 'blur' }],
get_time: [{ required: true, message: '请选择优惠券发放时间', trigger: 'blur' }],
use_time: [{ required: true, message: '请选择优惠券可使用时间', trigger: 'blur' }],
use_time_type: [{ required: true, message: '请选择优惠券使用时间类型', trigger: 'blur' }],
days: [{ required: true, message: '请输入优惠券有效天数', trigger: 'blur' }],
use_scope: [{ required: true, message: '请选择可用范围', trigger: 'blur' }],
},
});
function getDetail() {
Fast.api.ajax({
url: `shopro/coupon/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
form.model.get_time = [form.model.get_start_time, form.model.get_end_time];
if (form.model.use_time_type == 'days') {
form.model.use_time = '';
} else if (form.model.use_time_type == 'range') {
form.model.use_time = [form.model.use_start_time, form.model.use_end_time];
}
return false
}, function (ret, res) { })
}
function onSelectGoods() {
let ids = [];
form.model.items_value.forEach((i) => {
ids.push(i.id);
});
Fast.api.open(`shopro/goods/goods/select?multiple=true&ids=${ids.join(',')}`, "选择商品", {
callback(data) {
form.model.items_value = data;
}
})
}
function onDeleteGoods(index) {
form.model.items_value.splice(index, 1);
}
function onSelectCategory() {
let ids = [];
form.model.items_value.forEach((i) => {
ids.push(i.id);
});
Fast.api.open(`shopro/category/select?from=coupon&multiple=true`, "选择分类", {
callback(data) {
form.model.items_value = data.data;
}
})
}
function onDeleteCategory(index) {
form.model.items_value.splice(index, 1);
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
let submitForm = JSON.parse(JSON.stringify(form.model));
if (Number(submitForm.enough) < Number(submitForm.amount)) {
ElMessage({
message: '请输入正确的使用门槛',
type: 'warning',
});
return;
}
if (
submitForm.use_scope == 'goods' ||
submitForm.use_scope == 'disabled_goods' ||
submitForm.use_scope == 'category'
) {
let ids = [];
submitForm.items_value.forEach((i) => {
ids.push(i.id);
});
submitForm.items = ids.join(',');
} else if (submitForm.use_scope == 'all_use') {
submitForm.items = '';
}
delete submitForm.items_value;
if (!isEmpty(submitForm.use_time)) {
submitForm.use_time = submitForm.use_time.join(' - ');
}
if (!isEmpty(submitForm.get_time)) {
submitForm.get_time = submitForm.get_time.join(' - ');
}
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/coupon/add' : `shopro/coupon/edit/id/${state.id}`,
type: 'POST',
data: submitForm
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onSelectGoods,
onDeleteGoods,
onSelectCategory,
onDeleteCategory,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { reactive, onMounted } = Vue
const select = {
setup() {
const state = reactive({
multiple: new URLSearchParams(location.search).get('multiple') || false,
status: new URLSearchParams(location.search).get('status'),
data: [],
selected: [],
})
function getData() {
let tempSearch = {
status: state.status
};
let search = composeFilter(tempSearch);
Fast.api.ajax({
url: 'shopro/coupon/select',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onSelect(item) {
Fast.api.close(item)
}
function onChangeSelection(val) {
state.selected = val
}
function onConfirm() {
Fast.api.close(state.selected)
}
onMounted(() => {
getData()
})
return {
state,
getData,
pagination,
onSelect,
onChangeSelection,
onConfirm,
}
}
}
createApp('select', select);
},
recyclebin: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const recyclebin = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/coupon/recyclebin',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'restore':
onRestore(ids.join(','))
break;
case 'destroy':
ElMessageBox.confirm('此操作将销毁, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy(ids.join(','))
});
break;
case 'all':
ElMessageBox.confirm('此操作将清空回收站, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy('all')
});
break;
}
}
function onRestore(id) {
Fast.api.ajax({
url: `shopro/coupon/restore/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onDestroy(id) {
Fast.api.ajax({
url: `shopro/coupon/destroy/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onRestore,
onDestroy,
}
}
}
createApp('recyclebin', recyclebin);
},
};
return Controller;
});

View File

@@ -0,0 +1,552 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form', 'moment'], function ($, undefined, Backend, Table, Form, Moment) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
total: {
user: {
data: {},
color: '#806AF6',
color1: 'rgba(128, 106, 246, 0.4)',
color2: 'rgba(128, 106, 246, 0)',
title: '用户数量',
tip: '今日新增用户',
footer: '本周新增用户人数',
},
agent: {
data: {},
color: '#409EFF',
color1: 'rgba(64, 158, 255, 0.4)',
color2: ' rgba(64, 158, 255, 0)',
title: '分销商数量',
tip: '今日新增人数',
footer: '本周新增分销商人数',
},
share: {
data: {},
color: '#21C732',
color1: 'rgba(33, 199, 50, 0.4)',
color2: 'rgba(33, 199, 50, 0)',
title: '分享次数',
tip: '今日分享次数',
footer: '本周新增分享次数',
},
},
})
function getTotal() {
Fast.api.ajax({
url: 'shopro/dashboard/total',
type: 'GET',
}, function (ret, res) {
state.total.agent.data = res.data.agent_data;
state.total.share.data = res.data.share_data;
state.total.user.data = res.data.user_data;
for (var key in state.total) {
if (state.total[key].data) {
initChartTotal(key)
}
}
return false
}, function (ret, res) { })
}
function initChartTotal(key) {
var myChart = echarts.init(document.getElementById(`${key}Total`));
window.onresize = () => {
myChart.resize()
}
var option = {
grid: {
left: 6,
top: 6,
right: 6,
bottom: 6,
},
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'none',
},
},
xAxis: {
type: 'category',
data: ['分', 20, 36, 10, 10, 20],
boundaryGap: false,
axisTick: {
show: false,
},
axisLabel: {
show: false,
},
axisLine: {
show: false,
},
},
yAxis: {
type: 'value',
splitLine: {
show: false,
},
axisLabel: {
show: false,
},
},
series: [{
// name: state.total.user.title,
data: [5, 20, 36, 10, 10, 20], // [5, 20, 36, 10, 10, 20]
type: 'line',
smooth: true,
showSymbol: false,
symbol: 'circle',
symbolSize: 6,
itemStyle: {
color: state.total[key].color,
},
areaStyle: {
color: new echarts.graphic.LinearGradient(
0,
0,
0,
1,
[
{
offset: 0,
color: state.total[key].color1,
},
{
offset: 1,
color: state.total[key].color2,
},
],
false,
),
},
lineStyle: {
width: 2,
},
}]
};
initIntervalTotal(24, 'hours', option, key)
myChart.setOption(option);
}
function initIntervalTotal(interval, kld, option, key) {
let dateTime = `${Moment().format('YYYY-MM-DD')} 00:00:00`;
let x = [];
let y = [];
let timeStamp = [];
for (let i = 0; i <= interval; i++) {
x.push(Moment(dateTime).add(i, kld).format('HH:mm'));
y.push(0);
timeStamp.push(Moment(dateTime).add(i, kld).valueOf());
}
x.forEach((item, index) => {
state.total[key].data.array.forEach((item) => {
if (
timeStamp[index + 1] &&
item.createtime_unix > timeStamp[index] &&
item.createtime_unix <= timeStamp[index + 1]
) {
y[index]++;
}
});
});
option.xAxis.data = x;
option.series[0].data = y;
}
const chart = reactive({
tabsData: {
order: '订单数',
payOrder: '支付订单',
payAmount: '支付金额',
},
tabActive: 'order',
dateTime: getTimeSlot(),
shortcuts: [
{
text: '今天',
value: getTimeSlot(),
},
{
text: '昨天',
value: () => {
return getTimeSlot('yesterday');
},
},
{
text: '近一周',
value: () => {
return getTimeSlot('week');
},
},
],
data: {
payAmountArr: [], // 销售额
payOrderArr: [], // 订单
orderArr: [], //订单数
},
});
function onChangeTabActive(type) {
chart.tabActive = type;
chartOption.series[0].name = chart.tabsData[chart.tabActive];
initChart();
}
function onChangeDateTime(e) {
// 时间date必选
e && getChart();
}
const statistics = reactive({
order: {
num: 0,
text: '订单数',
path: '',
tip: '时间区间内总的下单数量(包含未支付订单)',
status: 'all',
},
payAmount: {
num: 0,
text: '支付金额',
path: '',
tip: '时间区间内支付订单的支付总金额(包含退款订单)',
status: 'paid',
},
payOrder: {
num: 0,
text: '支付订单',
path: '',
tip: '时间区间内支付的订单数量(包含退款订单)',
status: 'paid',
},
noSend: {
num: 0,
text: '待发货订单',
path: '',
tip: '时间区间内待发货订单数量',
status: 'nosend',
},
aftersale: {
num: 0,
text: '售后维权',
path: '',
tip: '时间区间内申请售后维权的订单数量',
status: 'aftersale',
},
refund: {
num: 0,
text: '退款订单',
path: '',
tip: '时间区间内退款的订单数量',
status: 'refund',
},
});
async function getChart() {
Fast.api.ajax({
url: 'shopro/dashboard/chart',
type: 'GET',
data: {
date: chart.dateTime.join(' - '),
}
}, function (ret, res) {
for (let key in statistics) {
statistics[key].num = res.data[`${key}Num`];
}
chart.data.payAmountArr = res.data.payAmountArr; // 销售额
chart.data.payOrderArr = res.data.payOrderArr; // 订单
chart.data.orderArr = res.data.orderArr; //订单数
initChart();
return false
}, function (ret, res) { })
}
// 柱状图参数
const chartOption = reactive({
grid: {
left: '10px',
top: '20px',
bottom: '20px',
right: '20px',
containLabel: true,
},
xAxis: {
type: 'category',
data: [],
offset: 5,
axisLine: {
show: false,
},
axisTick: {
show: false,
},
},
yAxis: {
type: 'value',
offset: 5,
splitLine: {
show: false,
},
axisTick: {
show: false,
},
axisLine: {
show: false,
},
},
tooltip: {
trigger: 'axis',
axisPointer: {
show: true,
status: 'shadow',
z: -1,
shadowStyle: {
color: 'rgba(191, 191, 191, 0.24)',
},
type: 'shadow',
},
},
series: [
{
name: chart.tabsData[chart.tabActive],
type: 'bar',
data: [],
zlevel: 1,
z: 1,
label: {
show: false,
position: 'top',
},
itemStyle: {
color: '#806af6',
},
showBackground: true,
backgroundStyle: {
color: 'rgba(191, 191, 191, 0.24)',
},
},
],
});
// 获取时间刻度
function initChart() {
if (chart.dateTime) {
let time =
(new Date(chart.dateTime[1].replace(/-/g, '/')).getTime() -
new Date(chart.dateTime[0].replace(/-/g, '/')).getTime()) /
1000 +
1;
let kld = '';
let interval = 0;
if (time <= 60 * 60) {
interval = parseInt(time / 60);
kld = 'minutes';
} else if (time <= 60 * 60 * 24) {
interval = parseInt(time / (60 * 60));
kld = 'hours';
} else if (time <= 60 * 60 * 24 * 30 * 1.5) {
interval = parseInt(time / (60 * 60 * 24));
kld = 'days';
} else if (time < 60 * 60 * 24 * 30 * 24) {
interval = parseInt(time / (60 * 60 * 24 * 30));
kld = 'months';
} else if (time >= 60 * 60 * 24 * 30 * 24) {
interval = parseInt(time / (60 * 60 * 24 * 30 * 12));
kld = 'years';
}
drawX(interval, kld);
console.log(chartOption, 'chartOption')
var myChart2 = echarts.init(document.getElementById(`chartContent`));
window.onresize = () => {
myChart2.resize()
}
myChart2.setOption(chartOption);
} else {
chartOption.xAxis.data = [];
chartOption.series[0].data = [];
}
}
// 给柱状图数据赋值
function drawX(interval, kld) {
let x = [];
let y = [];
let timeStamp = [];
for (let i = 0; i <= interval - 1; i++) {
if (kld == 'minutes' || kld == 'hours') {
x.push(Moment(chart.dateTime[0]).add(i, kld).format('DD HH:mm'));
y.push(0);
} else if (kld == 'days') {
x.push(Moment(chart.dateTime[0]).add(i, kld).format('YYYY-MM-DD'));
y.push(0);
} else if (kld == 'months') {
x.push(Moment(chart.dateTime[0]).add(i, kld).format('YYYY-MM'));
y.push(0);
} else {
x.push(Moment(chart.dateTime[0]).add(i, kld).format('YYYY'));
y.push(0);
}
}
for (let i = 1; i <= interval; i++) {
timeStamp.push(Moment(chart.dateTime[0]).add(i, kld).valueOf());
}
x.forEach((item, index) => {
chart.data[`${chart.tabActive}Arr`].forEach((item) => {
if (
item.createtime > (index - 1 >= 0 ? timeStamp[index - 1] : 0) &&
item.createtime <= timeStamp[index]
) {
if (chart.tabActive == 'payAmount') {
y[index] = (Number(y[index]) + Number(item.counter)).toFixed(2);
} else {
y[index]++;
}
}
});
});
chartOption.xAxis.data = x;
chartOption.series[0].data = y;
}
// 默认获取当天的时间赋值
function getTimeSlot(e) {
let beginTime = Moment(new Date()).format('YYYY-MM-DD');
let endTime = Moment(new Date()).format('YYYY-MM-DD');
switch (e) {
case 'yesterday':
endTime = Moment().subtract(1, 'days').format('YYYY-MM-DD');
beginTime = endTime;
break;
case 'week':
beginTime = Moment().subtract(1, 'weeks').format('YYYY-MM-DD');
break;
case 'month':
beginTime = Moment().subtract(1, 'months').format('YYYY-MM-DD');
}
let timeSlot = [beginTime + ' 00:00:00', endTime + ' 23:59:59'];
return timeSlot;
}
const ranking = reactive({
goods: [],
hot_search: []
})
const pieOption = reactive({
tooltip: {
trigger: 'item',
formatter: '{a} <br/>{b}: {c} ({d}%)',
},
legend: {
show: false,
},
series: [
{
name: '热搜榜',
type: 'pie',
radius: ['52%', '90%'],
avoidLabelOverlap: false,
label: {
show: false,
position: 'center',
},
zlevel: 1,
z: 1,
emphasis: {
label: {
show: true,
fontSize: '16',
fontWeight: 'normal',
},
},
labelLine: {
show: false,
},
data: [],
},
],
});
function getRanking() {
Fast.api.ajax({
url: 'shopro/dashboard/ranking',
type: 'GET',
}, function (ret, res) {
ranking.goods = res.data.goods
ranking.hot_search = res.data.hot_search
pieOption.series[0].data = []
ranking.hot_search.forEach(item => {
pieOption.series[0].data.push({
name: item.keyword,
value: item.num,
});
})
var myChart3 = echarts.init(document.getElementById(`rankingContent`));
window.onresize = () => {
myChart3.resize()
}
myChart3.setOption(pieOption);
return false
}, function (ret, res) { })
}
function onOpen(status) {
Fast.api.open(`shopro/order/order/index?status=${status}&createtime=${encodeURI(JSON.stringify(chart.dateTime))}`, "订单", {
callback() {
getChart()
}
})
}
onMounted(() => {
Config.cardList.forEach(item => {
if (item.name == 'total' && item.status) {
getTotal()
}
if (item.name == 'chart' && item.status) {
getChart()
}
if (item.name == 'ranking' && item.status) {
getRanking()
}
})
})
return {
state,
getTotal,
chart,
onChangeTabActive,
onChangeDateTime,
statistics,
getChart,
chartOption,
initChart,
drawX,
getTimeSlot,
ranking,
onOpen,
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,296 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
order: 'asc',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/data/area',
type: 'GET',
data: {
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onAdd() {
Fast.api.open("shopro/data/area/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/data/area/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/data/area/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
pid: 0,
id: '',
name: '',
},
rules: {
id: [{ required: true, message: '请输入行政区ID', trigger: 'blur' }],
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/data/area/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
const area = reactive({
select: []
})
function getAreaSelect() {
Fast.api.ajax({
url: 'shopro/data/area/select',
type: 'GET',
}, function (ret, res) {
area.select = res.data;
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/data/area/add' : `shopro/data/area/edit/old_id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
getAreaSelect()
state.type == 'edit' && getDetail()
})
return {
state,
form,
area,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { reactive, computed, onMounted, getCurrentInstance, nextTick } = Vue
const select = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
selected: JSON.parse(new URLSearchParams(location.search).get('selected')),
data: [],
ids: [],
label: {},
checkedAll: false,
})
function getSelect() {
Fast.api.ajax({
url: 'shopro/data/area/select',
type: 'GET',
}, function (ret, res) {
state.data = res.data
state.checkedAll = state.selected.province.split(',').length == state.data.length;
nextTick(() => {
proxy.$refs['treeRef']?.getCheckedNodes().forEach((data) => {
if (state.ids.includes(data.id)) {
if (!state.label[data.level]) {
state.label[data.level] = {};
}
state.label[data.level][data.id] = data.name;
}
});
});
return false
}, function (ret, res) { })
}
const isIndeterminate = computed(() => (state.ids.length > 0 && !state.checkedAll ? true : false));
function onChange() {
if (state.checkedAll) {
nextTick(() => {
state.ids = [];
proxy.$refs['treeRef']?.setCheckedNodes(state.data, false);
state.data.forEach((d) => {
state.ids.push(d.id);
if (!state.label[d.level]) {
state.label[d.level] = {};
}
state.label[d.level][d.id] = d.name;
});
});
} else {
proxy.$refs['treeRef']?.setCheckedKeys([], false);
state.ids = [];
state.label = {
province: {},
city: {},
district: {},
};
}
}
function onChangeCheck(data, checked, indeterminate) {
// 全选
if (!state.checkedAll) {
// 选中(把自己放进去)
if (checked) {
state.ids.push(data.id);
if (!state.label[data.level]) {
state.label[data.level] = {};
}
state.label[data.level][data.id] = data.name;
}
}
// 未选中(把自己删除)
if (!checked) {
if (state.ids.includes(data.id)) {
state.ids.splice(state.ids.indexOf(data.id), 1);
for (var key in state.label[data.level]) {
if (Number(key) == Number(data.id)) {
delete state.label[data.level][key];
}
}
}
}
if (state.label.province)
state.checkedAll = Object.keys(state.label.province).length == state.data.length;
}
function deleteId(arr) {
arr.forEach(item => {
if (state.ids.includes(item.id)) {
state.ids.splice(state.ids.indexOf(item.id), 1);
delete state.label[item.level][item.id];
}
if (item.children && item.children.length > 0) {
deleteId(item.children)
}
})
}
function onConfirm() {
state.ids = [];
state.label = {
province: {},
city: {},
district: {},
};
proxy.$refs['treeRef']?.getCheckedNodes().forEach(item => {
state.ids.push(item.id)
if (!state.label[item.level]) {
state.label[item.level] = {};
}
state.label[item.level][item.id] = item.name;
})
proxy.$refs['treeRef']?.getCheckedNodes().forEach(item => {
if (item.children && item.children.length > 0) {
deleteId(item.children)
}
})
Fast.api.close(state.label)
}
onMounted(() => {
for (var level in state.selected) {
if (state.selected[level]) {
state.selected[level].split(',').forEach((id) => {
state.ids.push(id);
});
}
}
getSelect()
})
return {
state,
isIndeterminate,
onChange,
onChangeCheck,
onConfirm,
}
}
}
createApp('select', select);
},
};
return Controller;
});

View File

@@ -0,0 +1,224 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
keyword: { field: 'name', value: '' },
},
tools: {
keyword: {
type: 'tinputprepend',
label: '查询内容',
placeholder: '请输入查询内容',
value: {
field: 'name',
value: '',
},
options: {
data: [{
label: '快递公司',
value: 'name',
},
{
label: '快递编码',
value: 'code',
}]
}
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
name: 'like',
code: 'like',
});
Fast.api.ajax({
url: 'shopro/data/express',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
}
}
function onAdd() {
Fast.api.open("shopro/data/express/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/data/express/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/data/express/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
name: '',
code: '',
weigh: 0,
},
rules: {
name: [{ required: true, message: '请输入快递公司', trigger: 'blur' }],
code: [{ required: true, message: '请输入快递编码', trigger: 'blur' }],
weigh: [{ required: true, message: '请输入权重', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/data/express/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/data/express/add' : `shopro/data/express/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onConfirm
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,359 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
user: { field: 'id', value: '' },
gender: 'all',
},
tools: {
user: {
type: 'tinputprepend',
label: '用户信息',
placeholder: '请输入查询内容',
value: {
field: 'id',
value: '',
},
options: {
data: [{
label: '用户ID',
value: 'id',
},
{
label: '用户名',
value: 'username',
},
{
label: '用户昵称',
value: 'nickname',
},
{
label: '用户手机号',
value: 'mobile',
},
{
label: '邮箱',
value: 'email',
}],
}
},
gender: {
type: 'tselect',
label: '用户性别',
value: '',
options: {
data: [{
label: '全部',
value: 'all',
},
{
label: '女',
value: '0',
},
{
label: '男',
value: '1',
}]
},
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
username: 'like',
nickname: 'like',
mobile: 'like',
email: 'like',
});
Fast.api.ajax({
url: 'shopro/data/fake_user',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
}
}
function onAdd() {
Fast.api.open("shopro/data/fake_user/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/data/fake_user/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/data/fake_user/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onRandom() {
Fast.api.open('shopro/data/fake_user/random', "自动生成", {
callback() {
getData()
}
})
}
onMounted(() => {
getData()
})
return {
Fast,
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete,
onRandom
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
avatar: '',
username: '',
nickname: '',
email: '',
mobile: '',
password: '',
gender: 0,
},
rules: {
avatar: [{ required: true, message: '请选择用户头像', trigger: 'blur' }],
username: [{ required: true, message: '请输入用户名', trigger: 'blur' }],
nickname: [{ required: true, message: '请输入用户昵称', trigger: 'blur' }],
email: [{ required: true, message: '请输入电子邮箱', trigger: 'blur' }],
mobile: [{ required: true, message: '请输入手机号', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/data/fake_user/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
form.model.password = '';
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/data/fake_user/add' : `shopro/data/fake_user/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: function () {
const { reactive, onMounted } = Vue
const select = {
setup() {
const state = reactive({
data: [],
})
function getData() {
Fast.api.ajax({
url: 'shopro/data/fake_user/select',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onSelect(item) {
Fast.api.close(item)
}
onMounted(() => {
getData()
})
return {
state,
getData,
pagination,
onSelect
}
}
}
createApp('select', select);
},
random: () => {
const { reactive, getCurrentInstance } = Vue
const random = {
setup() {
const { proxy } = getCurrentInstance();
const form = reactive({
model: {
num: 1,
},
rules: {
num: [{ required: true, message: '请输入生成虚拟人数', trigger: 'blur' }],
},
})
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: 'shopro/data/fake_user/random',
type: 'POST',
data: JSON.parse(JSON.stringify(form.model))
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
form,
onConfirm
}
}
}
createApp('random', random);
},
};
return Controller;
});

View File

@@ -0,0 +1,220 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
keyword: '',
},
tools: {
keyword: {
type: 'tinput',
label: '查询内容',
placeholder: '请输入查询内容',
value: '',
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
keyword: 'like',
});
Fast.api.ajax({
url: 'shopro/data/faq',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
default:
Fast.api.ajax({
url: `shopro/data/faq/edit/id/${ids.join(',')}`,
type: 'POST',
data: {
status: type
}
}, function (ret, res) {
getData()
}, function (ret, res) { })
break;
}
}
function onAdd() {
Fast.api.open("shopro/data/faq/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/data/faq/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/data/faq/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
title: '',
content: '',
status: 'normal',
},
rules: {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
content: [{ required: true, message: '请输入内容', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/data/faq/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/data/faq/add' : `shopro/data/faq/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onConfirm
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,355 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/data/page',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
}
}
function onAdd() {
Fast.api.open("shopro/data/page/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/data/page/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/data/page/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
name: '',
path: '',
group: '',
},
rules: {
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
path: [{ required: true, message: '请输入路径', trigger: 'blur' }],
group: [{ required: true, message: '请输入分组', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/data/page/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/data/page/add' : `shopro/data/page/edit/id/${state.id}`,
type: 'POST',
data: form.model
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { ref, reactive, onMounted, getCurrentInstance, nextTick } = Vue
const select = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
data: [],
height: [],
currentIndex: 0,
selected: {},
});
async function getSelect() {
Fast.api.ajax({
url: 'shopro/data/page/select',
type: 'GET',
}, function (ret, res) {
state.data = res.data;
nextTick(() => {
getHeight();
});
return false
}, function (ret, res) { })
}
function onChangeIndex(index) {
proxy.$refs.rightScrollRef.setScrollTop(state.height[index]);
state.currentIndex = index;
}
function onRightScroll(e) {
let index = state.height.findIndex((item) => {
return item > e.scrollTop;
});
if (index > 0) {
state.currentIndex = index - 1;
} else if (index == -1) {
state.currentIndex = state.height.length - 1;
}
}
function onSelect(link) {
state.selected = { ...link };
if (link.path == '/pages/index/page') {
Fast.api.open('shopro/decorate/template/select', "选择自定义页面", {
callback(data) {
state.selected.path += (!isEmpty(data.id) ? '?id=' + data.id : '');
}
})
} else if (link.path == '/pages/goods/index') {
Fast.api.open('shopro/goods/goods/select', "选择商品", {
callback(data) {
state.selected.path += (!isEmpty(data.id) ? '?id=' + data.id : '');
}
})
} else if (link.path == '/pages/index/category') {
Fast.api.open('shopro/category/select?from=page-category', "选择分类", {
callback(data) {
state.selected.path += (!isEmpty(data.ids) ? '?id=' + data.ids : '');
}
})
} else if (link.path == '/pages/goods/list') {
Fast.api.open('shopro/category/select?from=page-goods', "选择分类", {
callback(data) {
state.selected.path += (!isEmpty(data.ids) ? '?categoryId=' + data.ids : '');
}
})
} else if (link.path == '/pages/public/richtext') {
Fast.api.open('shopro/data/richtext/select', "选择富文本", {
callback(data) {
state.selected.path += (!isEmpty(data.id) ? '?id=' + data.id : '');
}
})
} else if (
link.path == '/pages/activity/groupon/list' ||
link.path == '/pages/activity/seckill/list'
) {
let activityType = {
groupon: 'groupon,groupon_ladder',
seckill: 'seckill',
};
Fast.api.open(`shopro/activity/activity/select?type=${activityType[link.path.split('/')[3]]}`, "选择活动", {
callback(data) {
state.selected.path += (!isEmpty(data.id) ? '?id=' + data.id : '');
}
})
} else if (link.path == '/pages/goods/groupon' || link.path == '/pages/goods/seckill') {
let activityType = {
groupon: 'groupon,groupon_ladder',
seckill: 'seckill',
};
Fast.api.open(`shopro/activity/activity/select?type=${activityType[link.path.split('/').pop()]}`, "选择活动", {
callback(data) {
state.selected.path += (!isEmpty(data.id) ? '?activity_id=' + data.id : '');
Fast.api.open(`shopro/goods/goods/select?goods_ids=${data.goods_ids}`, "选择商品", {
callback(data) {
state.selected.path += (!isEmpty(data.id) ? '&id=' + data.id : '');
}
})
}
})
} else if (link.path == '/pages/goods/score') {
Fast.api.open(`shopro/app/score_shop/select`, "选择积分商品", {
callback(data) {
state.selected.path += (!isEmpty(data.id) ? '?id=' + data.id : '');
}
})
} else if (link.path == '/pages/coupon/detail') {
Fast.api.open(`shopro/coupon/select?status=normal`, "选择优惠券", {
callback(data) {
state.selected.path += (!isEmpty(data.id) ? '?id=' + data.id : '');
}
})
}
}
const rightRef = {};
function setRightRef(el, item, index) {
rightRef[item.group + index] = el;
}
function getHeight() {
state.height = [];
for (let e in rightRef) {
state.height.push(rightRef[e].offsetTop);
}
}
const platformUrl = ref({});
function getPlatformUrl() {
Fast.api.ajax({
url: 'shopro/config/getPlatformUrl',
type: 'GET',
}, function (ret, res) {
platformUrl.value = res.data
return false
}, function (ret, res) { })
}
async function onConfirm() {
state.selected.fullPath = {
url: `${platformUrl.value.url.endsWith('/')
? platformUrl.value.url.substr(0, platformUrl.value.url.length - 1)
: platformUrl.value.url
}${state.selected.path}`,
appid: platformUrl.value.appid,
pagepath: state.selected.path
? '/pages/index/index?page=' + encodeURIComponent(state.selected.path)
: '/pages/index/index',
};
Fast.api.close(state.selected)
}
onMounted(() => {
getSelect();
getPlatformUrl();
});
return {
state,
getSelect,
onRightScroll,
onChangeIndex,
onSelect,
rightRef,
setRightRef,
getHeight,
platformUrl,
getPlatformUrl,
onConfirm,
}
}
}
createApp('select', select);
}
};
return Controller;
});

View File

@@ -0,0 +1,291 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
keyword: '',
},
tools: {
keyword: {
type: 'tinput',
label: '查询内容',
placeholder: '请输入查询内容',
value: '',
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
keyword: 'like',
});
Fast.api.ajax({
url: 'shopro/data/richtext',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
}
}
function onAdd() {
Fast.api.open("shopro/data/richtext/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/data/richtext/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/data/richtext/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance, nextTick } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
title: '',
content: '',
},
rules: {
title: [{ required: true, message: '请输入标题', trigger: 'blur' }],
content: [{ required: true, message: '请输入内容', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/data/richtext/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
nextTick(() => {
Controller.api.bindevent();
$('#richtextContent').html(form.model.content)
})
return false
}, function (ret, res) { })
}
function onConfirm() {
form.model.content = $("#richtextContent").val()
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/data/richtext/add' : `shopro/data/richtext/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
if (state.type == 'add') {
nextTick(() => {
Controller.api.bindevent();
})
} else if (state.type == 'edit') {
getDetail()
}
})
return {
state,
form,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { reactive, onMounted } = Vue
const select = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/data/richtext/select',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onAdd() {
Fast.api.open("shopro/data/richtext/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onSelect(item) {
Fast.api.close(item)
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
onAdd,
onSelect
}
}
}
createApp('select', select);
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
}
},
};
return Controller;
});

View File

@@ -0,0 +1,103 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
data: () => {
return {
platformList: [
{
type: 'WechatMiniProgram',
label: '微信小程序',
color: '#6F74E9',
},
{
type: 'WechatOfficialAccount',
label: '微信公众号',
color: '#07C160',
},
{
type: 'H5',
label: 'H5',
color: '#FC800E',
},
{
type: 'App',
label: 'APP',
color: '#806AF6',
},
]
}
},
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
})
function getData() {
$.ajax({
url: 'https://api.sheepjs.com/api/designer',
type: 'GET',
success: function (ret) {
if (ret.error == 0) {
state.data = ret.data
} else {
Toastr.error(ret.msg);
}
},
error: function (xhr, textStatus, error) { }
});
}
function onUse(id) {
$.ajax({
url: `https://api.sheepjs.com/api/designer/${id}`,
type: 'GET',
success: function (ret) {
if (ret.error == 0) {
Fast.api.ajax({
url: `shopro/decorate/designer/use`,
type: 'POST',
data: ret.data
}, function (ret, res) {
getData()
}, function (ret, res) { })
} else {
Toastr.error(ret.msg);
}
},
error: function (xhr, textStatus, error) { }
});
}
function onPreview(item) {
let previewData = {
name: item.name,
type: 'designer',
platform: item.platform,
h5Url: item.h5Url,
wxacode: item.wxacode,
}
localStorage.setItem("preview-data", JSON.stringify(previewData));
Fast.api.open(`shopro/decorate/page/preview`, "预览")
}
onMounted(() => {
getData()
})
return {
...Controller.data(),
state,
getData,
onUse,
onPreview,
}
}
}
createApp('index', index);
},
};
return Controller;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,362 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
data: () => {
return {
platformList: [
{
type: 'WechatMiniProgram',
label: '微信小程序',
color: '#6F74E9',
},
{
type: 'WechatOfficialAccount',
label: '微信公众号',
color: '#07C160',
},
{
type: 'H5',
label: 'H5',
color: '#FC800E',
},
{
type: 'App',
label: 'APP',
color: '#806AF6',
},
]
}
},
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
type: 'template',
},
tools: {},
}
})
const type = reactive({
data: {
type: [
{ name: '模板列表', type: 'template' },
{ name: '自定义页面', type: 'diypage' }
]
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch);
Fast.api.ajax({
url: 'shopro/decorate/template',
type: 'GET',
data: {
...search,
},
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onAdd() {
Fast.api.open(`shopro/decorate/template/add?type=add&template=${state.filter.data.type}`, "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/decorate/template/edit?type=edit&id=${id}&template=${state.filter.data.type}`, "编辑", {
callback() {
getData()
}
})
}
function onCopy(id) {
Fast.api.ajax({
url: `shopro/decorate/template/copy/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/decorate/template/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onRecyclebin() {
Fast.api.open(`shopro/decorate/template/recyclebin`, "回收站", {
callback() {
getData()
}
})
}
function onDecorate(id) {
Fast.api.addtabs(`shopro/decorate/page/index?id=${id}&from=${state.filter.data.type}`, '装修模板')
}
function onChangeStatus(item) {
Fast.api.ajax({
url: `shopro/decorate/template/status/id/${item.id}`,
type: 'POST',
data: {
status: item.status == 'enable' ? 'disabled' : 'enable',
},
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
...Controller.data(),
Fast,
state,
type,
getData,
onAdd,
onEdit,
onCopy,
onDelete,
onRecyclebin,
onDecorate,
onChangeStatus,
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
template: new URLSearchParams(location.search).get('template'),
})
const form = reactive({
model: {
type: state.template,
name: '',
memo: '',
platform: [],
},
rules: {
name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/decorate/template/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/decorate/template/add' : `shopro/decorate/template/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
...Controller.data(),
state,
form,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
select: () => {
const { reactive, onMounted } = Vue
const select = {
setup() {
const state = reactive({
data: [],
})
function getData() {
Fast.api.ajax({
url: 'shopro/decorate/template/select',
type: 'GET',
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onSelect(item) {
Fast.api.close(item)
}
onMounted(() => {
getData()
})
return {
state,
onSelect,
}
}
}
createApp('select', select);
},
recyclebin: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const recyclebin = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/decorate/template/recyclebin',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'restore':
onRestore(ids.join(','))
break;
case 'destroy':
ElMessageBox.confirm('此操作将销毁, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy(ids.join(','))
});
break;
case 'all':
ElMessageBox.confirm('此操作将清空回收站, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy('all')
});
break;
}
}
function onRestore(id) {
Fast.api.ajax({
url: `shopro/decorate/template/restore/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onDestroy(id) {
Fast.api.ajax({
url: `shopro/decorate/template/destroy/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onRestore,
onDestroy,
}
}
}
createApp('recyclebin', recyclebin);
},
};
return Controller;
});

View File

@@ -0,0 +1,254 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
dispatch_type: 'express',
data: [],
})
function getData() {
Fast.api.ajax({
url: 'shopro/dispatch/dispatch',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
type: state.dispatch_type
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onChangeTab() {
pagination.page = 1
getData()
}
function onAdd() {
Fast.api.open(`shopro/dispatch/dispatch/add?type=add&dispatch_type=${state.dispatch_type}`, "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/dispatch/dispatch/edit?type=edit&id=${id}&dispatch_type=${state.dispatch_type}`, "编辑", {
callback() {
getData()
}
})
}
function onCopy(id) {
Fast.api.open(`shopro/dispatch/dispatch/add?type=copy&id=${id}&dispatch_type=${state.dispatch_type}`, "复制", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/dispatch/dispatch/delete/id/${id}?type=${state.dispatch_type}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
pagination,
onChangeTab,
onAdd,
onEdit,
onCopy,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
dispatch_type: new URLSearchParams(location.search).get('dispatch_type'),
priceType: 'number',
})
const form = reactive({
model: {
// dispatch_type: state.dispatch_type,
name: '',
type: state.dispatch_type,
express: [],
autosend: {
type: "text",
content: ""
}
},
rules: {
name: [{ required: true, message: '请输入模板名称', trigger: 'blur' }],
express: {
first_num: [{ required: true, message: '请输入数量', trigger: 'blur' }],
first_price: [{ required: true, message: '请输入运费', trigger: 'blur' }],
additional_num: [{ required: true, message: '请输入数量', trigger: 'blur' }],
additional_price: [{ required: true, message: '请输入续费', trigger: 'blur' }],
district_text: [{ required: true, message: '请选择可配送区域', trigger: 'blur' }],
}
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/dispatch/dispatch/detail/id/${state.id}`,
type: 'GET',
data: {
type: state.dispatch_type,
}
}, function (ret, res) {
form.model = res.data;
if (state.dispatch_type == 'express') {
state.priceType = form.model.express.length > 0 ? form.model.express[0].type : 'number';
}
return false
}, function (ret, res) { })
}
function onAddTemplate() {
form.model.express.push({
type: state.priceType,
first_num: 0,
first_price: 0,
additional_num: 0,
additional_price: 0,
province_ids: '',
city_ids: '',
district_ids: '',
});
}
function onDeleteTemplate(index) {
form.model.express.splice(index, 1);
}
function onSelectArea(index) {
let selected = {
province: form.model.express[index].province_ids,
city: form.model.express[index].city_ids,
district: form.model.express[index].district_ids,
}
Fast.api.open(`shopro/data/area/select?selected=${encodeURI(JSON.stringify(selected))}`, "选择地区", {
callback(data) {
let text = [];
for (var key in data) {
let ids = [];
for (var id in data[key]) {
ids.push(id);
text.push(data[key][id]);
}
form.model.express[index][key + '_ids'] = ids.join(',');
}
form.model.express[index].district_text = text.join(',');
}
})
}
function onChangeAutosendType(type) {
form.model.autosend.content = type == 'text' ? '' : []
}
function onAddContent() {
console.log(123, form.model.autosend.content)
if(!form.model.autosend.content){
form.model.autosend.content=[]
}
form.model.autosend.content.push({
title: '',
content: '',
});
}
function onDeleteContent(index) {
form.model.autosend.content.splice(index, 1);
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
let submitForm = JSON.parse(JSON.stringify(form.model));
if (state.dispatch_type == 'express') {
submitForm.express.forEach((item) => {
item.type = state.priceType;
});
if (state.type == 'copy') {
delete submitForm.id;
submitForm.express.forEach((item) => {
delete item.id;
});
}
}else if(state.dispatch_type == 'autosend'){
if (state.type == 'copy') {
delete submitForm.id;
}
}
Fast.api.ajax({
url: state.type == 'add' || state.type == 'copy' ? 'shopro/dispatch/dispatch/add' : `shopro/dispatch/dispatch/edit/id/${state.id}`,
type: 'POST',
data: submitForm,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
(state.type == 'edit' || state.type == 'copy') && getDetail()
})
return {
state,
form,
onAddTemplate,
onDeleteTemplate,
onSelectArea,
onChangeAutosendType,
onAddContent,
onDeleteContent,
onConfirm
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,210 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
keyword: '',
phone: '',
},
tools: {
keyword: {
type: 'tinput',
label: '查询内容',
placeholder: '请输入查询内容',
value: '',
},
phone: {
type: 'tinput',
label: '联系电话',
placeholder: '请输入联系电话',
value: '',
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
keyword: 'like',
phone: 'like',
});
Fast.api.ajax({
url: 'shopro/feedback',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
default:
Fast.api.ajax({
url: `shopro/feedback/edit/id/${ids.join(',')}`,
type: 'POST',
data: {
status: type
}
}, function (ret, res) {
getData()
}, function (ret, res) { })
break;
}
}
function onDetail(id) {
Fast.api.open(`shopro/feedback/detail?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/feedback/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onDetail,
onDelete
}
}
}
createApp('index', index);
},
detail: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const detail = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {},
rules: {},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/feedback/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/feedback/edit/id/${state.id}`,
type: 'POST',
data: {
status: form.model.status,
remark: form.model.remark,
}
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onConfirm
}
}
}
createApp('detail', detail);
}
};
return Controller;
});

View File

@@ -0,0 +1,525 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
order_id: new URLSearchParams(location.search).get('order_id'),
order_item_id: new URLSearchParams(location.search).get('order_item_id'),
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
'goods.title': '',
user: { field: 'user.nickname', value: '' },
content: '',
status: '',
},
tools: {
'goods.title': {
type: 'tinput',
label: '商品名称',
value: '',
},
user: {
type: 'tinputprepend',
label: '用户信息',
placeholder: '请输入查询内容',
value: {
field: 'user.nickname',
value: '',
},
options: {
data: [
{
label: '用户昵称',
value: 'user.nickname',
},
{
label: '用户手机号',
value: 'user.mobile',
},
]
}
},
content: {
type: 'tinput',
label: '评价内容',
value: '',
},
status: {
type: 'tselect',
label: '状态',
value: '',
options: {
data: [
{
label: '显示',
value: 'normal',
},
{
label: '隐藏',
value: 'hidden',
},
],
},
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
if (state.order_id) {
tempSearch = { ...tempSearch, order_id: state.order_id }
}
if (state.order_item_id) {
tempSearch = { ...tempSearch, order_item_id: state.order_item_id }
}
let search = composeFilter(tempSearch, {
'goods.title': 'like',
'user.nickname': 'like',
'user.mobile': 'like',
content: 'like',
});
Fast.api.ajax({
url: 'shopro/goods/comment',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
default:
onCommand({ id: ids.join(','), type: type })
break;
}
}
function onCommand(item) {
Fast.api.ajax({
url: `shopro/goods/comment/edit/id/${item.id}`,
type: 'POST',
data: {
status: item.type
}
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onOpenGoodsDetail(id) {
Fast.api.open(`shopro/goods/goods/add?type=edit&id=${id}`, "商品详情", {
callback() {
getData()
}
})
}
function onAdd() {
Fast.api.open("shopro/goods/comment/add?type=add", "添加虚拟评价", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/goods/comment/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/goods/comment/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onRecyclebin() {
Fast.api.open('shopro/goods/comment/recyclebin', "回收站", {
callback() {
getData()
}
})
}
onMounted(() => {
getData()
})
return {
onClipboard,
state,
getData,
onOpenFilter,
onChangeFilter,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onCommand,
onOpenGoodsDetail,
onAdd,
onEdit,
onDelete,
onRecyclebin
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
fakeUserData: {},
goodsData: {}
})
const form = reactive({
model: {
content: '',
images: [],
level: 0,
user_id: '',
goods_id: '',
status: 'normal',
},
rules: {
content: [{ required: true, message: '请输入评价内容', trigger: 'blur' }],
level: [{ required: true, message: '请选择评价星级', trigger: 'blur' }],
user_id: [{ required: true, message: '请选择评价用户', trigger: 'blur' }],
goods_id: [{ required: true, message: '请选择商品信息', trigger: 'blur' }],
status: [{ required: true, message: '请选择状态', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/goods/comment/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data
return false
}, function (ret, res) { })
}
function onSelectFakeUser() {
Fast.api.open("shopro/data/fake_user/select", "选择虚拟用户", {
callback(data) {
state.fakeUserData = data
form.model.user_id = data.id
}
})
}
function onDeleteFakeUser() {
state.fakeUserData = {}
form.model.user_id = ''
}
function onSelectGoods() {
Fast.api.open(`shopro/goods/goods/select`, "选择商品", {
callback(data) {
state.goodsData = data;
form.model.goods_id = data.id;
}
})
}
function onDeleteGoods() {
state.goodsData = {};
form.model.goods_id = '';
}
function onChangeStatus() {
Fast.api.ajax({
url: `shopro/goods/comment/edit/id/${state.id}`,
type: 'POST',
data: {
status: form.model.status
}
}, function (ret, res) {
getDetail()
}, function (ret, res) { })
}
function onReply() {
Fast.api.open(`shopro/goods/comment/reply/id/${state.id}?id=${state.id}`, "回复", {
callback() {
getDetail()
}
})
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: 'shopro/goods/comment/add',
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onSelectFakeUser,
onDeleteFakeUser,
onSelectGoods,
onDeleteGoods,
onChangeStatus,
onReply,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
recyclebin: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const recyclebin = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/goods/comment/recyclebin',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
tools: [
{
type: 'restore',
label: '还原',
class: 'primary',
},
{
type: 'destroy',
label: '销毁',
class: 'danger',
},
{
type: 'all',
label: '清空回收站',
class: 'danger',
},
]
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'restore':
onRestore(ids.join(','))
break;
case 'destroy':
ElMessageBox.confirm('此操作将销毁, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy(ids.join(','))
});
break;
case 'all':
ElMessageBox.confirm('此操作将清空回收站, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy('all')
});
break;
}
}
function onRestore(id) {
Fast.api.ajax({
url: `shopro/goods/comment/restore/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onDestroy(id) {
Fast.api.ajax({
url: `shopro/goods/comment/destroy/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onRestore,
onDestroy,
}
}
}
createApp('recyclebin', recyclebin);
},
reply: () => {
const { reactive, getCurrentInstance } = Vue
const reply = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
})
const form = reactive({
model: {
content: '',
},
rules: {
content: [{ required: true, message: '请输入回复内容', trigger: 'change' }],
},
})
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/goods/comment/reply/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
form,
onConfirm
}
}
}
createApp('reply', reply);
},
};
return Controller;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,178 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/goods/service',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'delete':
ElMessageBox.confirm('此操作将删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDelete(ids.join(','))
});
break;
}
}
function onAdd() {
Fast.api.open("shopro/goods/service/add?type=add", "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/goods/service/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/goods/service/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
name: '',
image: '',
description: '',
},
rules: {
name: [{ required: true, message: '请输入名称', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/goods/service/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/goods/service/add' : `shopro/goods/service/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onConfirm
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,89 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
'goods.title': '',
},
tools: {
'goods.title': {
type: 'tinput',
label: '商品名称',
placeholder: '请输入商品名称',
value: '',
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'goods.title': 'like',
});
Fast.api.ajax({
url: 'shopro/goods/stock_log',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,227 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
stock_type: 'all',
'goods.title': '',
},
tools: {
'goods.title': {
type: 'tinput',
label: '商品名称',
placeholder: '请输入商品名称',
value: '',
},
},
condition: {},
},
stockType: {
all: { name: '全部' },
over: { name: '已售罄', num: 0 },
no_enough: { name: '预警中', num: 0 },
}
})
const type = reactive({
data: {
stock_type: {
all: { name: '全部' },
over: { name: '已售罄', num: 0 },
no_enough: { name: '预警中', num: 0 },
}
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'goods.title': 'like',
});
Fast.api.ajax({
url: 'shopro/goods/stock_warning',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.rows.data
pagination.total = res.data.rows.total
type.data.stock_type.over.num = res.data.over_total;
type.data.stock_type.no_enough.num = res.data.warning_total;
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
function onChangeTab() {
pagination.page = 1
getData()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onAddStock(item) {
Fast.api.open(`shopro/goods/stock_warning/addStock?id=${item.id}&stock=${item.stock}`, "补货", {
callback() {
getData()
}
})
}
function onRecyclebin() {
Fast.api.open('shopro/goods/stock_warning/recyclebin', "历史记录", {
callback() {
getData()
}
})
}
onMounted(() => {
getData()
})
return {
state,
type,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
onChangeTab,
pagination,
onAddStock,
onRecyclebin,
}
}
}
createApp('index', index);
},
addstock: () => {
const { reactive, getCurrentInstance } = Vue
const addStock = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
stock: new URLSearchParams(location.search).get('stock')
})
const form = reactive({
model: {
stock: '',
},
rules: {
stock: [{ required: true, message: '请输入补充库存', trigger: 'blur' }],
},
})
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/goods/stock_warning/addStock/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
state,
form,
onConfirm
}
}
}
createApp('addStock', addStock);
},
recyclebin: () => {
const { reactive, onMounted } = Vue
const recyclebin = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/goods/stock_warning/recyclebin',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
}
}
}
createApp('recyclebin', recyclebin);
},
};
return Controller;
});

View File

@@ -0,0 +1,277 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted, ref } = Vue
const index = {
setup() {
const state = reactive({
receiver_type: 'user',
data: [],
qrcodeUrl: '',
eventId: '',
scanStatus: '',
oauthInfo: {},
})
function getData() {
Fast.api.ajax({
url: 'shopro/notification/config',
type: 'GET',
data: {
receiver_type: state.receiver_type,
},
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onEdit(event, channel) {
Fast.api.open(`shopro/notification/config/edit?event=${event}&channel=${channel}`, "编辑", {
callback() {
getData()
}
})
}
function onSetStatus(status, event, channel) {
Fast.api.ajax({
url: `shopro/notification/config/setStatus/id/${event}`,
type: 'POST',
data: {
status, event, channel
}
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
// 点击二维码
function onQrcode() {
state.qrcodeUrl = '';
getQrcode();
}
function onHideQrcode() {
state.eventId = '';
}
// 获取绑定二维码
function getQrcode() {
Fast.api.ajax({
url: 'shopro/wechat/admin/getQrcode?event=bind',
type: 'GET',
loading: false,
}, function (ret, res) {
if (res.code === 1) {
state.qrcodeUrl = ret.url;
state.eventId = ret.eventId;
// 待扫码
state.scanStatus = 'pending';
checkScanResult(ret.eventId);
}
return false;
}, function (data, res) {
if (res.code === -2) {
// 已绑定
state.scanStatus = 'binded';
state.oauthInfo = res.data;
}
return false;
})
}
// 检查扫码结果
function checkScanResult(eventId) {
if (eventId !== state.eventId) return;
Fast.api.ajax({
url: 'shopro/wechat/admin/checkScan?event=bind&eventId=' + eventId,
type: 'GET',
loading: false,
}, function (data, res) {
if (res.code === 1) {
// 扫码成功
state.scanStatus = 'scanned';
}
return false;
}, function (data, res) {
if (res.code === -1) {
setTimeout(function () {
checkScanResult(eventId);
}, 2000)
// 待扫码
state.scanStatus = 'pending';
return false;
} else {
// 已过期
state.scanStatus = 'expired';
}
})
}
const qrcodePopoverRef = ref()
// 解除绑定
function onUnbind() {
Fast.api.ajax({
url: 'shopro/wechat/admin/unbind',
type: 'GET',
}, function (data, res) {
state.scanStatus = '';
qrcodePopoverRef.value.hide()
}, function (data, res) {
})
}
onMounted(() => {
getData()
})
return {
state,
getData,
onEdit,
onSetStatus,
onQrcode,
onHideQrcode,
qrcodePopoverRef,
onUnbind,
}
}
}
createApp('index', index);
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
event: new URLSearchParams(location.search).get('event'),
channel: new URLSearchParams(location.search).get('channel')
})
const form = reactive({
model: {},
rules: {},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/notification/config/detail`,
type: 'GET',
data: {
event: state.event,
channel: state.channel
}
}, function (ret, res) {
form.model = res.data;
if (state.channel == 'Email') {
fieldList.data = res.data.content;
form.model.content = res.data.content_text;
Controller.api.bindevent();
$('#emailContent').html(form.model.content)
} else {
form.model.content.fields.forEach((e) => {
if (!e.value) {
e['value'] = '';
}
if (!e.template_field) {
e['template_field'] = '';
}
});
}
return false
}, function (ret, res) { })
}
const templateIdPopover = reactive({
flag: false,
is_delete: '1'
})
function getTemplateId(is_delete) {
templateIdPopover.flag = false;
Fast.api.ajax({
url: `shopro/notification/config/getTemplateId`,
type: 'GET',
data: {
event: state.event,
channel: state.channel,
is_delete: is_delete,
template_id: is_delete == 1 ? form.model.content.template_id : '',
}
}, function (ret, res) {
form.model.content.template_id = res.data;
}, function (ret, res) { })
}
function onAddField() {
form.model.content.fields.push({
name: '',
template_field: '',
value: '',
});
}
function onDeleteField(index) {
form.model.content.fields.splice(index, 1);
}
const fieldList = reactive({
data: {},
});
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
let submitForm = JSON.parse(JSON.stringify(form.model));
if (state.channel == 'Email') {
delete submitForm.content_text;
submitForm.content = $("#emailContent").val();
}
Fast.api.ajax({
url: `shopro/notification/config/edit`,
type: 'POST',
data: {
event: state.event,
channel: state.channel,
...submitForm,
}
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
getDetail()
})
return {
state,
form,
templateIdPopover,
getTemplateId,
onAddField,
onDeleteField,
fieldList,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
api: {
bindevent: function () {
Form.api.bindevent($("form[role=form]"));
},
},
};
return Controller;
});

View File

@@ -0,0 +1,437 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
'aftersale_list.aftersale_status': 'all',
'aftersale_list.goods_title': '',
keyword: { field: 'aftersale_list.aftersale_sn', value: '' },
user: { field: 'user.nickname', value: '' },
'aftersale_list.type': '',
'aftersale_list.dispatch_status': '',
'aftersale_list.refund_status': '',
},
tools: {
'aftersale_list.goods_title': {
type: 'tinput',
label: '商品名称',
value: '',
},
keyword: {
type: 'tinputprepend',
label: '售后信息',
placeholder: '请输入查询内容',
value: {
field: 'aftersale_list.aftersale_sn',
value: '',
},
options: {
data: [{
label: '售后单号',
value: 'aftersale_list.aftersale_sn',
},
{
label: '售后手机号',
value: 'aftersale_list.mobile',
},
{
label: '订单编号',
value: 'order_sn',
}]
}
},
user: {
type: 'tinputprepend',
label: '售后用户',
placeholder: '请输入查询内容',
value: {
field: 'user.nickname',
value: '',
},
options: {
data: [{
label: '用户昵称',
value: 'user.nickname',
},
{
label: '手机号',
value: 'user.mobile',
}]
},
},
'aftersale_list.type': {
type: 'tselect',
label: '售后类型',
value: '',
options: {
data: [],
props: {
label: 'name',
value: 'type',
},
},
},
'aftersale_list.dispatch_status': {
type: 'tselect',
label: '发货状态',
value: '',
options: {
data: [],
props: {
label: 'name',
value: 'type',
},
},
},
'aftersale_list.refund_status': {
type: 'tselect',
label: '退款状态',
value: '',
options: {
data: [],
props: {
label: 'name',
value: 'type',
},
},
},
},
condition: {},
}
})
const type = reactive({
data: {}
})
function getType() {
Fast.api.ajax({
url: 'shopro/order/aftersale/getType',
type: 'GET',
}, function (ret, res) {
type.data = res.data
for (key in res.data) {
if (key == 'aftersale_status') {
} else {
state.filter.tools[`aftersale_list.${key}`].options.data = res.data[key]
}
}
return false
}, function (ret, res) { })
}
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'aftersale_list.goods_title': 'like',
'aftersale_list.aftersale_sn': 'like',
'aftersale_list.mobile': 'like',
order_sn: 'like',
'user.nickname': 'like',
'user.mobile': 'like',
});
search = {
search: JSON.stringify({
'aftersale_list._': '',
...JSON.parse(search.search),
}),
};
Fast.api.ajax({
url: 'shopro/order/aftersale',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
function onChangeTab() {
pagination.page = 1
getData()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onDetail(id) {
Fast.api.open(`shopro/order/aftersale/detail/id/${id}?id=${id}`, "详情", {
callback() {
getData()
}
})
}
function onOpenGoods(id) {
Fast.api.open(`shopro/goods/goods/add?type=edit&id=${id}`, "商品详情", {
callback() {
getData()
}
})
}
function onOpenOrderDetail(id) {
Fast.api.open(`shopro/order/order/detail?id=${id}`, "订单详情", {
callback() {
getData()
}
})
}
onMounted(() => {
getType()
getData()
})
return {
onClipboard,
state,
type,
getData,
onOpenFilter,
onChangeFilter,
onChangeTab,
pagination,
onDetail,
onOpenGoods,
onOpenOrderDetail,
}
}
}
createApp('index', index);
},
detail: () => {
const { reactive, onMounted } = Vue
const detail = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
data: {},
stepActive: 1,
})
function getDetail() {
Fast.api.ajax({
url: `shopro/order/aftersale/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.data = res.data;
setStepActive()
return false
}, function (ret, res) { })
}
function setStepActive() {
if (
state.data.aftersale_status == -1 ||
state.data.aftersale_status == -2 ||
state.data.aftersale_status == 2
) {
state.stepActive = 3;
} else {
state.stepActive = state.data.aftersale_status + 1;
}
}
function onRefund() {
Fast.api.open(`shopro/order/aftersale/refund/id/${state.id}?id=${state.id}&suggest_refund_fee=${state.data.suggest_refund_fee}`, "售后退款", {
callback() {
getDetail()
}
})
}
function onRefuse() {
Fast.api.open(`shopro/order/aftersale/refuse/id/${state.id}?id=${state.id}`, "拒绝售后", {
callback() {
getDetail()
}
})
}
function onCompleted() {
Fast.api.ajax({
url: `shopro/order/aftersale/completed/id/${state.id}`,
type: 'POST',
}, function (ret, res) {
getDetail()
}, function (ret, res) { })
}
function onAddLog() {
Fast.api.open(`shopro/order/aftersale/addLog/id/${state.id}?id=${state.id}`, "回复买家", {
callback() {
getDetail()
}
})
}
onMounted(() => {
getDetail()
})
return {
onClipboard,
state,
onRefund,
onRefuse,
onCompleted,
onAddLog,
}
}
}
createApp('detail', detail);
},
refund: () => {
const { reactive, getCurrentInstance } = Vue
const refund = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
suggest_refund_fee: new URLSearchParams(location.search).get('suggest_refund_fee'),
})
const form = reactive({
model: {
refund_type: 'back',
refund_money: '',
},
rules: {
refund_money: [{ required: true, message: '请输入退款金额', trigger: 'blur' }],
},
})
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/order/aftersale/refund/id/${state.id}`,
type: 'POST',
data: form.model
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
state,
form,
onConfirm,
}
}
}
createApp('refund', refund);
},
refuse: () => {
const { reactive, getCurrentInstance } = Vue
const refuse = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
})
const form = reactive({
model: {
refuse_msg: '',
},
rules: {
refuse_msg: [{ required: true, message: '请输入拒绝原因', trigger: 'blur' }],
},
})
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/order/aftersale/refuse/id/${state.id}`,
type: 'POST',
data: form.model
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
state,
form,
onConfirm,
}
}
}
createApp('refuse', refuse);
},
addlog: () => {
const { reactive, getCurrentInstance } = Vue
const addLog = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
})
const form = reactive({
model: {
content: '',
images: [],
},
rules: {
content: [{ required: true, message: '请输入', trigger: 'blur' }],
},
})
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/order/aftersale/addLog/id/${state.id}`,
type: 'POST',
data: form.model
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
state,
form,
onConfirm,
}
}
}
createApp('addLog', addLog);
},
};
return Controller;
});

View File

@@ -0,0 +1,273 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
status: 'all',
order: { field: 'order.order_sn', value: '' },
user: { field: 'user.nickname', value: '' },
invoice: { field: 'name', value: '' },
type: '',
},
tools: {
order: {
type: 'tinputprepend',
label: '订单信息',
placeholder: '请输入查询内容',
value: {
field: 'order.order_sn',
value: '',
},
options: {
data: [{
label: '订单编号',
value: 'order.order_sn',
},
{
label: '订单ID',
value: 'order_id',
}]
}
},
user: {
type: 'tinputprepend',
label: '用户信息',
placeholder: '请输入查询内容',
value: {
field: 'user.nickname',
value: '',
},
options: {
data: [{
label: '用户昵称',
value: 'user.nickname',
},
{
label: '用户手机号',
value: 'user.mobile',
}]
}
},
invoice: {
type: 'tinputprepend',
label: '发票信息',
placeholder: '请输入查询内容',
value: {
field: 'name',
value: '',
},
options: {
data: [{
label: '发票抬头',
value: 'name',
},
{
label: '税号',
value: 'tax_no',
},
{
label: ' 联系方式',
value: 'mobile',
},
{
label: ' 公司地址',
value: 'address',
}]
}
},
type: {
type: 'tselect',
label: '发票类型',
value: '',
options: {
data: [{
label: '全部',
value: 'all',
},
{
label: '个人',
value: 'person',
},
{
label: '企/事业单位',
value: 'company',
}]
},
},
},
condition: {},
},
statusStyle: {
cancel: 'danger',
unpaid: 'info',
waiting: 'warning',
finish: 'success',
},
})
const type = reactive({
data: {
status: [{
name: '全部',
type: 'all',
},
{
name: '已取消',
type: 'cancel',
},
{
name: '未支付',
type: 'unpaid',
},
{
name: '等待处理',
type: 'waiting',
},
{
name: '已开具',
type: 'finish',
}],
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'order.order_sn': 'like',
'user.nickname': 'like',
'user.mobile': 'like',
name: 'like',
tax_no: 'like',
address: 'like',
});
Fast.api.ajax({
url: 'shopro/order/invoice',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
function onChangeTab() {
pagination.page = 1
getData()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onConfirm(item) {
let params = {
id: item.id,
order_status_text: item.order_status_text,
order_fee: item.order_fee,
amount: item.amount,
}
Fast.api.open(`shopro/order/invoice/confirm/id/${item.id}?item=${encodeURI(JSON.stringify(params))}`, "开具发票", {
callback() {
getData()
}
})
}
function onOpenOrderDetail(id) {
Fast.api.open(`shopro/order/order/detail?id=${id}`, "订单详情", {
callback() {
getData()
}
})
}
onMounted(() => {
getData()
})
return {
onClipboard,
state,
type,
getData,
onOpenFilter,
onChangeFilter,
onChangeTab,
pagination,
onOpenOrderDetail,
onConfirm,
}
}
}
createApp('index', index);
},
confirm: () => {
const { reactive, getCurrentInstance } = Vue
const confirm = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
item: JSON.parse(new URLSearchParams(location.search).get('item')),
})
const form = reactive({
model: {
invoice_amount: state.item.amount,
download_urls: [],
},
rules: {
invoice_amount: [{ required: true, message: '请输入实际开票金额', trigger: 'blur' }],
download_urls: [{ required: true, message: '请选择发票图片', trigger: 'blur' }],
},
});
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/order/invoice/confirm/id/${state.item.id}`,
type: 'POST',
data: form.model
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
state,
form,
onConfirm,
}
}
}
createApp('confirm', confirm);
},
};
return Controller;
});

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,240 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => { },
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
name: '',
type: 'wechat',
params: {
app_id: '',
mode: '0',
mch_secret_cert: '',
mch_public_cert_path: '',
alipay_public_cert_path: '',
app_public_cert_path: '',
alipay_root_cert_path: '',
app_secret_cert: '',
service_provider_id: '',
mch_id: '',
mch_secret_key: '',
sub_mch_id: '',
sub_mch_secret_key: '',
sub_mch_public_cert_path: '',
sub_mch_secret_cert: '',
wechat_public_cert_id: '',
wechat_public_cert: '',
},
status: 'normal',
},
rules: {
name: [{ required: true, message: '请输入标题', trigger: 'blur' }],
params: {
mch_id: [{ required: true, message: '请输入商户号', trigger: 'blur' }],
mch_secret_key: [{ required: true, message: '请输入商户密钥', trigger: 'blur' }],
mch_secret_cert: [{ required: true, message: '请上传商户key证书', trigger: 'blur' }],
mch_public_cert_path: [{ required: true, message: '请上传商户证书', trigger: 'blur' }],
app_id: [{ required: true, message: '请输入主商户AppId', trigger: 'blur' }],
sub_mch_id: [{ required: true, message: '请输入子商户号', trigger: 'blur' }],
alipay_public_cert_path: [
{ required: true, message: '请上传支付宝公钥证书', trigger: 'blur' },
],
app_public_cert_path: [{ required: true, message: '请上传应用公钥证书', trigger: 'blur' }],
alipay_root_cert_path: [{ required: true, message: '请上传支付宝根证书', trigger: 'blur' }],
app_secret_cert: [{ required: true, message: '请输入私钥', trigger: 'blur' }],
service_provider_id: [{ required: true, message: '请输入主商户ID', trigger: 'blur' }],
},
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/pay_config/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
function onAjaxUpload(id) {
var formData = new FormData();
formData.append("file", $('#' + id)[0].files[0]);
formData.append('shopro_type', 'simple');
$.ajax({
type: "POST",
url: "ajax/upload",
data: formData,
cache: false,
processData: false,
contentType: false,
success: function (res) {
if (res.code == 1) {
form.model.params[id] = res.data.url
} else {
Toastr.error(res.msg);
}
},
})
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/pay_config/add' : `shopro/pay_config/edit/id/${state.id}`,
type: 'POST',
data: JSON.parse(JSON.stringify(form.model))
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onAjaxUpload,
onConfirm
}
}
}
createApp('addEdit', addEdit);
},
recyclebin: () => {
const { reactive, onMounted } = Vue
const { ElMessageBox } = ElementPlus
const recyclebin = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/pay_config/recyclebin',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const batchHandle = reactive({
data: [],
})
function onChangeSelection(val) {
batchHandle.data = val
}
function onBatchHandle(type) {
let ids = []
batchHandle.data.forEach((item) => {
ids.push(item.id)
})
switch (type) {
case 'restore':
onRestore(ids.join(','))
break;
case 'destroy':
ElMessageBox.confirm('此操作将销毁, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy(ids.join(','))
});
break;
case 'all':
ElMessageBox.confirm('此操作将清空回收站, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning',
}).then(() => {
onDestroy('all')
});
break;
}
}
function onRestore(id) {
Fast.api.ajax({
url: `shopro/pay_config/restore/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onDestroy(id) {
Fast.api.ajax({
url: `shopro/pay_config/destroy/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
batchHandle,
onChangeSelection,
onBatchHandle,
onRestore,
onDestroy,
}
}
}
createApp('recyclebin', recyclebin);
},
};
return Controller;
});

View File

@@ -0,0 +1,275 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
data: () => {
return {
statusStyle: {
unpaid: 'warning',
paid: 'success',
completed: 'success',
closed: 'danger',
cancel: 'info',
closed: 'danger',
}
}
},
index: () => {
const { ref, reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
filter: {
drawer: false,
data: {
status: 'all',
order: { field: 'id', value: '' },
user: { field: 'user_id', value: '' },
platform: '',
'pay.pay_type': '',
createtime: [],
},
tools: {
order: {
type: 'tinputprepend',
label: '查询内容',
placeholder: '请输入查询内容',
value: {
field: 'id',
value: '',
},
options: {
data: [{
label: '订单ID',
value: 'id',
},
{
label: '订单编号',
value: 'order_sn',
},
{
label: '支付单号',
value: 'pay.pay_sn',
}],
}
},
user: {
type: 'tinputprepend',
label: '用户信息',
placeholder: '请输入查询内容',
value: {
field: 'user_id',
value: '',
},
options: {
data: [{
label: '用户ID',
value: 'user_id',
},
{
label: '用户昵称',
value: 'user.nickname',
},
{
label: '用户手机号',
value: 'user.mobile',
}],
}
},
platform: {
type: 'tselect',
label: '订单来源',
value: '',
options: {
data: [],
props: {
label: 'name',
value: 'type',
},
},
},
'pay.pay_type': {
type: 'tselect',
label: '支付方式',
value: '',
options: {
data: [],
props: {
label: 'name',
value: 'type',
},
},
},
createtime: {
type: 'tdatetimerange',
label: '下单时间',
value: [],
},
},
condition: {},
},
})
const type = reactive({
data: {}
})
function getType() {
Fast.api.ajax({
url: 'shopro/trade/order/getType',
type: 'GET',
}, function (ret, res) {
type.data = res.data
for (key in res.data) {
if (key == 'pay_type') {
state.filter.tools['pay.pay_type'].options.data = res.data[key]
} else if (key == 'platform') {
state.filter.tools[key].options.data = res.data[key]
}
}
return false
}, function (ret, res) { })
}
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
order_sn: 'like',
'pay.pay_sn': 'like',
'user.nickname': 'like',
'user.mobile': 'like',
createtime: 'range',
});
Fast.api.ajax({
url: 'shopro/trade/order',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.orders.data
pagination.total = res.data.orders.total
type.data?.status?.forEach(item => {
item.num = res.data[item.type]
})
return false
}, function (ret, res) { })
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
function onChangeTab() {
pagination.page = 1
getData()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const exportLoading = ref(false);
function onExport() {
exportLoading.value = true;
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
order_sn: 'like',
'pay.pay_sn': 'like',
'user.nickname': 'like',
'user.mobile': 'like',
createtime: 'range',
});
if (Config.save_type == 'download') {
window.location.href = `${Config.moduleurl}/shopro/trade/order/export?page=${pagination.page}&list_rows=${pagination.list_rows}&search=${search.search}`;
exportLoading.value = false;
} else if (Config.save_type == 'save') {
Fast.api.ajax({
url: 'shopro/trade/order/export',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
exportLoading.value = false;
}, function (ret, res) { })
}
}
function onDetail(id) {
Fast.api.open(`shopro/trade/order/detail/id/${id}?id=${id}`, "详情", {
callback() {
getData()
}
})
}
onMounted(() => {
getType()
getData()
})
return {
onClipboard,
...Controller.data(),
state,
type,
getData,
onOpenFilter,
onChangeFilter,
onChangeTab,
pagination,
exportLoading,
onExport,
onDetail,
}
}
}
createApp('index', index);
},
detail: () => {
const { reactive, onMounted } = Vue
const detail = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
detail: {},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/trade/order/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.detail = res.data;
return false
}, function (ret, res) { })
}
onMounted(() => {
getDetail()
})
return {
...Controller.data(),
state,
}
}
}
createApp('detail', detail);
},
};
return Controller;
});

View File

@@ -0,0 +1,155 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
coupon_id: new URLSearchParams(location.search).get('coupon_id'),
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
user: { field: 'user_id', value: '' },
'order.order_sn': '',
status: '',
createtime: [],
use_time: [],
},
tools: {
user: {
type: 'tinputprepend',
label: '用户信息',
placeholder: '请输入查询内容',
value: {
field: 'user_id',
value: '',
},
options: {
data: [{
label: '用户ID',
value: 'user_id',
},
{
label: '用户昵称',
value: 'user.nickname',
},
{
label: '用户手机号',
value: 'user.mobile',
}]
}
},
'order.order_sn': {
type: 'tinput',
label: '订单号',
placeholder: '请输入订单号',
value: '',
},
status: {
type: 'tselect',
label: '状态',
value: '',
options: {
data: [{
label: '未使用',
value: 'geted',
},
{
label: '已使用',
value: 'used',
},
{
label: '已过期',
value: 'expired',
}],
},
},
createtime: {
type: 'tdatetimerange',
label: '领取时间',
value: [],
},
use_time: {
type: 'tdatetimerange',
label: '使用时间',
value: [],
},
},
condition: {},
},
statusClass: {
geted: 'info',
used: 'success',
expired: 'error',
},
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'user.nickname': 'like',
'user.mobile': 'like',
createtime: 'range',
use_time: 'range',
});
Fast.api.ajax({
url: 'shopro/user/coupon',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
coupon_id: state.coupon_id,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,475 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
user: { field: 'id', value: '' },
createtime: [],
logintime: [],
},
tools: {
user: {
type: 'tinputprepend',
label: '用户信息',
placeholder: '请输入查询内容',
value: {
field: 'id',
value: '',
},
options: {
data: [{
label: '用户ID',
value: 'id',
},
{
label: '用户名',
value: 'username',
},
{
label: '昵称',
value: 'nickname',
},
{
label: '手机号',
value: 'mobile',
},
{
label: '邮箱',
value: 'email',
}],
}
},
createtime: {
type: 'tdatetimerange',
label: '注册时间',
value: [],
},
logintime: {
type: 'tdatetimerange',
label: '上次登录',
value: [],
},
},
condition: {},
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
username: 'like',
nickname: 'like',
mobile: 'like',
email: 'like',
createtime: 'range',
logintime: 'range',
});
Fast.api.ajax({
url: 'shopro/user/user',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onDetail(id) {
Fast.api.open(`shopro/user/user/detail?id=${id}`, "详情", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/user/user/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
pagination,
onDetail,
onDelete
}
}
}
createApp('index', index);
},
detail: () => {
const { reactive, onMounted } = Vue
const detail = {
setup() {
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
detail: {}
})
function getDetail() {
Fast.api.ajax({
url: `shopro/user/user/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.detail = res.data;
return false
}, function (ret, res) { })
}
const platform = {
wechat: {
openPlatform: '微信开放平台',
miniProgram: '微信小程序',
officialAccount: '微信公众平台',
},
};
function statusStyle(key) {
let flag = state.detail.verification?.[key];
return `<span style="color:${flag ? 'var(--el-color-success)' : 'var(--el-color-warning)'}">
${flag ? '已' : '未'}${key == 'username' || key == 'password' ? '设置' : '认证'}
</span>`;
}
function onSelectAvatar() {
Fast.api.open(`general/attachment/select`, "选择", {
callback: function (data) {
state.detail.avatar = data.url;
}
});
}
async function onSave() {
Fast.api.ajax({
url: `shopro/user/user/edit/id/${state.id}`,
type: 'POST',
data: state.detail,
}, function (ret, res) {
getDetail()
}, function (ret, res) { })
}
function onChangeParentUser() {
Fast.api.open(`shopro/commission/agent/select?id=${state.id}`, "更换上级分销商", {
callback() {
getDetail()
}
})
}
function onRecharge(type) {
Fast.api.open(`shopro/user/user/recharge?type=${type}&id=${state.detail.id}`, "充值", {
callback: function () {
getDetail();
getLog()
}
});
}
const log = reactive({
tabActive: 'money',
data: [],
})
function getLog() {
let url
let search = {}
if (log.tabActive == 'money' || log.tabActive == 'score' || log.tabActive == 'commission') {
url = `shopro/user/wallet_log/${log.tabActive}/id/${state.id}`
}
if (log.tabActive == 'order') {
url = `shopro/order/order`
search = {
search: JSON.stringify({
user_id: state.id
})
}
}
if (log.tabActive == 'share') {
url = `shopro/share`
search = {
id: state.id
}
}
if (log.tabActive == 'coupon') {
url = `shopro/user/user/coupon/id/${state.id}`
}
Fast.api.ajax({
url: url,
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
if (log.tabActive == 'order') {
log.data = res.data.orders.data
pagination.total = res.data.orders.total
} else {
log.data = res.data.data
pagination.total = res.data.total
}
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onChangeTab() {
log.data = []
pagination.page = 1
pagination.total = 0
getLog()
}
onMounted(() => {
getDetail()
getLog()
})
return {
state,
getDetail,
platform,
statusStyle,
onSelectAvatar,
onSave,
onChangeParentUser,
onRecharge,
log,
getLog,
pagination,
onChangeTab,
}
}
}
createApp('detail', detail);
},
recharge: () => {
const { reactive, getCurrentInstance } = Vue
const recharge = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
id: state.id,
type: state.type,
amount: '',
memo: '',
},
rules: {
amount: [{ required: true, message: '请输入', trigger: 'blur' }],
},
})
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/user/user/recharge`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
state,
form,
onConfirm
}
}
}
createApp('recharge', recharge);
},
select: function () {
const { reactive, onMounted } = Vue
const select = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id') || false,
filter: {
drawer: false,
data: {
keyword: '',
},
tools: {},
condition: {},
},
data: [],
ids: [],
isSelectAll: false,
isIndeterminate: false,
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
keyword: 'like',
});
Fast.api.ajax({
url: 'shopro/user/user/select',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
calculateSelect();
return false
}, function (ret, res) { })
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onChangeFilter() {
pagination.page = 1
getData()
}
function onSelect(type, row) {
if (type) {
state.ids.push(row.id);
} else {
let findIndex = state.ids.findIndex((id) => id == row.id);
state.ids.splice(findIndex, 1);
}
calculateSelect();
};
function onSelectAll(type) {
if (type) {
state.data.forEach((item) => {
state.ids.push(item.id);
});
state.ids = Array.from(new Set(state.ids));
} else {
state.data.forEach((item) => {
if (state.ids.findIndex((id) => id == item.id) !== -1) {
state.ids.splice(
state.ids.findIndex((id) => id == item.id),
1,
);
}
});
}
calculateSelect();
}
function calculateSelect() {
state.isSelectAll = false;
state.isIndeterminate = false;
if (state.data.every((item) => state.ids.includes(item.id))) {
state.isSelectAll = true;
state.isIndeterminate = false;
} else if (state.data.some((item) => state.ids.includes(item.id))) {
state.isSelectAll = false;
state.isIndeterminate = true;
}
if (state.data.length === 0) {
state.isSelectAll = false;
state.isIndeterminate = false;
}
}
function onConfirm() {
Fast.api.ajax({
url: `shopro/coupon/send/id/${state.id}`,
type: 'POST',
data: {
user_ids: state.ids
},
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
pagination,
onChangeFilter,
onSelect,
onSelectAll,
onConfirm
}
}
}
createApp('select', select);
},
};
return Controller;
});

View File

@@ -0,0 +1,62 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const index = {
setup() {
const { proxy } = getCurrentInstance();
const form = reactive({
model: {},
rules: {
name: [{ required: true, message: '请输入系统名称', trigger: 'blur' }],
logo: [{ required: true, message: '请选择公众号Logo', trigger: 'blur' }],
qrcode: [{ required: true, message: '请选择公众号二维码', trigger: 'blur' }],
app_id: [{ required: true, message: '请输入开发者AppId', trigger: 'blur' }],
secret: [{ required: true, message: '请输入开发者AppSecret', trigger: 'blur' }],
token: [{ required: true, message: '请输入令牌(Token)', trigger: 'blur' }],
aes_key: [{ required: true, message: '请输入消息加解密密钥', trigger: 'blur' }],
},
})
function getData() {
Fast.api.ajax({
url: 'shopro/wechat/config',
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: 'shopro/wechat/config',
type: 'POST',
data: form.model,
}, function (ret, res) {
}, function (ret, res) { })
}
});
}
onMounted(() => {
getData()
})
return {
onClipboard,
form,
getData,
onConfirm,
}
}
}
createApp('index', index);
},
};
return Controller;
});

View File

@@ -0,0 +1,196 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
type: 'news'
})
function getData() {
Fast.api.ajax({
url: 'shopro/wechat/material',
type: 'GET',
data: {
type: state.type,
page: pagination.page,
list_rows: pagination.list_rows,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeTab() {
state.data = []
pagination.page = 1
getData()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onAdd() {
Fast.api.open(`shopro/wechat/material/add?type=add&materialType=${state.type}`, "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/wechat/material/edit?type=edit&materialType=${state.type}&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/wechat/material/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeTab,
pagination,
onAdd,
onEdit,
onDelete
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
materialType: new URLSearchParams(location.search).get('materialType'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
type: state.materialType,
content: ''
},
rules: {
content: [{ required: true, message: '请输入内容', trigger: 'blur' }],
'content.title': [{ required: true, message: '请输入标题', trigger: 'blur' }],
'content.url': [{ required: true, message: '请输入链接地址', trigger: 'blur' }],
'content.image': [{ required: true, message: '请选择图片', trigger: 'blur' }],
'content.description': [{ required: true, message: '请输入描述', trigger: 'blur' }],
},
})
// 初始化数据
if (form.model.type == 'text') {
form.model.content = ''
} else if (form.model.type == 'link') {
form.model.content = {
title: '',
url: '',
image: '',
description: ''
}
}
function getDetail() {
Fast.api.ajax({
url: `shopro/wechat/material/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
return false
}, function (ret, res) { })
}
const linkPopover = reactive({
flag: false,
form: {
model: {
text: '',
href: '',
},
rules: {
text: [{ required: true, message: '请输入文本内容', trigger: 'blur' }],
href: [{ required: true, message: '请输入链接地址', trigger: 'blur' }],
},
},
});
function onConfirmLinkPopover() {
proxy.$refs['linkFormRef'].validate((valid) => {
if (valid) {
form.model.content += `<a href="${linkPopover.form.model.href}" target="_blank">${linkPopover.form.model.text}</a>`;
onCancelLinkPopover();
}
});
}
function onCancelLinkPopover() {
linkPopover.flag = false;
linkPopover.form.model = {
text: '',
href: '',
};
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/wechat/material/add' : `shopro/wechat/material/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
linkPopover,
onCancelLinkPopover,
onConfirmLinkPopover,
onConfirm
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,466 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
current: [],
data: [],
order: '',
sort: '',
})
function getData() {
Fast.api.ajax({
url: 'shopro/wechat/menu',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
},
}, function (ret, res) {
state.current = res.data.current
state.data = res.data.list.data
pagination.total = res.data.list.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
function onAdd() {
Fast.api.open(`shopro/wechat/menu/add?type=add`, "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/wechat/menu/edit?type=edit&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/wechat/menu/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onPublish(id) {
Fast.api.ajax({
url: `shopro/wechat/menu/publish/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onCopy(id) {
Fast.api.ajax({
url: `shopro/wechat/menu/copy/id/${id}`,
type: 'POST',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onChangeSort,
pagination,
onAdd,
onEdit,
onDelete,
onPublish,
onCopy,
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, ref, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
id: new URLSearchParams(location.search).get('id'),
rightShow: false,
selectLevel: null,
selectedIndex1: null,
selectedIndex2: null,
right: [],
})
const defaultSubButton = {
name: '未命名',
type: 'view',
selected: true,
show: true,
url: '',
appid: '',
pagepath: '',
sub_button: [],
media_type: 'news',
media_id: '',
};
const form = reactive({
model: {
name: '',
rules: []
},
rules: {
name: [{ required: true, message: '请输入菜单名称', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/wechat/menu/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
initData();
return false
}, function (ret, res) { })
}
function initData() {
form.model.rules.forEach((d) => {
loopData(d);
});
function loopData(d) {
for (var key in defaultSubButton) {
if (!d[key]) {
d[key] = JSON.parse(JSON.stringify(defaultSubButton))[key];
}
d.selected = false;
d.show = false;
}
if (d.type == 'click') {
d.media_type = d.key?.split('|')[0];
d.media_id = d.key?.split('|')[1];
}
if (d.sub_button && d.sub_button.length > 0) {
d.sub_button.forEach((s) => {
loopData(s);
});
}
}
}
function onAddMenu(index, level) {
//右侧显示
state.rightShow = true;
state.selectLevel = level;
// 添加level2的数据
if (index != null) {
state.selectedIndex1 = index;
form.model.rules.forEach((i) => {
i.selected = false;
if (i.sub_button) {
i.sub_button.forEach((j) => {
j.selected = false;
});
}
});
form.model.rules[index].sub_button.push(JSON.parse(JSON.stringify(defaultSubButton)));
state.right = form.model.rules[index].sub_button[form.model.rules[index].sub_button.length - 1];
state.selectedIndex2 = form.model.rules[index].sub_button.length - 1;
} else {
// 添加level1的数据 所有的level1不显示
form.model.rules.forEach((i) => {
i.selected = false;
i.show = false;
});
form.model.rules.push(JSON.parse(JSON.stringify(defaultSubButton)));
state.selectedIndex1 = form.model.rules.length - 1;
state.right = form.model.rules[form.model.rules.length - 1];
}
}
function onEditMenu(index1, index2) {
state.selectedIndex1 = index1;
state.selectedIndex2 = index2;
state.rightShow = true;
form.model.rules.forEach((i) => {
i.selected = false;
i.show = false;
if (i.sub_button) {
i.sub_button.forEach((j) => {
j.selected = false;
});
}
});
form.model.rules[index1].show = true;
if (index2 == null) {
state.selectLevel = 1;
form.model.rules[index1].selected = true;
form.model.rules[index1].show = true;
state.right = form.model.rules[index1];
} else {
state.selectLevel = 2;
form.model.rules[index1].sub_button[index2].selected = true;
state.right = form.model.rules[index1].sub_button[index2];
}
getMaterialSelect()
}
function onDeleteMenu() {
if (state.selectedIndex2 != null) {
form.model.rules[state.selectedIndex1].sub_button.splice(state.selectedIndex2, 1);
if (form.model.rules[state.selectedIndex1].sub_button.length > 0) {
if (state.selectedIndex2 == 0) {
form.model.rules[state.selectedIndex1].sub_button[0].selected = true;
state.right = menuData[state.selectedIndex1].sub_button[0];
} else {
form.model.rules[state.selectedIndex1].sub_button[state.selectedIndex2 - 1].selected = true;
state.right = form.model.rules[state.selectedIndex1].sub_button[state.selectedIndex2 - 1];
state.selectedIndex2--;
}
} else {
state.right = {};
state.rightShow = false;
}
} else {
form.model.rules.splice(state.selectedIndex1, 1);
if (form.model.rules.length > 0) {
if (state.selectedIndex1 == 0) {
form.model.rules[0].selected = true;
form.model.rules[0].show = true;
state.right = form.model.rules[0];
} else {
form.model.rules[state.selectedIndex1 - 1].selected = true;
form.model.rules[state.selectedIndex1 - 1].show = true;
state.right = form.model.rules[state.selectedIndex1 - 1];
state.selectedIndex1--;
}
} else {
state.right = {};
state.rightShow = false;
}
}
}
function onSelectUrl() {
Fast.api.open("shopro/data/page/select", "选择链接", {
callback(data) {
state.right.url = data.fullPath.url;
if (state.right.type == 'miniprogram') {
state.right.appid = data.fullPath.appid;
state.right.pagepath = data.fullPath.pagepath;
}
}
})
}
function onChangeType() {
if (state.right.type == 'click') {
getMaterialSelect();
}
}
function onChangeMediaType() {
material.pagination.page = 1
getMaterialSelect()
}
const material = reactive({
select: [],
pagination: {
page: 1,
list_rows: 10,
total: 0,
}
})
function getMaterialSelect() {
Fast.api.ajax({
url: 'shopro/wechat/material/select',
type: 'GET',
data: {
type: state.right.media_type,
page: material.pagination.page,
list_rows: material.pagination.list_rows,
},
}, function (ret, res) {
material.select = initMaterialData(res.data.data, state.right.media_type)
material.pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function initMaterialData(data, type) {
let options = [];
if (type == 'news') {
data.forEach((i) => {
i.content.news_item.forEach((e) => {
options.push({
media_id: i.media_id,
title: e.title,
thumb_url: e.thumb_url,
type,
});
});
});
} else if (type == 'image') {
data.forEach((i) => {
options.push({
media_id: i.media_id,
title: i.name,
thumb_url: i.url,
type,
});
});
} else if (type == 'video') {
data.forEach((i) => {
options.push({
media_id: i.media_id,
title: i.name,
thumb_url: i.cover_url,
type,
});
});
} else if (type == 'voice') {
data.forEach((i) => {
options.push({
media_id: i.media_id,
title: i.name,
thumb_url: '',
type,
});
});
} else if (type == 'text') {
data.forEach((i) => {
options.push({
media_id: i.id,
title: i.content,
thumb_url: i.content,
type,
});
});
} else if (type == 'link') {
data.forEach((i) => {
options.push({
media_id: i.id,
title: i.content.title,
thumb_url: i.content.image,
description: i.content.description,
type,
});
});
}
return options;
}
function formatData() {
// 不同类型包含的数据组
const view = ['name', 'type', 'url', 'sub_button'];
const miniprogram = ['name', 'type', 'url', 'appid', 'pagepath', 'sub_button'];
const click = ['name', 'type', 'media_type', 'media_id', 'sub_button'];
const data = JSON.parse(JSON.stringify(form.model.rules));
data.forEach((d) => {
loopData(d);
});
function loopData(d) {
if (d.type == 'view') {
for (let j in d) {
if (!view.includes(j)) delete d[j];
}
}
if (d.type == 'miniprogram') {
for (let j in d) {
if (!miniprogram.includes(j)) delete d[j];
}
}
if (d.type == 'click') {
for (let j in d) {
if (!click.includes(j)) delete d[j];
}
d.key = d.media_type + '|' + d.media_id;
delete d.media_type;
delete d.media_id;
}
if (d.sub_button && d.sub_button.length > 0) {
for (let j in d) {
if (j != 'name' && j != 'sub_button') delete d[j];
}
d.sub_button.forEach((s) => {
loopData(s);
});
} else {
delete d.sub_button;
}
}
return data;
}
function onConfirm(data = {}) {
let submitForm = { name: form.model.name, rules: formatData(), ...data };
// proxy.$refs['formRef'].validate((valid) => {
// if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/wechat/menu/add' : `shopro/wechat/menu/edit/id/${state.id}`,
type: 'POST',
data: submitForm,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
// }
// });
}
function onPublish() {
onConfirm({ publish: 1 })
}
onMounted(() => {
state.type == 'edit' && getDetail()
})
return {
state,
form,
onAddMenu,
onEditMenu,
onDeleteMenu,
onSelectUrl,
onChangeType,
onChangeMediaType,
material,
getMaterialSelect,
onConfirm,
onPublish
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,270 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
group: 'keywords',
})
function getData() {
Fast.api.ajax({
url: 'shopro/wechat/reply',
type: 'GET',
data: {
group: state.group,
},
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
function onAdd() {
Fast.api.open(`shopro/wechat/reply/add?type=add&group=${state.group}`, "添加", {
callback() {
getData()
}
})
}
function onEdit(id) {
Fast.api.open(`shopro/wechat/reply/edit?type=edit&group=${state.group}&id=${id}`, "编辑", {
callback() {
getData()
}
})
}
function onDelete(id) {
Fast.api.ajax({
url: `shopro/wechat/reply/delete/id/${id}`,
type: 'DELETE',
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
function onChangeStatus(item) {
Fast.api.ajax({
url: `shopro/wechat/reply/edit/id/${item.id}`,
type: 'POST',
data: {
status: item.status,
},
}, function (ret, res) {
getData()
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
getData,
onAdd,
onEdit,
onDelete,
onChangeStatus,
}
}
}
createApp('index', index);
},
add: () => {
Controller.form();
},
edit: () => {
Controller.form();
},
form: () => {
const { reactive, ref, onMounted, getCurrentInstance } = Vue
const addEdit = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
type: new URLSearchParams(location.search).get('type'),
group: new URLSearchParams(location.search).get('group'),
id: new URLSearchParams(location.search).get('id')
})
const form = reactive({
model: {
group: state.group,
keywords: [],
type: 'news',
content: '1',
status: 'enable',
},
rules: {
keywords: [{ required: true, message: '请输入关键字', trigger: 'blur' }],
content: [{ required: true, message: '请选择回复内容', trigger: 'blur' }],
},
})
function getDetail() {
Fast.api.ajax({
url: `shopro/wechat/reply/detail/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
form.model = res.data;
getMaterialSelect()
return false
}, function (ret, res) { })
}
const keywords = ref('')
function onAddKeywords(val) {
if (val.trim()) {
if (form.model.keywords.indexOf(val.trim()) == -1) {
form.model.keywords.push(val.trim());
keywords.value = '';
} else {
ElMessage({
message: '已存在不可再次添加.',
type: 'warning',
});
}
} else {
ElMessage({
message: '请输入关键字.',
type: 'warning',
});
}
}
function onDeleteKeywords(index) {
form.model.keywords.splice(index, 1);
}
function onChangeType() {
material.pagination.page = 1
getMaterialSelect()
}
const material = reactive({
select: [],
pagination: {
page: 1,
list_rows: 10,
total: 0,
}
})
function getMaterialSelect() {
Fast.api.ajax({
url: 'shopro/wechat/material/select',
type: 'GET',
data: {
type: form.model.type,
page: material.pagination.page,
list_rows: material.pagination.list_rows,
},
}, function (ret, res) {
material.select = initMaterialData(res.data.data,form.model.type)
material.pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function initMaterialData(data, type) {
let options = [];
if (type == 'news') {
data.forEach((i) => {
i.content.news_item.forEach((e) => {
options.push({
media_id: i.media_id,
title: e.title,
thumb_url: e.thumb_url,
type,
});
});
});
} else if (type == 'image') {
data.forEach((i) => {
options.push({
media_id: i.media_id,
title: i.name,
thumb_url: i.url,
type,
});
});
} else if (type == 'video') {
data.forEach((i) => {
options.push({
media_id: i.media_id,
title: i.name,
thumb_url: i.cover_url,
type,
});
});
} else if (type == 'voice') {
data.forEach((i) => {
options.push({
media_id: i.media_id,
title: i.name,
thumb_url: '',
type,
});
});
} else if (type == 'text') {
data.forEach((i) => {
options.push({
media_id: i.id,
title: i.content,
thumb_url: i.content,
type,
});
});
} else if (type == 'link') {
data.forEach((i) => {
options.push({
media_id: i.id,
title: i.content.title,
thumb_url: i.content.image,
description: i.content.description,
type,
});
});
}
return options;
}
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: state.type == 'add' ? 'shopro/wechat/reply/add' : `shopro/wechat/reply/edit/id/${state.id}`,
type: 'POST',
data: form.model,
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
onMounted(() => {
state.type == 'add' && getMaterialSelect()
state.type == 'edit' && getDetail()
})
return {
state,
form,
keywords,
onAddKeywords,
onDeleteKeywords,
onChangeType,
material,
getMaterialSelect,
onConfirm
}
}
}
createApp('addEdit', addEdit);
}
};
return Controller;
});

View File

@@ -0,0 +1,291 @@
define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefined, Backend, Table, Form) {
var Controller = {
index: () => {
const { reactive, onMounted } = Vue
const index = {
setup() {
const state = reactive({
data: [],
order: '',
sort: '',
filter: {
drawer: false,
data: {
status: 'all',
user: { field: 'user_id', value: '' },
withdraw_type: 'all',
createtime: [],
updatetime: [],
},
tools: {
user: {
type: 'tinputprepend',
label: '用户信息',
placeholder: '请输入查询内容',
value: {
field: 'user_id',
value: '',
},
options: {
data: [{
label: '用户ID',
value: 'user_id',
},
{
label: '用户昵称',
value: 'user.nickname',
},
{
label: '用户手机号',
value: 'user.mobile',
}]
}
},
withdraw_type: {
type: 'tselect',
label: '提现方式',
value: '',
options: {
data: [{
label: '全部',
value: 'all',
},
{
label: '支付宝账户',
value: 'alipay',
},
{
label: '微信零钱',
value: 'wechat',
},
{
label: '银行卡',
value: 'bank',
}]
},
},
createtime: {
type: 'tdatetimerange',
label: '下单时间',
value: [],
},
updatetime: {
type: 'tdatetimerange',
label: '上次操作时间',
value: [],
},
},
condition: {},
},
statusStyle: {
'-1': 'sa-color--danger',
0: 'sa-color--info',
1: 'sa-color--warning',
2: 'sa-color--success',
}
})
const type = reactive({
data: {
status: [{
name: '全部',
type: 'all',
},
{
name: '待审核',
type: '0',
},
{
name: '处理中',
type: '1',
},
{
name: '已处理',
type: '2',
},
{
name: '已拒绝',
type: '-1',
},],
}
})
function getData() {
let tempSearch = JSON.parse(JSON.stringify(state.filter.data));
let search = composeFilter(tempSearch, {
'user.nickname': 'like',
'user.mobile': 'like',
createtime: 'range',
updatetime: 'range',
});
Fast.api.ajax({
url: 'shopro/withdraw',
type: 'GET',
data: {
page: pagination.page,
list_rows: pagination.list_rows,
order: state.order,
sort: state.sort,
...search,
},
}, function (ret, res) {
state.data = res.data.data
pagination.total = res.data.total
return false
}, function (ret, res) { })
}
function onChangeSort({ prop, order }) {
state.order = order == 'ascending' ? 'asc' : 'desc';
state.sort = prop;
getData();
}
function onOpenFilter() {
state.filter.drawer = true
}
function onChangeFilter() {
pagination.page = 1
getData()
state.filter.drawer && (state.filter.drawer = false)
}
function onChangeTab() {
pagination.page = 1
getData()
}
const pagination = reactive({
page: 1,
list_rows: 10,
total: 0,
})
const handlePopover = reactive({
flag: {}
})
function onAgree(id, index, type) {
handlePopover.flag[index] = false;
Fast.api.ajax({
url: `shopro/withdraw/handle/id/${id}`,
type: 'POST',
data: {
action: type,
},
}, function (ret, res) {
getData();
}, function (ret, res) { })
}
function onRefuse(id) {
Fast.api.open(`shopro/withdraw/handle/id/${id}?id=${id}`, "拒绝", {
callback() {
getData()
}
})
}
function onLog(id) {
Fast.api.open(`shopro/withdraw/log/id/${id}?id=${id}`, "日志")
}
onMounted(() => {
getData()
})
return {
onClipboard,
state,
type,
getData,
onChangeSort,
onOpenFilter,
onChangeFilter,
onChangeTab,
pagination,
handlePopover,
onAgree,
onRefuse,
onLog,
}
}
}
createApp('index', index);
},
handle: () => {
const { reactive, getCurrentInstance } = Vue
const handle = {
setup() {
const { proxy } = getCurrentInstance();
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
})
const form = reactive({
model: {
action: 'refuse',
refuse_msg: '',
},
rules: {
refuse_msg: [{ required: true, message: '请输入拒绝理由', trigger: 'blur' }],
},
});
function onConfirm() {
proxy.$refs['formRef'].validate((valid) => {
if (valid) {
Fast.api.ajax({
url: `shopro/withdraw/handle/id/${state.id}`,
type: 'POST',
data: form.model
}, function (ret, res) {
Fast.api.close()
}, function (ret, res) { })
}
});
}
return {
state,
form,
onConfirm,
}
}
}
createApp('handle', handle);
},
log: () => {
const { reactive, onMounted } = Vue
const log = {
setup() {
const state = reactive({
id: new URLSearchParams(location.search).get('id'),
data: [],
})
function getData() {
Fast.api.ajax({
url: `shopro/withdraw/log/id/${state.id}`,
type: 'GET',
}, function (ret, res) {
state.data = res.data
return false
}, function (ret, res) { })
}
onMounted(() => {
getData()
})
return {
state,
}
}
}
createApp('log', log);
},
};
return Controller;
});

View File

@@ -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;
});

View File

@@ -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(/(&|&amp;)nbsp;/g, '&nbsp;');
var caret = row.haschild == 1 || row.ismenu == 1 ? '<i class="fa fa-caret-right"></i>' : '';
value = value.indexOf("&nbsp;") > -1 ? value.replace(/(.*)&nbsp;/, "$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;
});

View File

@@ -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;
});