init
- 框架初始化 - 安装插件 - 修复PHP8.4报错
This commit is contained in:
171
public/assets/js/addons.js
Normal file
171
public/assets/js/addons.js
Normal file
@@ -0,0 +1,171 @@
|
||||
define([], function () {
|
||||
if (Config.modulename == 'admin' && Config.controllername == 'index' && Config.actionname == 'index') {
|
||||
require.config({
|
||||
paths: {
|
||||
'vue3': "../addons/shopro/libs/vue",
|
||||
'vue': "../addons/shopro/libs/vue.amd",
|
||||
'text': "../addons/shopro/libs/require-text",
|
||||
'SaChat': '../addons/shopro/chat/index',
|
||||
'ElementPlus': '../addons/shopro/libs/element-plus/index',
|
||||
'ElementPlusIconsVue3': "../addons/shopro/libs/element-plus/icons-vue",
|
||||
'ElementPlusIconsVue': '../addons/shopro/libs/element-plus/icons-vue.amd',
|
||||
'io': '../addons/shopro/libs/socket.io',
|
||||
},
|
||||
shim: {
|
||||
'ElementPlus': {
|
||||
deps: ['css!../addons/shopro/libs/element-plus/index.css']
|
||||
},
|
||||
},
|
||||
});
|
||||
require(['vue3', 'ElementPlusIconsVue3'], function (Vue3, ElementPlusIconsVue3) {
|
||||
require(['vue', 'jquery', 'SaChat', 'text!../addons/shopro/chat/index.html', 'ElementPlus', 'ElementPlusIconsVue', 'io'], function (Vue, $, SaChat, SaChatTemplate, ElementPlus, ElementPlusIconsVue, io) {
|
||||
if (Config.dark_type != 'none') {
|
||||
SaChatTemplate = SaChatTemplate.replaceAll('__DARK__', `<link rel="stylesheet" href="__CDN__/assets/addons/shopro/css/dark.css?v={$site.version|htmlentities}" />`)
|
||||
}
|
||||
|
||||
SaChatTemplate = SaChatTemplate.replaceAll('__DARK__', ``)
|
||||
SaChatTemplate = SaChatTemplate.replaceAll('__CDN__', Config.__CDN__)
|
||||
|
||||
Fast.api.ajax({
|
||||
url: 'shopro/chat/index/init',
|
||||
loading: false,
|
||||
type: 'GET'
|
||||
}, function (ret, res) {
|
||||
$("body").append(`<div id="SaChatTemplateContainer"></div>
|
||||
<div id="SaChatWrap"><sa-chat></sa-chat></div>`);
|
||||
|
||||
$("#SaChatTemplateContainer").append(SaChatTemplate);
|
||||
|
||||
const { createApp } = Vue
|
||||
const app = createApp({})
|
||||
|
||||
app.use(ElementPlus)
|
||||
for (const [key, component] of Object.entries(ElementPlusIconsVue)) {
|
||||
app.component(key, component)
|
||||
}
|
||||
|
||||
app.component('sa-chat', SaChat)
|
||||
app.mount(`#SaChatWrap`)
|
||||
return false;
|
||||
}, function (ret, res) {
|
||||
if (res.msg == '') {
|
||||
return false;
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
require.config({
|
||||
paths: {
|
||||
'summernote': '../addons/summernote/lang/summernote-zh-CN.min'
|
||||
},
|
||||
shim: {
|
||||
'summernote': ['../addons/summernote/js/summernote.min', 'css!../addons/summernote/css/summernote.min.css'],
|
||||
}
|
||||
});
|
||||
require(['form', 'upload'], function (Form, Upload) {
|
||||
var _bindevent = Form.events.bindevent;
|
||||
Form.events.bindevent = function (form) {
|
||||
_bindevent.apply(this, [form]);
|
||||
try {
|
||||
//绑定summernote事件
|
||||
if ($(Config.summernote.classname || '.editor', form).length > 0) {
|
||||
var selectUrl = typeof Config !== 'undefined' && Config.modulename === 'index' ? 'user/attachment' : 'general/attachment/select';
|
||||
require(['summernote'], function () {
|
||||
var imageButton = function (context) {
|
||||
var ui = $.summernote.ui;
|
||||
var button = ui.button({
|
||||
contents: '<i class="fa fa-file-image-o"/>',
|
||||
tooltip: __('Choose'),
|
||||
click: function () {
|
||||
parent.Fast.api.open(selectUrl + "?element_id=&multiple=true&mimetype=image/", __('Choose'), {
|
||||
callback: function (data) {
|
||||
var urlArr = data.url.split(/\,/);
|
||||
$.each(urlArr, function () {
|
||||
var url = Fast.api.cdnurl(this, true);
|
||||
context.invoke('editor.insertImage', url);
|
||||
});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return button.render();
|
||||
};
|
||||
var attachmentButton = function (context) {
|
||||
var ui = $.summernote.ui;
|
||||
var button = ui.button({
|
||||
contents: '<i class="fa fa-file"/>',
|
||||
tooltip: __('Choose'),
|
||||
click: function () {
|
||||
parent.Fast.api.open(selectUrl + "?element_id=&multiple=true&mimetype=*", __('Choose'), {
|
||||
callback: function (data) {
|
||||
var urlArr = data.url.split(/\,/);
|
||||
$.each(urlArr, function () {
|
||||
var url = Fast.api.cdnurl(this, true);
|
||||
var node = $("<a href='" + url + "'>" + url + "</a>");
|
||||
context.invoke('insertNode', node[0]);
|
||||
});
|
||||
}
|
||||
});
|
||||
return false;
|
||||
}
|
||||
});
|
||||
return button.render();
|
||||
};
|
||||
|
||||
$(Config.summernote.classname || '.editor', form).each(function () {
|
||||
$(this).summernote($.extend(true, {}, {
|
||||
height: isNaN(Config.summernote.height) ? null : parseInt(Config.summernote.height),
|
||||
minHeight: parseInt(Config.summernote.minHeight || 250),
|
||||
toolbar: Config.summernote.toolbar,
|
||||
followingToolbar: parseInt(Config.summernote.followingToolbar),
|
||||
placeholder: Config.summernote.placeholder || '',
|
||||
airMode: parseInt(Config.summernote.airMode) || false,
|
||||
lang: 'zh-CN',
|
||||
fontNames: [
|
||||
'Arial', 'Arial Black', 'Serif', 'Sans', 'Courier',
|
||||
'Courier New', 'Comic Sans MS', 'Helvetica', 'Impact', 'Lucida Grande',
|
||||
"Open Sans", "Hiragino Sans GB", "Microsoft YaHei",
|
||||
'微软雅黑', '宋体', '黑体', '仿宋', '楷体', '幼圆',
|
||||
],
|
||||
fontNamesIgnoreCheck: [
|
||||
"Open Sans", "Microsoft YaHei",
|
||||
'微软雅黑', '宋体', '黑体', '仿宋', '楷体', '幼圆'
|
||||
],
|
||||
buttons: {
|
||||
image: imageButton,
|
||||
attachment: attachmentButton,
|
||||
},
|
||||
dialogsInBody: true,
|
||||
callbacks: {
|
||||
onChange: function (contents) {
|
||||
$(this).val(contents);
|
||||
$(this).trigger('change');
|
||||
},
|
||||
onInit: function () {
|
||||
},
|
||||
onImageUpload: function (files) {
|
||||
var that = this;
|
||||
//依次上传图片
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
Upload.api.send(files[i], function (data) {
|
||||
var url = Fast.api.cdnurl(data.url, true);
|
||||
$(that).summernote("insertImage", url, 'filename');
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}, $(this).data("summernote-options") || {}));
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
});
|
||||
|
||||
});
|
||||
893
public/assets/js/adminlte.js
Normal file
893
public/assets/js/adminlte.js
Normal file
@@ -0,0 +1,893 @@
|
||||
/*! AdminLTE app.js
|
||||
* ================
|
||||
* Main JS application file for AdminLTE v2. This file
|
||||
* should be included in all pages. It controls some layout
|
||||
* options and implements exclusive AdminLTE plugins.
|
||||
*
|
||||
* @Author Almsaeed Studio
|
||||
* @Support <http://www.almsaeedstudio.com>
|
||||
* @Email <abdullah@almsaeedstudio.com>
|
||||
* @version 2.3.8
|
||||
* @license MIT <http://opensource.org/licenses/MIT>
|
||||
*/
|
||||
|
||||
//Make sure jQuery has been loaded before app.js
|
||||
if (typeof jQuery === "undefined") {
|
||||
throw new Error("AdminLTE requires jQuery");
|
||||
}
|
||||
|
||||
/* AdminLTE
|
||||
*
|
||||
* @type Object
|
||||
* @description $.AdminLTE is the main object for the template's app.
|
||||
* It's used for implementing functions and options related
|
||||
* to the template. Keeping everything wrapped in an object
|
||||
* prevents conflict with other plugins and is a better
|
||||
* way to organize our code.
|
||||
*/
|
||||
$.AdminLTE = {};
|
||||
|
||||
/* --------------------
|
||||
* - AdminLTE Options -
|
||||
* --------------------
|
||||
* Modify these options to suit your implementation
|
||||
*/
|
||||
$.AdminLTE.options = {
|
||||
//Add slimscroll to navbar menus
|
||||
//This requires you to load the slimscroll plugin
|
||||
//in every page before app.js
|
||||
navbarMenuSlimscroll: true,
|
||||
navbarMenuSlimscrollWidth: "3px", //The width of the scroll bar
|
||||
navbarMenuHeight: "200px", //The height of the inner menu
|
||||
//General animation speed for JS animated elements such as box collapse/expand and
|
||||
//sidebar treeview slide up/down. This options accepts an integer as milliseconds,
|
||||
//'fast', 'normal', or 'slow'
|
||||
animationSpeed: 300,
|
||||
//Sidebar push menu toggle button selector
|
||||
sidebarToggleSelector: "[data-toggle='offcanvas']",
|
||||
//Activate sidebar push menu
|
||||
sidebarPushMenu: true,
|
||||
//Activate sidebar slimscroll if the fixed layout is set (requires SlimScroll Plugin)
|
||||
sidebarSlimScroll: true,
|
||||
//Enable sidebar expand on hover effect for sidebar mini
|
||||
//This option is forced to true if both the fixed layout and sidebar mini
|
||||
//are used together
|
||||
sidebarExpandOnHover: false,
|
||||
//BoxRefresh Plugin
|
||||
enableBoxRefresh: true,
|
||||
//Bootstrap.js tooltip
|
||||
enableBSToppltip: true,
|
||||
BSTooltipSelector: "[data-toggle='tooltip']",
|
||||
//Enable Fast Click. Fastclick.js creates a more
|
||||
//native touch experience with touch devices. If you
|
||||
//choose to enable the plugin, make sure you load the script
|
||||
//before AdminLTE's app.js
|
||||
enableFastclick: false,
|
||||
//Control Sidebar Tree views
|
||||
enableControlTreeView: true,
|
||||
//Control Sidebar Options
|
||||
enableControlSidebar: true,
|
||||
controlSidebarOptions: {
|
||||
//Which button should trigger the open/close event
|
||||
toggleBtnSelector: "[data-toggle='control-sidebar']",
|
||||
//The sidebar selector
|
||||
selector: ".control-sidebar",
|
||||
//Enable slide over content
|
||||
slide: true
|
||||
},
|
||||
//Box Widget Plugin. Enable this plugin
|
||||
//to allow boxes to be collapsed and/or removed
|
||||
enableBoxWidget: true,
|
||||
//Box Widget plugin options
|
||||
boxWidgetOptions: {
|
||||
boxWidgetIcons: {
|
||||
//Collapse icon
|
||||
collapse: 'fa-minus',
|
||||
//Open icon
|
||||
open: 'fa-plus',
|
||||
//Remove icon
|
||||
remove: 'fa-times'
|
||||
},
|
||||
boxWidgetSelectors: {
|
||||
//Remove button selector
|
||||
remove: '[data-widget="remove"]',
|
||||
//Collapse button selector
|
||||
collapse: '[data-widget="collapse"]'
|
||||
}
|
||||
},
|
||||
//Direct Chat plugin options
|
||||
directChat: {
|
||||
//Enable direct chat by default
|
||||
enable: true,
|
||||
//The button to open and close the chat contacts pane
|
||||
contactToggleSelector: '[data-widget="chat-pane-toggle"]'
|
||||
},
|
||||
//Define the set of colors to use globally around the website
|
||||
colors: {
|
||||
lightBlue: "#3c8dbc",
|
||||
red: "#f56954",
|
||||
green: "#00a65a",
|
||||
aqua: "#00c0ef",
|
||||
yellow: "#f39c12",
|
||||
blue: "#0073b7",
|
||||
navy: "#001F3F",
|
||||
teal: "#39CCCC",
|
||||
olive: "#3D9970",
|
||||
lime: "#01FF70",
|
||||
orange: "#FF851B",
|
||||
fuchsia: "#F012BE",
|
||||
purple: "#8E24AA",
|
||||
maroon: "#D81B60",
|
||||
black: "#222222",
|
||||
gray: "#d2d6de"
|
||||
},
|
||||
//The standard screen sizes that bootstrap uses.
|
||||
//If you change these in the variables.less file, change
|
||||
//them here too.
|
||||
screenSizes: {
|
||||
xs: 480,
|
||||
sm: 768,
|
||||
md: 992,
|
||||
lg: 1200
|
||||
}
|
||||
};
|
||||
|
||||
/* ------------------
|
||||
* - Implementation -
|
||||
* ------------------
|
||||
* The next block of code implements AdminLTE's
|
||||
* functions and plugins as specified by the
|
||||
* options above.
|
||||
*/
|
||||
$(function () {
|
||||
"use strict";
|
||||
|
||||
//Fix for IE page transitions
|
||||
$("body").removeClass("hold-transition");
|
||||
|
||||
//Extend options if external options exist
|
||||
if (typeof AdminLTEOptions !== "undefined") {
|
||||
$.extend(true,
|
||||
$.AdminLTE.options,
|
||||
AdminLTEOptions);
|
||||
}
|
||||
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
$.AdminLTE.options.sidebarSlimScroll = false;
|
||||
$(".main-sidebar").css({height: ($(window).height() - $(".main-header").height()) + "px", overflow: "scroll"});
|
||||
}
|
||||
|
||||
//Easy access to options
|
||||
var o = $.AdminLTE.options;
|
||||
|
||||
//Set up the object
|
||||
_init();
|
||||
|
||||
//Activate the layout maker
|
||||
$.AdminLTE.layout.activate();
|
||||
|
||||
//Enable sidebar tree view controls
|
||||
if (o.enableControlTreeView) {
|
||||
$.AdminLTE.tree('.sidebar');
|
||||
}
|
||||
|
||||
//Enable control sidebar
|
||||
if (o.enableControlSidebar) {
|
||||
$.AdminLTE.controlSidebar.activate();
|
||||
}
|
||||
|
||||
//Add slimscroll to navbar dropdown
|
||||
if (o.navbarMenuSlimscroll && typeof $.fn.slimscroll != 'undefined') {
|
||||
$(".navbar .menu").slimscroll({
|
||||
height: o.navbarMenuHeight,
|
||||
alwaysVisible: false,
|
||||
size: o.navbarMenuSlimscrollWidth
|
||||
}).css("width", "100%");
|
||||
}
|
||||
|
||||
//Activate sidebar push menu
|
||||
if (o.sidebarPushMenu) {
|
||||
$.AdminLTE.pushMenu.activate(o.sidebarToggleSelector);
|
||||
}
|
||||
|
||||
//Activate Bootstrap tooltip
|
||||
if (o.enableBSToppltip) {
|
||||
$('body').tooltip({
|
||||
selector: o.BSTooltipSelector,
|
||||
container: 'body'
|
||||
});
|
||||
}
|
||||
|
||||
//Activate box widget
|
||||
if (o.enableBoxWidget) {
|
||||
$.AdminLTE.boxWidget.activate();
|
||||
}
|
||||
|
||||
//Activate fast click
|
||||
if (o.enableFastclick && typeof FastClick != 'undefined') {
|
||||
FastClick.attach(document.body);
|
||||
}
|
||||
|
||||
//Activate direct chat widget
|
||||
if (o.directChat.enable) {
|
||||
$(document).on('click', o.directChat.contactToggleSelector, function () {
|
||||
var box = $(this).parents('.direct-chat').first();
|
||||
box.toggleClass('direct-chat-contacts-open');
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* INITIALIZE BUTTON TOGGLE
|
||||
* ------------------------
|
||||
*/
|
||||
$('.btn-group[data-toggle="btn-toggle"]').each(function () {
|
||||
var group = $(this);
|
||||
$(this).find(".btn").on('click', function (e) {
|
||||
group.find(".btn.active").removeClass("active");
|
||||
$(this).addClass("active");
|
||||
e.preventDefault();
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
/* ----------------------------------
|
||||
* - Initialize the AdminLTE Object -
|
||||
* ----------------------------------
|
||||
* All AdminLTE functions are implemented below.
|
||||
*/
|
||||
function _init() {
|
||||
'use strict';
|
||||
/* Layout
|
||||
* ======
|
||||
* Fixes the layout height in case min-height fails.
|
||||
*
|
||||
* @type Object
|
||||
* @usage $.AdminLTE.layout.activate()
|
||||
* $.AdminLTE.layout.fix()
|
||||
* $.AdminLTE.layout.fixSidebar()
|
||||
*/
|
||||
$.AdminLTE.layout = {
|
||||
activate: function () {
|
||||
var _this = this;
|
||||
//_this.fix();
|
||||
_this.fixSidebar();
|
||||
//$('body, html, .wrapper').css('height', 'auto');
|
||||
$(window, ".wrapper").resize(function () {
|
||||
//_this.fix();
|
||||
_this.fixSidebar();
|
||||
});
|
||||
},
|
||||
fix: function () {
|
||||
// Remove overflow from .wrapper if layout-boxed exists
|
||||
$(".layout-boxed > .wrapper").css('overflow', 'hidden');
|
||||
//Get window height and the wrapper height
|
||||
var footer_height = $('.main-footer').outerHeight() || 0;
|
||||
var neg = $('.main-header').outerHeight() + footer_height;
|
||||
var window_height = $(window).height();
|
||||
var sidebar_height = $(".sidebar").height() || 0;
|
||||
//Set the min-height of the content and sidebar based on the
|
||||
//the height of the document.
|
||||
if ($("body").hasClass("fixed")) {
|
||||
$(".content-wrapper, .right-side").css('min-height', window_height - footer_height);
|
||||
} else {
|
||||
var postSetWidth;
|
||||
if (window_height >= sidebar_height) {
|
||||
$(".content-wrapper, .right-side").css('min-height', window_height - neg);
|
||||
postSetWidth = window_height - neg;
|
||||
} else {
|
||||
$(".content-wrapper, .right-side").css('min-height', sidebar_height);
|
||||
postSetWidth = sidebar_height;
|
||||
}
|
||||
|
||||
//Fix for the control sidebar height
|
||||
var controlSidebar = $($.AdminLTE.options.controlSidebarOptions.selector);
|
||||
if (typeof controlSidebar !== "undefined") {
|
||||
if (controlSidebar.height() > postSetWidth)
|
||||
$(".content-wrapper, .right-side").css('min-height', controlSidebar.height());
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
fixSidebar: function () {
|
||||
//Make sure the body tag has the .fixed class
|
||||
if (!$("body").hasClass("fixed")) {
|
||||
if (typeof $.fn.slimScroll != 'undefined') {
|
||||
$(".sidebar").slimScroll({destroy: true}).height("auto");
|
||||
}
|
||||
return;
|
||||
} else if (typeof $.fn.slimScroll == 'undefined' && window.console) {
|
||||
window.console.error("Error: the fixed layout requires the slimscroll plugin!");
|
||||
}
|
||||
//Enable slimscroll for fixed layout
|
||||
if ($.AdminLTE.options.sidebarSlimScroll) {
|
||||
if (typeof $.fn.slimScroll != 'undefined') {
|
||||
//Destroy if it exists
|
||||
$(".sidebar").slimScroll({destroy: true}).height("auto").css("overflow", "inherit");
|
||||
if (!$("body").hasClass('sidebar-collapse')) {
|
||||
$(".sidebar").off("mousewheel").css("margin-top", 0);
|
||||
$('.sidebar .treeview-menu').off('mousewheel').removeAttr("style");
|
||||
//Add slimscroll
|
||||
$(".sidebar").slimscroll({
|
||||
height: ($(window).height() - $(".main-header").height()) + "px",
|
||||
color: "rgba(0,0,0,0.2)",
|
||||
size: "8px"
|
||||
});
|
||||
$(".sidebar").trigger("mouseover");
|
||||
} else {
|
||||
var sidebarHeight = $(".sidebar").height();
|
||||
var maxHeight = $(window).height() - $(".main-header").height();
|
||||
var overflowHeight = sidebarHeight + $(".main-header").height() - $(window).height();
|
||||
if (overflowHeight > 0) {
|
||||
$(".sidebar").height(maxHeight);
|
||||
$(".sidebar").on("mousewheel", function (e) {
|
||||
e.preventDefault();
|
||||
if (e.originalEvent.pageX < $(".sidebar").width()) {
|
||||
var marginTop = parseInt($(".sidebar").css("margin-top").replace("px", "")) + e.originalEvent.wheelDelta;
|
||||
if (marginTop < 0 && Math.abs(marginTop) > overflowHeight) {
|
||||
marginTop = Math.min(overflowHeight, marginTop);
|
||||
marginTop = -overflowHeight;
|
||||
}
|
||||
marginTop = Math.min(0, marginTop);
|
||||
$(".sidebar").css("margin-top", marginTop);
|
||||
}
|
||||
});
|
||||
$('.sidebar .treeview-menu').on('mousewheel', function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* PushMenu()
|
||||
* ==========
|
||||
* Adds the push menu functionality to the sidebar.
|
||||
*
|
||||
* @type Function
|
||||
* @usage: $.AdminLTE.pushMenu("[data-toggle='offcanvas']")
|
||||
*/
|
||||
$.AdminLTE.pushMenu = {
|
||||
activate: function (toggleBtn) {
|
||||
//Get the screen sizes
|
||||
var screenSizes = $.AdminLTE.options.screenSizes;
|
||||
|
||||
//Enable sidebar toggle
|
||||
$(document).on('click', toggleBtn, function (e) {
|
||||
e.preventDefault();
|
||||
|
||||
//Enable sidebar push menu
|
||||
if ($(window).width() > (screenSizes.sm - 1)) {
|
||||
if ($("body").hasClass('sidebar-collapse')) {
|
||||
$("body").removeClass('sidebar-collapse').trigger('expanded.pushMenu');
|
||||
} else {
|
||||
$("body").addClass('sidebar-collapse').trigger('collapsed.pushMenu');
|
||||
}
|
||||
}
|
||||
//Handle sidebar push menu for small screens
|
||||
else {
|
||||
if ($("body").hasClass('sidebar-open')) {
|
||||
$("body").removeClass('sidebar-open').removeClass('sidebar-collapse').trigger('collapsed.pushMenu');
|
||||
} else {
|
||||
$("body").addClass('sidebar-open').trigger('expanded.pushMenu');
|
||||
}
|
||||
}
|
||||
$.AdminLTE.layout.fixSidebar();
|
||||
});
|
||||
|
||||
$(".content-wrapper").click(function () {
|
||||
//Enable hide menu when clicking on the content-wrapper on small screens
|
||||
if ($(window).width() <= (screenSizes.sm - 1) && $("body").hasClass("sidebar-open")) {
|
||||
$("body").removeClass('sidebar-open');
|
||||
}
|
||||
});
|
||||
|
||||
//Enable expand on hover for sidebar mini
|
||||
if ($.AdminLTE.options.sidebarExpandOnHover) {
|
||||
this.expandOnHover();
|
||||
}
|
||||
},
|
||||
expandOnHover: function () {
|
||||
var _this = this;
|
||||
var screenWidth = $.AdminLTE.options.screenSizes.sm - 1;
|
||||
//Expand sidebar on hover
|
||||
$('.main-sidebar').hover(function () {
|
||||
if ($.AdminLTE.options.sidebarExpandOnHover) {
|
||||
if ($('body').hasClass('sidebar-mini')
|
||||
&& $("body").hasClass('sidebar-collapse')
|
||||
&& $(window).width() > screenWidth) {
|
||||
_this.expand();
|
||||
}
|
||||
}
|
||||
}, function () {
|
||||
if ($('body').hasClass('sidebar-mini')
|
||||
&& $('body').hasClass('sidebar-expanded-on-hover')
|
||||
&& $(window).width() > screenWidth) {
|
||||
_this.collapse();
|
||||
}
|
||||
});
|
||||
},
|
||||
expand: function () {
|
||||
$("body").removeClass('sidebar-collapse').addClass('sidebar-expanded-on-hover');
|
||||
$.AdminLTE.layout.fixSidebar();
|
||||
},
|
||||
collapse: function () {
|
||||
if ($('body').hasClass('sidebar-expanded-on-hover')) {
|
||||
$('body').removeClass('sidebar-expanded-on-hover').addClass('sidebar-collapse');
|
||||
// $.AdminLTE.layout.fixSidebar();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/* Tree()
|
||||
* ======
|
||||
* Converts the sidebar into a multilevel
|
||||
* tree view menu.
|
||||
*
|
||||
* @type Function
|
||||
* @Usage: $.AdminLTE.tree('.sidebar')
|
||||
*/
|
||||
$.AdminLTE.tree = function (menu) {
|
||||
var _this = this;
|
||||
var animationSpeed = $.AdminLTE.options.animationSpeed;
|
||||
$(document).off('mouseenter', menu + ' .sidebar-menu > li')
|
||||
.on('mouseenter', menu + ' .sidebar-menu > li', function () {
|
||||
var treemenu = $(this).find("> .treeview-menu");
|
||||
if (treemenu.length > 0) {
|
||||
if ($("body").hasClass("sidebar-collapse")) {
|
||||
var liHeight = $(this).height();
|
||||
var headerHeight = $(".main-header").height();
|
||||
var maxBottomHeight = $(window).height() - ($(this).offset().top + headerHeight);
|
||||
var maxTopHeight = $(window).height() - maxBottomHeight - liHeight;
|
||||
var maxHeight = maxBottomHeight;
|
||||
if (maxBottomHeight < 300 || maxTopHeight > maxBottomHeight) {
|
||||
treemenu.css("top", "unset").css("bottom", liHeight);
|
||||
maxHeight = maxTopHeight;
|
||||
}
|
||||
treemenu.css("max-height", maxHeight).css("overflow-y", "auto");
|
||||
} else {
|
||||
treemenu.css("max-height", "inherit").css("overflow-y", "unset");
|
||||
}
|
||||
}
|
||||
});
|
||||
$(document).off('click', menu + ' li a')
|
||||
.on('click', menu + ' li a', function (e) {
|
||||
//Get the clicked link and the next element
|
||||
var $this = $(this);
|
||||
var checkElement = $this.next();
|
||||
//Check if the next element is a menu and is visible
|
||||
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible'))) {
|
||||
if ($("body").hasClass("sidebar-collapse") && $this.parent().parent().hasClass("sidebar-menu")) {
|
||||
return false;
|
||||
}
|
||||
//Close the menu
|
||||
checkElement.slideUp(animationSpeed, function () {
|
||||
checkElement.removeClass('menu-open');
|
||||
//Fix the layout in case the sidebar stretches over the height of the window
|
||||
//_this.layout.fix();
|
||||
});
|
||||
// checkElement.parent("li").removeClass("active");
|
||||
checkElement.parent("li").removeClass('treeview-open');
|
||||
}
|
||||
//If the menu is not visible
|
||||
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {
|
||||
//Get the parent menu
|
||||
var parent = $this.parents('ul').first();
|
||||
// modified by FastAdmin
|
||||
if ($(".show-submenu", menu).length == 0) {
|
||||
//Close all open menus within the parent
|
||||
var ul = parent.find('ul:visible').slideUp(animationSpeed);
|
||||
//Remove the menu-open class from the parent
|
||||
ul.removeClass('menu-open');
|
||||
parent.find('li.treeview').removeClass("treeview-open");
|
||||
}
|
||||
//Get the parent li
|
||||
var parent_li = $this.parent("li");
|
||||
|
||||
//Open the target menu and add the menu-open class
|
||||
checkElement.slideDown(animationSpeed, function () {
|
||||
//Add the class active to the parent li
|
||||
checkElement.addClass('menu-open');
|
||||
//parent.find('li.active').removeClass('active');
|
||||
//parent_li.addClass('active');
|
||||
//Fix the layout in case the sidebar stretches over the height of the window
|
||||
// _this.layout.fix();
|
||||
});
|
||||
parent_li.addClass('treeview-open');
|
||||
} else {
|
||||
if (!$this.parent().hasClass("active")) {
|
||||
// $this.parent().addClass("active");
|
||||
}
|
||||
// modified by FastAdmin
|
||||
if ($(".show-submenu", menu).length == 0 && $this.parent().parent().hasClass("sidebar-menu")) {
|
||||
$this.parent().siblings().find("ul.menu-open").slideUp();
|
||||
$this.parent().siblings("li.treeview-open").removeClass("treeview-open");
|
||||
}
|
||||
}
|
||||
//if this isn't a link, prevent the page from being redirected
|
||||
if (checkElement.is('.treeview-menu')) {
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/* ControlSidebar
|
||||
* ==============
|
||||
* Adds functionality to the right sidebar
|
||||
*
|
||||
* @type Object
|
||||
* @usage $.AdminLTE.controlSidebar.activate(options)
|
||||
*/
|
||||
$.AdminLTE.controlSidebar = {
|
||||
//instantiate the object
|
||||
activate: function () {
|
||||
//Get the object
|
||||
var _this = this;
|
||||
//Update options
|
||||
var o = $.AdminLTE.options.controlSidebarOptions;
|
||||
//Get the sidebar
|
||||
var sidebar = $(o.selector);
|
||||
//The toggle button
|
||||
var btn = $(o.toggleBtnSelector);
|
||||
|
||||
//Listen to the click event
|
||||
btn.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
//If the sidebar is not open
|
||||
if (!sidebar.hasClass('control-sidebar-open')
|
||||
&& !$('body').hasClass('control-sidebar-open')) {
|
||||
//Open the sidebar
|
||||
_this.open(sidebar, o.slide);
|
||||
} else {
|
||||
_this.close(sidebar, o.slide);
|
||||
}
|
||||
});
|
||||
|
||||
//If the body has a boxed layout, fix the sidebar bg position
|
||||
var bg = $(".control-sidebar-bg");
|
||||
_this._fix(bg);
|
||||
|
||||
//If the body has a fixed layout, make the control sidebar fixed
|
||||
if ($('body').hasClass('fixed')) {
|
||||
_this._fixForFixed(sidebar);
|
||||
} else {
|
||||
//If the content height is less than the sidebar's height, force max height
|
||||
if ($('.content-wrapper, .right-side').height() < sidebar.height()) {
|
||||
_this._fixForContent(sidebar);
|
||||
}
|
||||
}
|
||||
},
|
||||
//Open the control sidebar
|
||||
open: function (sidebar, slide) {
|
||||
//Slide over content
|
||||
if (slide) {
|
||||
sidebar.addClass('control-sidebar-open');
|
||||
} else {
|
||||
//Push the content by adding the open class to the body instead
|
||||
//of the sidebar itself
|
||||
$('body').addClass('control-sidebar-open');
|
||||
}
|
||||
},
|
||||
//Close the control sidebar
|
||||
close: function (sidebar, slide) {
|
||||
if (slide) {
|
||||
sidebar.removeClass('control-sidebar-open');
|
||||
} else {
|
||||
$('body').removeClass('control-sidebar-open');
|
||||
}
|
||||
},
|
||||
_fix: function (sidebar) {
|
||||
var _this = this;
|
||||
if ($("body").hasClass('layout-boxed')) {
|
||||
sidebar.css('position', 'absolute');
|
||||
sidebar.height($(".wrapper").height());
|
||||
if (_this.hasBindedResize) {
|
||||
return;
|
||||
}
|
||||
$(window).resize(function () {
|
||||
_this._fix(sidebar);
|
||||
});
|
||||
_this.hasBindedResize = true;
|
||||
} else {
|
||||
sidebar.css({
|
||||
'position': 'fixed',
|
||||
'height': 'auto'
|
||||
});
|
||||
}
|
||||
},
|
||||
_fixForFixed: function (sidebar) {
|
||||
sidebar.css({
|
||||
'position': 'fixed',
|
||||
'max-height': '100%',
|
||||
'overflow': 'auto',
|
||||
});
|
||||
},
|
||||
_fixForContent: function (sidebar) {
|
||||
$(".content-wrapper, .right-side").css('min-height', sidebar.height());
|
||||
}
|
||||
};
|
||||
|
||||
/* BoxWidget
|
||||
* =========
|
||||
* BoxWidget is a plugin to handle collapsing and
|
||||
* removing boxes from the screen.
|
||||
*
|
||||
* @type Object
|
||||
* @usage $.AdminLTE.boxWidget.activate()
|
||||
* Set all your options in the main $.AdminLTE.options object
|
||||
*/
|
||||
$.AdminLTE.boxWidget = {
|
||||
selectors: $.AdminLTE.options.boxWidgetOptions.boxWidgetSelectors,
|
||||
icons: $.AdminLTE.options.boxWidgetOptions.boxWidgetIcons,
|
||||
animationSpeed: $.AdminLTE.options.animationSpeed,
|
||||
activate: function (_box) {
|
||||
var _this = this;
|
||||
if (!_box) {
|
||||
_box = document; // activate all boxes per default
|
||||
}
|
||||
//Listen for collapse event triggers
|
||||
$(_box).on('click', _this.selectors.collapse, function (e) {
|
||||
e.preventDefault();
|
||||
_this.collapse($(this));
|
||||
});
|
||||
|
||||
//Listen for remove event triggers
|
||||
$(_box).on('click', _this.selectors.remove, function (e) {
|
||||
e.preventDefault();
|
||||
_this.remove($(this));
|
||||
});
|
||||
},
|
||||
collapse: function (element) {
|
||||
var _this = this;
|
||||
//Find the box parent
|
||||
var box = element.parents(".box").first();
|
||||
//Find the body and the footer
|
||||
var box_content = box.find("> .box-body, > .box-footer, > form >.box-body, > form > .box-footer");
|
||||
if (!box.hasClass("collapsed-box")) {
|
||||
//Convert minus into plus
|
||||
element.children(":first")
|
||||
.removeClass(_this.icons.collapse)
|
||||
.addClass(_this.icons.open);
|
||||
//Hide the content
|
||||
box_content.slideUp(_this.animationSpeed, function () {
|
||||
box.addClass("collapsed-box");
|
||||
});
|
||||
} else {
|
||||
//Convert plus into minus
|
||||
element.children(":first")
|
||||
.removeClass(_this.icons.open)
|
||||
.addClass(_this.icons.collapse);
|
||||
//Show the content
|
||||
box_content.slideDown(_this.animationSpeed, function () {
|
||||
box.removeClass("collapsed-box");
|
||||
});
|
||||
}
|
||||
},
|
||||
remove: function (element) {
|
||||
//Find the box parent
|
||||
var box = element.parents(".box").first();
|
||||
box.slideUp(this.animationSpeed);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/* ------------------
|
||||
* - Custom Plugins -
|
||||
* ------------------
|
||||
* All custom plugins are defined below.
|
||||
*/
|
||||
|
||||
/*
|
||||
* BOX REFRESH BUTTON
|
||||
* ------------------
|
||||
* This is a custom plugin to use with the component BOX. It allows you to add
|
||||
* a refresh button to the box. It converts the box's state to a loading state.
|
||||
*
|
||||
* @type plugin
|
||||
* @usage $("#box-widget").boxRefresh( options );
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
"use strict";
|
||||
|
||||
$.fn.boxRefresh = function (options) {
|
||||
|
||||
// Render options
|
||||
var settings = $.extend({
|
||||
//Refresh button selector
|
||||
trigger: ".refresh-btn",
|
||||
//File source to be loaded (e.g: ajax/src.php)
|
||||
source: "",
|
||||
//Callbacks
|
||||
onLoadStart: function (box) {
|
||||
return box;
|
||||
}, //Right after the button has been clicked
|
||||
onLoadDone: function (box) {
|
||||
return box;
|
||||
} //When the source has been loaded
|
||||
|
||||
}, options);
|
||||
|
||||
//The overlay
|
||||
var overlay = $('<div class="overlay"><div class="fa fa-refresh fa-spin"></div></div>');
|
||||
|
||||
return this.each(function () {
|
||||
//if a source is specified
|
||||
if (settings.source === "") {
|
||||
if (window.console) {
|
||||
window.console.log("Please specify a source first - boxRefresh()");
|
||||
}
|
||||
return;
|
||||
}
|
||||
//the box
|
||||
var box = $(this);
|
||||
//the button
|
||||
var rBtn = box.find(settings.trigger).first();
|
||||
|
||||
//On trigger click
|
||||
rBtn.on('click', function (e) {
|
||||
e.preventDefault();
|
||||
//Add loading overlay
|
||||
start(box);
|
||||
|
||||
//Perform ajax call
|
||||
box.find(".box-body").load(settings.source, function () {
|
||||
done(box);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
function start(box) {
|
||||
//Add overlay and loading img
|
||||
box.append(overlay);
|
||||
|
||||
settings.onLoadStart.call(box);
|
||||
}
|
||||
|
||||
function done(box) {
|
||||
//Remove overlay and loading img
|
||||
box.find(overlay).remove();
|
||||
|
||||
settings.onLoadDone.call(box);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
/*
|
||||
* EXPLICIT BOX CONTROLS
|
||||
* -----------------------
|
||||
* This is a custom plugin to use with the component BOX. It allows you to activate
|
||||
* a box inserted in the DOM after the app.js was loaded, toggle and remove box.
|
||||
*
|
||||
* @type plugin
|
||||
* @usage $("#box-widget").activateBox();
|
||||
* @usage $("#box-widget").toggleBox();
|
||||
* @usage $("#box-widget").removeBox();
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
$.fn.activateBox = function () {
|
||||
$.AdminLTE.boxWidget.activate(this);
|
||||
};
|
||||
|
||||
$.fn.toggleBox = function () {
|
||||
var button = $($.AdminLTE.boxWidget.selectors.collapse, this);
|
||||
$.AdminLTE.boxWidget.collapse(button);
|
||||
};
|
||||
|
||||
$.fn.removeBox = function () {
|
||||
var button = $($.AdminLTE.boxWidget.selectors.remove, this);
|
||||
$.AdminLTE.boxWidget.remove(button);
|
||||
};
|
||||
|
||||
})(jQuery);
|
||||
|
||||
/*
|
||||
* TODO LIST CUSTOM PLUGIN
|
||||
* -----------------------
|
||||
* This plugin depends on iCheck plugin for checkbox and radio inputs
|
||||
*
|
||||
* @type plugin
|
||||
* @usage $("#todo-widget").todolist( options );
|
||||
*/
|
||||
(function ($) {
|
||||
|
||||
'use strict';
|
||||
|
||||
$.fn.todolist = function (options) {
|
||||
// Render options
|
||||
var settings = $.extend({
|
||||
//When the user checks the input
|
||||
onCheck: function (ele) {
|
||||
return ele;
|
||||
},
|
||||
//When the user unchecks the input
|
||||
onUncheck: function (ele) {
|
||||
return ele;
|
||||
}
|
||||
}, options);
|
||||
|
||||
return this.each(function () {
|
||||
|
||||
if (typeof $.fn.iCheck != 'undefined') {
|
||||
$('input', this).on('ifChecked', function () {
|
||||
var ele = $(this).parents("li").first();
|
||||
ele.toggleClass("done");
|
||||
settings.onCheck.call(ele);
|
||||
});
|
||||
|
||||
$('input', this).on('ifUnchecked', function () {
|
||||
var ele = $(this).parents("li").first();
|
||||
ele.toggleClass("done");
|
||||
settings.onUncheck.call(ele);
|
||||
});
|
||||
} else {
|
||||
$('input', this).on('change', function () {
|
||||
var ele = $(this).parents("li").first();
|
||||
ele.toggleClass("done");
|
||||
if ($('input', ele).is(":checked")) {
|
||||
settings.onCheck.call(ele);
|
||||
} else {
|
||||
settings.onUncheck.call(ele);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
//set/get form element value
|
||||
$.fn.field = function (name, value) {
|
||||
if (typeof name !== "string")
|
||||
return false;
|
||||
var element = $(this).find("[name='" + name + "']");
|
||||
|
||||
if (typeof value === "undefined" && element.length >= 1) {
|
||||
switch (element.attr("type")) {
|
||||
case "checkbox":
|
||||
var result = new Array();
|
||||
element.each(function (i, val) {
|
||||
if ($(this).is(":checked")) {
|
||||
result.push($(this).val());
|
||||
}
|
||||
});
|
||||
return result;
|
||||
break;
|
||||
case "radio":
|
||||
var result;
|
||||
element.each(function (i, val) {
|
||||
if ($(this).is(":checked")) {
|
||||
result = $(this).val();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
break;
|
||||
default:
|
||||
return element.val();
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (element.attr("type")) {
|
||||
case "checkbox":
|
||||
case "radio":
|
||||
value = $.isArray(value) ? value : [value];
|
||||
element.each(function (i) {
|
||||
$(this).prop({
|
||||
checked: $.inArray($(this).val(), value) > -1
|
||||
});
|
||||
});
|
||||
break;
|
||||
case undefined:
|
||||
default:
|
||||
element.val(value);
|
||||
break;
|
||||
}
|
||||
return element;
|
||||
}
|
||||
};
|
||||
}(jQuery));
|
||||
1032
public/assets/js/autocomplete.js
Normal file
1032
public/assets/js/autocomplete.js
Normal file
File diff suppressed because it is too large
Load Diff
3
public/assets/js/backend-init.js
Normal file
3
public/assets/js/backend-init.js
Normal file
@@ -0,0 +1,3 @@
|
||||
define(['backend'], function (Backend) {
|
||||
|
||||
});
|
||||
260
public/assets/js/backend.js
Normal file
260
public/assets/js/backend.js
Normal file
@@ -0,0 +1,260 @@
|
||||
define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
|
||||
var Backend = {
|
||||
api: {
|
||||
sidebar: function (params) {
|
||||
colorArr = ['red', 'green', 'yellow', 'blue', 'teal', 'orange', 'purple'];
|
||||
$colorNums = colorArr.length;
|
||||
badgeList = {};
|
||||
$.each(params, function (k, v) {
|
||||
$url = Fast.api.fixurl(k);
|
||||
|
||||
if ($.isArray(v)) {
|
||||
$nums = typeof v[0] !== 'undefined' ? v[0] : 0;
|
||||
$color = typeof v[1] !== 'undefined' ? v[1] : colorArr[(!isNaN($nums) ? $nums : $nums.length) % $colorNums];
|
||||
$class = typeof v[2] !== 'undefined' ? v[2] : 'label';
|
||||
} else {
|
||||
$nums = v;
|
||||
$color = colorArr[(!isNaN($nums) ? $nums : $nums.length) % $colorNums];
|
||||
$class = 'label';
|
||||
}
|
||||
//必须nums大于0才显示
|
||||
badgeList[$url] = $nums > 0 ? '<small class="' + $class + ' pull-right bg-' + $color + '">' + $nums + '</small>' : '';
|
||||
});
|
||||
$.each(badgeList, function (k, v) {
|
||||
var anchor = top.window.$("li a[addtabs][url='" + k + "']");
|
||||
if (anchor) {
|
||||
top.window.$(".pull-right-container", anchor).html(v);
|
||||
top.window.$(".nav-addtabs li a[node-id='" + anchor.attr("addtabs") + "'] .pull-right-container").html(v);
|
||||
}
|
||||
});
|
||||
},
|
||||
addtabs: function (url, title, icon) {
|
||||
var dom = "a[url='{url}']"
|
||||
var leftlink = top.window.$(dom.replace(/\{url\}/, url));
|
||||
if (leftlink.length > 0) {
|
||||
leftlink.trigger("click");
|
||||
} else {
|
||||
url = Fast.api.fixurl(url);
|
||||
leftlink = top.window.$(dom.replace(/\{url\}/, url));
|
||||
if (leftlink.length > 0) {
|
||||
var event = leftlink.parent().hasClass("active") ? "dblclick" : "click";
|
||||
leftlink.trigger(event);
|
||||
} else {
|
||||
var baseurl = url.substr(0, url.indexOf("?") > -1 ? url.indexOf("?") : url.length);
|
||||
leftlink = top.window.$(dom.replace(/\{url\}/, baseurl));
|
||||
//能找到相对地址
|
||||
if (leftlink.length > 0) {
|
||||
icon = typeof icon !== 'undefined' ? icon : leftlink.find("i").attr("class");
|
||||
title = typeof title !== 'undefined' ? title : leftlink.find("span:first").text();
|
||||
leftlink.trigger("fa.event.toggleitem");
|
||||
}
|
||||
var navnode = top.window.$(".nav-tabs ul li a[node-url='" + url + "']");
|
||||
if (navnode.length > 0) {
|
||||
navnode.trigger("click");
|
||||
} else {
|
||||
//追加新的tab
|
||||
var id = Math.floor(new Date().valueOf() * Math.random());
|
||||
icon = typeof icon !== 'undefined' ? icon : 'fa fa-circle-o';
|
||||
title = typeof title !== 'undefined' ? title : '';
|
||||
top.window.$("<a />").append('<i class="' + icon + '"></i> <span>' + title + '</span>').prop("href", url).attr({
|
||||
url: url,
|
||||
addtabs: id
|
||||
}).addClass("hide").appendTo(top.window.document.body).trigger("click");
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
closetabs: function (url) {
|
||||
if (typeof url === 'undefined') {
|
||||
top.window.$("ul.nav-addtabs li.active .close-tab").trigger("click");
|
||||
} else {
|
||||
var dom = "a[url='{url}']"
|
||||
var navlink = top.window.$(dom.replace(/\{url\}/, url));
|
||||
if (navlink.length === 0) {
|
||||
url = Fast.api.fixurl(url);
|
||||
navlink = top.window.$(dom.replace(/\{url\}/, url));
|
||||
if (navlink.length === 0) {
|
||||
} else {
|
||||
var baseurl = url.substr(0, url.indexOf("?") > -1 ? url.indexOf("?") : url.length);
|
||||
navlink = top.window.$(dom.replace(/\{url\}/, baseurl));
|
||||
//能找到相对地址
|
||||
if (navlink.length === 0) {
|
||||
navlink = top.window.$(".nav-tabs ul li a[node-url='" + url + "']");
|
||||
}
|
||||
}
|
||||
}
|
||||
if (navlink.length > 0 && navlink.attr('addtabs')) {
|
||||
top.window.$("ul.nav-addtabs li#tab_" + navlink.attr('addtabs') + " .close-tab").trigger("click");
|
||||
}
|
||||
}
|
||||
},
|
||||
replaceids: function (elem, url) {
|
||||
//如果有需要替换ids的
|
||||
if (url.indexOf("{ids}") > -1) {
|
||||
var ids = 0;
|
||||
var tableId = $(elem).data("table-id");
|
||||
if (tableId && $("#" + tableId).length > 0 && $("#" + tableId).data("bootstrap.table")) {
|
||||
var Table = require("table");
|
||||
ids = Table.api.selectedids($("#" + tableId)).join(",");
|
||||
}
|
||||
url = url.replace(/\{ids\}/g, ids);
|
||||
}
|
||||
return url;
|
||||
},
|
||||
refreshmenu: function () {
|
||||
top.window.$(".sidebar-menu").trigger("refresh");
|
||||
},
|
||||
gettablecolumnbutton: function (options) {
|
||||
if (typeof options.tableId !== 'undefined' && typeof options.fieldIndex !== 'undefined' && typeof options.buttonIndex !== 'undefined') {
|
||||
var tableOptions = $("#" + options.tableId).bootstrapTable('getOptions');
|
||||
if (tableOptions) {
|
||||
var columnObj = null;
|
||||
$.each(tableOptions.columns, function (i, columns) {
|
||||
$.each(columns, function (j, column) {
|
||||
if (typeof column.fieldIndex !== 'undefined' && column.fieldIndex === options.fieldIndex) {
|
||||
columnObj = column;
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (columnObj) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (columnObj) {
|
||||
return columnObj['buttons'][options.buttonIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
},
|
||||
init: function () {
|
||||
//公共代码
|
||||
//添加ios-fix兼容iOS下的iframe
|
||||
if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) {
|
||||
$("html").addClass("ios-fix");
|
||||
}
|
||||
//配置Toastr的参数
|
||||
Toastr.options.positionClass = Config.controllername === 'index' ? "toast-top-right-index" : "toast-top-right";
|
||||
//点击包含.btn-dialog的元素时弹出dialog
|
||||
$(document).on('click', '.btn-dialog,.dialogit', function (e) {
|
||||
var that = this;
|
||||
var options = $.extend({}, $(that).data() || {});
|
||||
var url = Backend.api.replaceids(that, $(that).data("url") || $(that).attr('href'));
|
||||
var title = $(that).attr("title") || $(that).data("title") || $(that).data('original-title');
|
||||
var button = Backend.api.gettablecolumnbutton(options);
|
||||
if (button && typeof button.callback === 'function') {
|
||||
options.callback = button.callback;
|
||||
}
|
||||
if (typeof options.confirm !== 'undefined') {
|
||||
Layer.confirm(options.confirm, function (index) {
|
||||
Backend.api.open(url, title, options);
|
||||
Layer.close(index);
|
||||
});
|
||||
} else {
|
||||
window[$(that).data("window") || 'self'].Backend.api.open(url, title, options);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
//点击包含.btn-addtabs的元素时新增选项卡
|
||||
$(document).on('click', '.btn-addtabs,.addtabsit', function (e) {
|
||||
var that = this;
|
||||
var options = $.extend({}, $(that).data() || {});
|
||||
var url = Backend.api.replaceids(that, $(that).data("url") || $(that).attr('href'));
|
||||
var title = $(that).attr("title") || $(that).data("title") || $(that).data('original-title');
|
||||
var icon = $(that).attr("icon") || $(that).data("icon");
|
||||
if (typeof options.confirm !== 'undefined') {
|
||||
Layer.confirm(options.confirm, function (index) {
|
||||
Backend.api.addtabs(url, title, icon);
|
||||
Layer.close(index);
|
||||
});
|
||||
} else {
|
||||
Backend.api.addtabs(url, title, icon);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
//点击包含.btn-ajax的元素时发送Ajax请求
|
||||
$(document).on('click', '.btn-ajax,.ajaxit', function (e) {
|
||||
var that = this;
|
||||
var options = $.extend({}, $(that).data() || {});
|
||||
if (typeof options.url === 'undefined' && $(that).attr("href")) {
|
||||
options.url = $(that).attr("href");
|
||||
}
|
||||
options.url = Backend.api.replaceids(this, options.url);
|
||||
var success = typeof options.success === 'function' ? options.success : null;
|
||||
var error = typeof options.error === 'function' ? options.error : null;
|
||||
delete options.success;
|
||||
delete options.error;
|
||||
var button = Backend.api.gettablecolumnbutton(options);
|
||||
if (button) {
|
||||
if (typeof button.success === 'function') {
|
||||
success = button.success;
|
||||
}
|
||||
if (typeof button.error === 'function') {
|
||||
error = button.error;
|
||||
}
|
||||
}
|
||||
//如果未设备成功的回调,设定了自动刷新的情况下自动进行刷新
|
||||
if (!success && typeof options.tableId !== 'undefined' && typeof options.refresh !== 'undefined' && options.refresh) {
|
||||
success = function () {
|
||||
$("#" + options.tableId).bootstrapTable('refresh');
|
||||
}
|
||||
}
|
||||
if (typeof options.confirm !== 'undefined') {
|
||||
Layer.confirm(options.confirm, function (index) {
|
||||
Backend.api.ajax(options, success, error);
|
||||
Layer.close(index);
|
||||
});
|
||||
} else {
|
||||
Backend.api.ajax(options, success, error);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
$(document).on('click', '.btn-click,.clickit', function (e) {
|
||||
var that = this;
|
||||
var options = $.extend({}, $(that).data() || {});
|
||||
var row = {};
|
||||
if (typeof options.tableId !== 'undefined') {
|
||||
var index = parseInt(options.rowIndex);
|
||||
var data = $("#" + options.tableId).bootstrapTable('getData');
|
||||
row = typeof data[index] !== 'undefined' ? data[index] : {};
|
||||
}
|
||||
var button = Backend.api.gettablecolumnbutton(options);
|
||||
var click = typeof button.click === 'function' ? button.click : $.noop;
|
||||
|
||||
if (typeof options.confirm !== 'undefined') {
|
||||
Layer.confirm(options.confirm, function (index) {
|
||||
click.apply(that, [options, row, button]);
|
||||
Layer.close(index);
|
||||
});
|
||||
} else {
|
||||
click.apply(that, [options, row, button]);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
//修复含有fixed-footer类的body边距
|
||||
if ($(".fixed-footer").length > 0) {
|
||||
$(document.body).css("padding-bottom", $(".fixed-footer").outerHeight());
|
||||
}
|
||||
//修复不在iframe时layer-footer隐藏的问题
|
||||
if ($(".layer-footer").length > 0 && self === top) {
|
||||
$(".layer-footer").show();
|
||||
}
|
||||
//tooltip和popover
|
||||
if (!('ontouchstart' in document.documentElement)) {
|
||||
$('body').tooltip({selector: '[data-toggle="tooltip"]', trigger: 'hover'});
|
||||
}
|
||||
$('body').popover({selector: '[data-toggle="popover"]'});
|
||||
}
|
||||
};
|
||||
Backend.api = $.extend(Fast.api, Backend.api);
|
||||
//将Template渲染至全局,以便于在子框架中调用
|
||||
window.Template = Template;
|
||||
//将Moment渲染至全局,以便于在子框架中调用
|
||||
window.Moment = Moment;
|
||||
//将Backend渲染至全局,以便于在子框架中调用
|
||||
window.Backend = Backend;
|
||||
|
||||
Backend.init();
|
||||
return Backend;
|
||||
});
|
||||
847
public/assets/js/backend/addon.js
Normal file
847
public/assets/js/backend/addon.js
Normal 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;
|
||||
});
|
||||
62
public/assets/js/backend/auth/admin.js
Normal file
62
public/assets/js/backend/auth/admin.js
Normal 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;
|
||||
});
|
||||
64
public/assets/js/backend/auth/adminlog.js
Normal file
64
public/assets/js/backend/auth/adminlog.js
Normal 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;
|
||||
});
|
||||
160
public/assets/js/backend/auth/group.js
Normal file
160
public/assets/js/backend/auth/group.js
Normal 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(/(&|&)nbsp;/g, ' ');
|
||||
}
|
||||
},
|
||||
{field: 'status', title: __('Status'), formatter: Table.api.formatter.status},
|
||||
{
|
||||
field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: function (value, row, index) {
|
||||
if (Config.admin.group_ids.indexOf(parseInt(row.id)) > -1) {
|
||||
return '';
|
||||
}
|
||||
return Table.api.formatter.operate.call(this, value, row, index);
|
||||
}
|
||||
}
|
||||
]
|
||||
],
|
||||
pagination: false,
|
||||
search: false,
|
||||
commonSearch: false,
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);//当内容渲染完成后
|
||||
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
Form.api.bindevent($("form[role=form]"), null, null, function () {
|
||||
if ($("#treeview").length > 0) {
|
||||
var r = $("#treeview").jstree("get_all_checked");
|
||||
$("input[name='row[rules]']").val(r.join(','));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
//渲染权限节点树
|
||||
//变更级别后需要重建节点树
|
||||
$(document).on("change", "select[name='row[pid]']", function () {
|
||||
var pid = $(this).data("pid");
|
||||
var id = $(this).data("id");
|
||||
if ($(this).val() == id) {
|
||||
$("option[value='" + pid + "']", this).prop("selected", true).change();
|
||||
Backend.api.toastr.error(__('Can not change the parent to self'));
|
||||
return false;
|
||||
}
|
||||
$.ajax({
|
||||
url: "auth/group/roletree",
|
||||
type: 'post',
|
||||
dataType: 'json',
|
||||
data: {id: id, pid: $(this).val()},
|
||||
success: function (ret) {
|
||||
if (ret.hasOwnProperty("code")) {
|
||||
var data = ret.hasOwnProperty("data") && ret.data != "" ? ret.data : "";
|
||||
if (ret.code === 1) {
|
||||
//销毁已有的节点树
|
||||
$("#treeview").jstree("destroy");
|
||||
Controller.api.rendertree(data);
|
||||
} else {
|
||||
Backend.api.toastr.error(ret.msg);
|
||||
}
|
||||
}
|
||||
}, error: function (e) {
|
||||
Backend.api.toastr.error(e.message);
|
||||
}
|
||||
});
|
||||
});
|
||||
//全选和展开
|
||||
$(document).on("click", "#checkall", function () {
|
||||
$("#treeview").jstree($(this).prop("checked") ? "check_all" : "uncheck_all");
|
||||
});
|
||||
$(document).on("click", "#expandall", function () {
|
||||
$("#treeview").jstree($(this).prop("checked") ? "open_all" : "close_all");
|
||||
});
|
||||
$("select[name='row[pid]']").trigger("change");
|
||||
},
|
||||
rendertree: function (content) {
|
||||
$("#treeview")
|
||||
.on('redraw.jstree', function (e) {
|
||||
$(".layer-footer").attr("domrefresh", Math.random());
|
||||
})
|
||||
.jstree({
|
||||
"themes": {"stripes": true},
|
||||
"checkbox": {
|
||||
"keep_selected_style": false,
|
||||
},
|
||||
"types": {
|
||||
"root": {
|
||||
"icon": "fa fa-folder-open",
|
||||
},
|
||||
"menu": {
|
||||
"icon": "fa fa-folder-open",
|
||||
},
|
||||
"file": {
|
||||
"icon": "fa fa-file-o",
|
||||
}
|
||||
},
|
||||
"plugins": ["checkbox", "types"],
|
||||
"core": {
|
||||
'check_callback': true,
|
||||
"data": content
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
221
public/assets/js/backend/auth/rule.js
Normal file
221
public/assets/js/backend/auth/rule.js
Normal 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(/(&|&)nbsp;/g, ' ');
|
||||
var caret = row.haschild == 1 || row.ismenu == 1 ? '<i class="fa fa-caret-right"></i>' : '';
|
||||
value = value.indexOf(" ") > -1 ? value.replace(/(.*) /, "$1" + caret) : caret + value;
|
||||
|
||||
value = !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||
return '<a href="javascript:;" data-id="' + row.id + '" data-pid="' + row.pid + '" class="'
|
||||
+ (row.haschild == 1 || row.ismenu == 1 ? 'text-primary' : 'disabled') + ' btn-node-sub">' + value + '</a>';
|
||||
},
|
||||
name: function (value, row, index) {
|
||||
return !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||
},
|
||||
icon: function (value, row, index) {
|
||||
return '<span class="' + (!row.ismenu || row.status == 'hidden' ? 'text-muted' : '') + '"><i class="' + value + '"></i></span>';
|
||||
}
|
||||
},
|
||||
bindevent: function () {
|
||||
$(document).on('click', "input[name='row[ismenu]']", function () {
|
||||
var name = $("input[name='row[name]']");
|
||||
var ismenu = $(this).val() == 1;
|
||||
name.prop("placeholder", ismenu ? name.data("placeholder-menu") : name.data("placeholder-node"));
|
||||
$('div[data-type="menu"]').toggleClass("hidden", !ismenu);
|
||||
});
|
||||
$("input[name='row[ismenu]']:checked").trigger("click");
|
||||
|
||||
var iconlist = [];
|
||||
var iconfunc = function () {
|
||||
Layer.open({
|
||||
type: 1,
|
||||
area: ['80%', '80%'], //宽高
|
||||
content: Template('chooseicontpl', {iconlist: iconlist})
|
||||
});
|
||||
};
|
||||
Form.api.bindevent($("form[role=form]"), function (data) {
|
||||
Fast.api.refreshmenu();
|
||||
});
|
||||
$(document).on('change keyup', "#icon", function () {
|
||||
$(this).prev().find("i").prop("class", $(this).val());
|
||||
});
|
||||
$(document).on('click', ".btn-search-icon", function () {
|
||||
if (iconlist.length == 0) {
|
||||
$.get(Config.site.cdnurl + "/assets/libs/font-awesome/css/font-awesome.css", function (ret) {
|
||||
var exp = /fa-(.*):before/ig;
|
||||
var result;
|
||||
while ((result = exp.exec(ret)) != null) {
|
||||
iconlist.push(result[1]);
|
||||
}
|
||||
iconfunc();
|
||||
});
|
||||
} else {
|
||||
iconfunc();
|
||||
}
|
||||
});
|
||||
$(document).on('click', '#chooseicon ul li', function () {
|
||||
$("input[name='row[icon]']").val('fa fa-' + $(this).data("font")).trigger("change");
|
||||
Layer.closeAll();
|
||||
});
|
||||
$(document).on('keyup', 'input.js-icon-search', function () {
|
||||
$("#chooseicon ul li").show();
|
||||
if ($(this).val() != '') {
|
||||
$("#chooseicon ul li:not([data-font*='" + $(this).val() + "'])").hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
93
public/assets/js/backend/category.js
Normal file
93
public/assets/js/backend/category.js
Normal 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(/(&|&)nbsp;/g, ' ');
|
||||
}
|
||||
},
|
||||
{field: 'nickname', title: __('Nickname')},
|
||||
{field: 'flag', title: __('Flag'), formatter: Table.api.formatter.flag},
|
||||
{field: 'image', title: __('Image'), operate: false, events: Table.api.events.image, formatter: Table.api.formatter.image},
|
||||
{field: 'weigh', title: __('Weigh')},
|
||||
{field: 'status', title: __('Status'), operate: false, formatter: Table.api.formatter.status},
|
||||
{field: 'operate', title: __('Operate'), table: table, events: Table.api.events.operate, formatter: Table.api.formatter.operate}
|
||||
]
|
||||
]
|
||||
};
|
||||
// 初始化表格
|
||||
table.bootstrapTable(tableOptions);
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
|
||||
//绑定TAB事件
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
// var options = table.bootstrapTable(tableOptions);
|
||||
var typeStr = $(this).attr("href").replace('#', '');
|
||||
var options = table.bootstrapTable('getOptions');
|
||||
options.pageNumber = 1;
|
||||
options.queryParams = function (params) {
|
||||
// params.filter = JSON.stringify({type: typeStr});
|
||||
params.type = typeStr;
|
||||
|
||||
return params;
|
||||
};
|
||||
table.bootstrapTable('refresh', {});
|
||||
return false;
|
||||
|
||||
});
|
||||
|
||||
//必须默认触发shown.bs.tab事件
|
||||
// $('ul.nav-tabs li.active a[data-toggle="tab"]').trigger("shown.bs.tab");
|
||||
|
||||
},
|
||||
add: function () {
|
||||
Controller.api.bindevent();
|
||||
setTimeout(function () {
|
||||
$("#c-type").trigger("change");
|
||||
}, 100);
|
||||
},
|
||||
edit: function () {
|
||||
Controller.api.bindevent();
|
||||
},
|
||||
api: {
|
||||
bindevent: function () {
|
||||
$(document).on("change", "#c-type", function () {
|
||||
$("#c-pid option[data-type='all']").prop("selected", true);
|
||||
$("#c-pid option").removeClass("hide");
|
||||
$("#c-pid option[data-type!='" + $(this).val() + "'][data-type!='all']").addClass("hide");
|
||||
$("#c-pid").data("selectpicker") && $("#c-pid").selectpicker("refresh");
|
||||
});
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
234
public/assets/js/backend/command.js
Normal file
234
public/assets/js/backend/command.js
Normal 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;
|
||||
});
|
||||
80
public/assets/js/backend/dashboard.js
Normal file
80
public/assets/js/backend/dashboard.js
Normal 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;
|
||||
});
|
||||
261
public/assets/js/backend/general/attachment.js
Normal file
261
public/assets/js/backend/general/attachment.js
Normal 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;
|
||||
});
|
||||
140
public/assets/js/backend/general/config.js
Normal file
140
public/assets/js/backend/general/config.js
Normal 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;
|
||||
});
|
||||
57
public/assets/js/backend/general/profile.js
Normal file
57
public/assets/js/backend/general/profile.js
Normal 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;
|
||||
});
|
||||
423
public/assets/js/backend/index.js
Normal file
423
public/assets/js/backend/index.js
Normal 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;
|
||||
});
|
||||
1057
public/assets/js/backend/shopro/activity/activity.js
Normal file
1057
public/assets/js/backend/shopro/activity/activity.js
Normal file
File diff suppressed because it is too large
Load Diff
244
public/assets/js/backend/shopro/activity/groupon.js
Normal file
244
public/assets/js/backend/shopro/activity/groupon.js
Normal 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;
|
||||
});
|
||||
145
public/assets/js/backend/shopro/app/mplive/goods.js
Normal file
145
public/assets/js/backend/shopro/app/mplive/goods.js
Normal 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;
|
||||
});
|
||||
260
public/assets/js/backend/shopro/app/mplive/index.js
Normal file
260
public/assets/js/backend/shopro/app/mplive/index.js
Normal 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;
|
||||
});
|
||||
329
public/assets/js/backend/shopro/app/mplive/room.js
Normal file
329
public/assets/js/backend/shopro/app/mplive/room.js
Normal 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;
|
||||
});
|
||||
396
public/assets/js/backend/shopro/app/score_shop.js
Normal file
396
public/assets/js/backend/shopro/app/score_shop.js
Normal 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;
|
||||
});
|
||||
373
public/assets/js/backend/shopro/category.js
Normal file
373
public/assets/js/backend/shopro/category.js
Normal 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;
|
||||
});
|
||||
290
public/assets/js/backend/shopro/chat/common_word.js
Normal file
290
public/assets/js/backend/shopro/chat/common_word.js
Normal 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;
|
||||
});
|
||||
288
public/assets/js/backend/shopro/chat/customer_service.js
Normal file
288
public/assets/js/backend/shopro/chat/customer_service.js
Normal 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;
|
||||
});
|
||||
290
public/assets/js/backend/shopro/chat/question.js
Normal file
290
public/assets/js/backend/shopro/chat/question.js
Normal 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;
|
||||
});
|
||||
223
public/assets/js/backend/shopro/chat/record.js
Normal file
223
public/assets/js/backend/shopro/chat/record.js
Normal 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;
|
||||
});
|
||||
154
public/assets/js/backend/shopro/chat/user.js
Normal file
154
public/assets/js/backend/shopro/chat/user.js
Normal 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;
|
||||
});
|
||||
506
public/assets/js/backend/shopro/commission/agent.js
Normal file
506
public/assets/js/backend/shopro/commission/agent.js
Normal 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;
|
||||
});
|
||||
435
public/assets/js/backend/shopro/commission/goods.js
Normal file
435
public/assets/js/backend/shopro/commission/goods.js
Normal 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;
|
||||
});
|
||||
401
public/assets/js/backend/shopro/commission/level.js
Normal file
401
public/assets/js/backend/shopro/commission/level.js
Normal 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;
|
||||
});
|
||||
109
public/assets/js/backend/shopro/commission/log.js
Normal file
109
public/assets/js/backend/shopro/commission/log.js
Normal 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;
|
||||
});
|
||||
405
public/assets/js/backend/shopro/commission/order.js
Normal file
405
public/assets/js/backend/shopro/commission/order.js
Normal 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;
|
||||
});
|
||||
201
public/assets/js/backend/shopro/commission/reward.js
Normal file
201
public/assets/js/backend/shopro/commission/reward.js
Normal 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;
|
||||
});
|
||||
645
public/assets/js/backend/shopro/config.js
Normal file
645
public/assets/js/backend/shopro/config.js
Normal 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;
|
||||
});
|
||||
556
public/assets/js/backend/shopro/coupon.js
Normal file
556
public/assets/js/backend/shopro/coupon.js
Normal 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;
|
||||
});
|
||||
552
public/assets/js/backend/shopro/dashboard.js
Normal file
552
public/assets/js/backend/shopro/dashboard.js
Normal 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;
|
||||
});
|
||||
296
public/assets/js/backend/shopro/data/area.js
Normal file
296
public/assets/js/backend/shopro/data/area.js
Normal 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;
|
||||
});
|
||||
224
public/assets/js/backend/shopro/data/express.js
Normal file
224
public/assets/js/backend/shopro/data/express.js
Normal 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;
|
||||
});
|
||||
359
public/assets/js/backend/shopro/data/fake_user.js
Normal file
359
public/assets/js/backend/shopro/data/fake_user.js
Normal 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;
|
||||
});
|
||||
220
public/assets/js/backend/shopro/data/faq.js
Normal file
220
public/assets/js/backend/shopro/data/faq.js
Normal 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;
|
||||
});
|
||||
355
public/assets/js/backend/shopro/data/page.js
Normal file
355
public/assets/js/backend/shopro/data/page.js
Normal 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;
|
||||
});
|
||||
291
public/assets/js/backend/shopro/data/richtext.js
Normal file
291
public/assets/js/backend/shopro/data/richtext.js
Normal 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;
|
||||
});
|
||||
103
public/assets/js/backend/shopro/decorate/designer.js
Normal file
103
public/assets/js/backend/shopro/decorate/designer.js
Normal 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;
|
||||
});
|
||||
2280
public/assets/js/backend/shopro/decorate/page.js
Normal file
2280
public/assets/js/backend/shopro/decorate/page.js
Normal file
File diff suppressed because it is too large
Load Diff
362
public/assets/js/backend/shopro/decorate/template.js
Normal file
362
public/assets/js/backend/shopro/decorate/template.js
Normal 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;
|
||||
});
|
||||
254
public/assets/js/backend/shopro/dispatch/dispatch.js
Normal file
254
public/assets/js/backend/shopro/dispatch/dispatch.js
Normal 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;
|
||||
});
|
||||
210
public/assets/js/backend/shopro/feedback.js
Normal file
210
public/assets/js/backend/shopro/feedback.js
Normal 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;
|
||||
});
|
||||
525
public/assets/js/backend/shopro/goods/comment.js
Normal file
525
public/assets/js/backend/shopro/goods/comment.js
Normal 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;
|
||||
});
|
||||
1471
public/assets/js/backend/shopro/goods/goods.js
Normal file
1471
public/assets/js/backend/shopro/goods/goods.js
Normal file
File diff suppressed because it is too large
Load Diff
178
public/assets/js/backend/shopro/goods/service.js
Normal file
178
public/assets/js/backend/shopro/goods/service.js
Normal 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;
|
||||
});
|
||||
89
public/assets/js/backend/shopro/goods/stock_log.js
Normal file
89
public/assets/js/backend/shopro/goods/stock_log.js
Normal 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;
|
||||
});
|
||||
227
public/assets/js/backend/shopro/goods/stock_warning.js
Normal file
227
public/assets/js/backend/shopro/goods/stock_warning.js
Normal 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;
|
||||
});
|
||||
277
public/assets/js/backend/shopro/notification/config.js
Normal file
277
public/assets/js/backend/shopro/notification/config.js
Normal 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;
|
||||
});
|
||||
437
public/assets/js/backend/shopro/order/aftersale.js
Normal file
437
public/assets/js/backend/shopro/order/aftersale.js
Normal 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;
|
||||
});
|
||||
273
public/assets/js/backend/shopro/order/invoice.js
Normal file
273
public/assets/js/backend/shopro/order/invoice.js
Normal 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;
|
||||
});
|
||||
1584
public/assets/js/backend/shopro/order/order.js
Normal file
1584
public/assets/js/backend/shopro/order/order.js
Normal file
File diff suppressed because it is too large
Load Diff
240
public/assets/js/backend/shopro/pay_config.js
Normal file
240
public/assets/js/backend/shopro/pay_config.js
Normal 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;
|
||||
});
|
||||
275
public/assets/js/backend/shopro/trade/order.js
Normal file
275
public/assets/js/backend/shopro/trade/order.js
Normal 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;
|
||||
});
|
||||
155
public/assets/js/backend/shopro/user/coupon.js
Normal file
155
public/assets/js/backend/shopro/user/coupon.js
Normal 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;
|
||||
});
|
||||
475
public/assets/js/backend/shopro/user/user.js
Normal file
475
public/assets/js/backend/shopro/user/user.js
Normal 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;
|
||||
});
|
||||
62
public/assets/js/backend/shopro/wechat/config.js
Normal file
62
public/assets/js/backend/shopro/wechat/config.js
Normal 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;
|
||||
});
|
||||
196
public/assets/js/backend/shopro/wechat/material.js
Normal file
196
public/assets/js/backend/shopro/wechat/material.js
Normal 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;
|
||||
});
|
||||
466
public/assets/js/backend/shopro/wechat/menu.js
Normal file
466
public/assets/js/backend/shopro/wechat/menu.js
Normal 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;
|
||||
});
|
||||
270
public/assets/js/backend/shopro/wechat/reply.js
Normal file
270
public/assets/js/backend/shopro/wechat/reply.js
Normal 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;
|
||||
});
|
||||
291
public/assets/js/backend/shopro/withdraw.js
Normal file
291
public/assets/js/backend/shopro/withdraw.js
Normal 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;
|
||||
});
|
||||
114
public/assets/js/backend/user/group.js
Normal file
114
public/assets/js/backend/user/group.js
Normal 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;
|
||||
});
|
||||
130
public/assets/js/backend/user/rule.js
Normal file
130
public/assets/js/backend/user/rule.js
Normal 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(/(&|&)nbsp;/g, ' ');
|
||||
var caret = row.haschild == 1 || row.ismenu == 1 ? '<i class="fa fa-caret-right"></i>' : '';
|
||||
value = value.indexOf(" ") > -1 ? value.replace(/(.*) /, "$1" + caret) : caret + value;
|
||||
|
||||
value = !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||
return '<a href="javascript:;" data-id="' + row.id + '" data-pid="' + row.pid + '" class="'
|
||||
+ (row.haschild == 1 || row.ismenu == 1 ? 'text-primary' : 'disabled') + ' btn-node-sub">' + value + '</a>';
|
||||
},
|
||||
name: function (value, row, index) {
|
||||
return !row.ismenu || row.status == 'hidden' ? "<span class='text-muted'>" + value + "</span>" : value;
|
||||
},
|
||||
},
|
||||
bindevent: function () {
|
||||
$(document).on('click', "input[name='row[ismenu]']", function () {
|
||||
var name = $("input[name='row[name]']");
|
||||
name.prop("placeholder", $(this).val() == 1 ? name.data("placeholder-menu") : name.data("placeholder-node"));
|
||||
});
|
||||
$("input[name='row[ismenu]']:checked").trigger("click");
|
||||
Form.api.bindevent($("form[role=form]"));
|
||||
}
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
67
public/assets/js/backend/user/user.js
Normal file
67
public/assets/js/backend/user/user.js
Normal 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;
|
||||
});
|
||||
404
public/assets/js/bootstrap-table-commonsearch.js
vendored
Normal file
404
public/assets/js/bootstrap-table-commonsearch.js
vendored
Normal file
@@ -0,0 +1,404 @@
|
||||
/**
|
||||
* FastAdmin通用搜索
|
||||
*
|
||||
* @author: pppscn <35696959@qq.com>
|
||||
* @update 2017-05-07 <https://gitee.com/pp/fastadmin>
|
||||
*
|
||||
* @author: Karson <karson@fastadmin.net>
|
||||
* @update 2018-04-05 <https://gitee.com/karson/fastadmin>
|
||||
*/
|
||||
|
||||
!function ($) {
|
||||
'use strict';
|
||||
|
||||
var ColumnsForSearch = [];
|
||||
|
||||
var sprintf = $.fn.bootstrapTable.utils.sprintf;
|
||||
|
||||
var initCommonSearch = function (pColumns, that) {
|
||||
var vFormCommon = createFormCommon(pColumns, that);
|
||||
|
||||
var vModal = sprintf("<div class=\"commonsearch-table %s\">", that.options.searchFormVisible ? "" : "hidden");
|
||||
vModal += vFormCommon;
|
||||
vModal += "</div>";
|
||||
that.$container.prepend($(vModal));
|
||||
that.$commonsearch = $(".commonsearch-table", that.$container);
|
||||
var form = $("form.form-commonsearch", that.$commonsearch);
|
||||
|
||||
require(['form'], function (Form) {
|
||||
Form.api.bindevent(form);
|
||||
form.validator("destroy");
|
||||
});
|
||||
|
||||
// 表单提交
|
||||
form.on("submit", function (event) {
|
||||
event.preventDefault();
|
||||
that.onCommonSearch();
|
||||
return false;
|
||||
});
|
||||
|
||||
// 重置搜索
|
||||
form.on("click", "button[type=reset]", function (event) {
|
||||
form[0].reset();
|
||||
|
||||
setTimeout(function () {
|
||||
that.onCommonSearch();
|
||||
}, 1);
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var createFormCommon = function (pColumns, that) {
|
||||
// 如果有使用模板则直接返回模板的内容
|
||||
if (that.options.searchFormTemplate) {
|
||||
return Template(that.options.searchFormTemplate, {columns: pColumns, table: that});
|
||||
}
|
||||
var htmlForm = [];
|
||||
htmlForm.push(sprintf('<form class="form-horizontal form-commonsearch" novalidate method="post" action="%s" >', that.options.actionForm));
|
||||
htmlForm.push('<fieldset>');
|
||||
if (that.options.titleForm.length > 0)
|
||||
htmlForm.push(sprintf("<legend>%s</legend>", that.options.titleForm));
|
||||
htmlForm.push('<div class="row">');
|
||||
for (var i in pColumns) {
|
||||
var vObjCol = pColumns[i];
|
||||
if (!vObjCol.checkbox && !vObjCol.radio && vObjCol.field && vObjCol.field !== 'operate' && vObjCol.searchable && vObjCol.operate !== false) {
|
||||
var query = Fast.api.query(vObjCol.field);
|
||||
var operate = Fast.api.query(vObjCol.field + "-operate");
|
||||
|
||||
var renderDefault = that.options.renderDefault && (typeof vObjCol.renderDefault == 'undefined' || vObjCol.renderDefault);
|
||||
vObjCol.defaultValue = renderDefault && query ? query : (typeof vObjCol.defaultValue === 'undefined' ? '' : vObjCol.defaultValue);
|
||||
vObjCol.operate = renderDefault && operate ? operate : (typeof vObjCol.operate === 'undefined' ? '=' : vObjCol.operate);
|
||||
ColumnsForSearch.push(vObjCol);
|
||||
|
||||
htmlForm.push('<div class="form-group col-xs-12 col-sm-6 col-md-4 col-lg-3">');
|
||||
htmlForm.push(sprintf('<label for="%s" class="control-label col-xs-4">%s</label>', vObjCol.field, vObjCol.title));
|
||||
htmlForm.push('<div class="col-xs-8">');
|
||||
|
||||
vObjCol.operate = vObjCol.operate ? vObjCol.operate.toUpperCase() : '=';
|
||||
htmlForm.push(sprintf('<input type="hidden" class="form-control operate" name="%s-operate" data-name="%s" value="%s" readonly>', vObjCol.field, vObjCol.field, vObjCol.operate));
|
||||
|
||||
var addClass = typeof vObjCol.addClass === 'undefined' ? (typeof vObjCol.addclass === 'undefined' ? 'form-control' : 'form-control ' + vObjCol.addclass) : 'form-control ' + vObjCol.addClass;
|
||||
var extend = typeof vObjCol.extend === 'undefined' ? '' : vObjCol.extend;
|
||||
var style = typeof vObjCol.style === 'undefined' ? '' : sprintf('style="%s"', vObjCol.style);
|
||||
extend = typeof vObjCol.data !== 'undefined' && extend == '' ? vObjCol.data : extend;
|
||||
extend = typeof vObjCol.autocomplete !== 'undefined' ? extend + ' autocomplete="' + (vObjCol.autocomplete === false || vObjCol.autocomplete === 'off' ? 'off' : 'on') + '"' : extend;
|
||||
if (vObjCol.searchList) {
|
||||
if (typeof vObjCol.searchList === 'function') {
|
||||
htmlForm.push(vObjCol.searchList.call(this, vObjCol));
|
||||
} else {
|
||||
var optionList = [sprintf('<option value="">%s</option>', that.options.formatCommonChoose())];
|
||||
if (typeof vObjCol.searchList === 'object' && typeof vObjCol.searchList.then === 'function') {
|
||||
(function (vObjCol, that) {
|
||||
$.when(vObjCol.searchList).done(function (ret) {
|
||||
var searchList = [];
|
||||
if (ret.data && ret.data.searchlist && $.isArray(ret.data.searchlist)) {
|
||||
searchList = ret.data.searchlist;
|
||||
} else if (ret.constructor === Array || ret.constructor === Object) {
|
||||
searchList = ret;
|
||||
}
|
||||
var optionList = createOptionList(searchList, vObjCol, that);
|
||||
$("form.form-commonsearch select[name='" + vObjCol.field + "']", that.$container).html(optionList.join('')).trigger("change");
|
||||
});
|
||||
})(vObjCol, that);
|
||||
} else {
|
||||
optionList = createOptionList(vObjCol.searchList, vObjCol, that);
|
||||
}
|
||||
htmlForm.push(sprintf('<select class="%s" name="%s" %s %s>%s</select>', addClass, vObjCol.field, style, extend, optionList.join('')));
|
||||
}
|
||||
} else {
|
||||
var placeholder = typeof vObjCol.placeholder === 'undefined' ? vObjCol.title : vObjCol.placeholder;
|
||||
var type = typeof vObjCol.type === 'undefined' ? 'text' : vObjCol.type;
|
||||
var defaultValue = typeof vObjCol.defaultValue === 'undefined' ? '' : vObjCol.defaultValue;
|
||||
if (/BETWEEN$/.test(vObjCol.operate)) {
|
||||
var defaultValueArr = defaultValue.toString().match(/\|/) ? defaultValue.split('|') : ['', ''];
|
||||
var placeholderArr = placeholder.toString().match(/\|/) ? placeholder.split('|') : [placeholder, placeholder];
|
||||
htmlForm.push('<div class="row row-between">');
|
||||
htmlForm.push(sprintf('<div class="col-xs-6"><input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s-min" data-index="%s" %s %s></div>', type, addClass, vObjCol.field, defaultValueArr[0], placeholderArr[0], vObjCol.field, i, style, extend));
|
||||
htmlForm.push(sprintf('<div class="col-xs-6"><input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s-max" data-index="%s" %s %s></div>', type, addClass, vObjCol.field, defaultValueArr[1], placeholderArr[1], vObjCol.field, i, style, extend));
|
||||
htmlForm.push('</div>');
|
||||
} else {
|
||||
htmlForm.push(sprintf('<input type="%s" class="%s" name="%s" value="%s" placeholder="%s" id="%s" data-index="%s" %s %s>', type, addClass, vObjCol.field, defaultValue, placeholder, vObjCol.field, i, style, extend));
|
||||
}
|
||||
}
|
||||
|
||||
htmlForm.push('</div>');
|
||||
htmlForm.push('</div>');
|
||||
}
|
||||
}
|
||||
htmlForm.push('<div class="form-group col-xs-12 col-sm-6 col-md-4 col-lg-3">');
|
||||
htmlForm.push(createFormBtn(that).join(''));
|
||||
htmlForm.push('</div>');
|
||||
htmlForm.push('</div>');
|
||||
htmlForm.push('</fieldset>');
|
||||
htmlForm.push('</form>');
|
||||
|
||||
return htmlForm.join('');
|
||||
};
|
||||
|
||||
var createFormBtn = function (that) {
|
||||
var htmlBtn = [];
|
||||
var searchSubmit = that.options.formatCommonSubmitButton();
|
||||
var searchReset = that.options.formatCommonResetButton();
|
||||
htmlBtn.push('<div class="col-sm-8 col-xs-offset-4">');
|
||||
htmlBtn.push(sprintf('<button type="submit" class="btn btn-success" formnovalidate>%s</button> ', searchSubmit));
|
||||
htmlBtn.push(sprintf('<button type="reset" class="btn btn-default" >%s</button> ', searchReset));
|
||||
htmlBtn.push('</div>');
|
||||
return htmlBtn;
|
||||
};
|
||||
|
||||
var createOptionList = function (searchList, vObjCol, that) {
|
||||
var isArray = searchList.constructor === Array;
|
||||
var optionList = [];
|
||||
optionList.push(sprintf('<option value="">%s</option>', that.options.formatCommonChoose()));
|
||||
$.each(searchList, function (key, value) {
|
||||
if (value.constructor === Object) {
|
||||
key = value.id;
|
||||
value = value.name;
|
||||
} else {
|
||||
key = isArray ? value : key;
|
||||
}
|
||||
optionList.push(sprintf("<option value='" + Fast.api.escape(key) + "' %s>" + Fast.api.escape(value) + "</option>", key == vObjCol.defaultValue ? 'selected' : ''));
|
||||
});
|
||||
return optionList;
|
||||
};
|
||||
|
||||
var isSearchAvailble = function (that) {
|
||||
|
||||
//只支持服务端搜索
|
||||
if (!that.options.commonSearch || that.options.sidePagination != 'server' || !that.options.url) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
};
|
||||
|
||||
var getSearchQuery = function (that, removeempty) {
|
||||
var op = {};
|
||||
var filter = {};
|
||||
var value = '';
|
||||
$("form.form-commonsearch .operate", that.$commonsearch).each(function (i) {
|
||||
var name = $(this).data("name");
|
||||
var sym = $(this).is("select") ? $("option:selected", this).val() : $(this).val().toUpperCase();
|
||||
var obj = $("[name='" + name + "']", that.$commonsearch);
|
||||
if (obj.length == 0)
|
||||
return true;
|
||||
var vObjCol = ColumnsForSearch[i];
|
||||
var process = !that.options.searchFormTemplate && vObjCol && typeof vObjCol.process == 'function' ? vObjCol.process : null;
|
||||
if (obj.length > 1) {
|
||||
if (/BETWEEN$/.test(sym)) {
|
||||
var value_begin = $.trim($("[name='" + name + "']:first", that.$commonsearch).val()),
|
||||
value_end = $.trim($("[name='" + name + "']:last", that.$commonsearch).val());
|
||||
if (value_begin.length || value_end.length) {
|
||||
if (process) {
|
||||
value_begin = process(value_begin, 'begin');
|
||||
value_end = process(value_end, 'end');
|
||||
}
|
||||
value = value_begin + ',' + value_end;
|
||||
} else {
|
||||
value = '';
|
||||
}
|
||||
//如果是时间筛选,将operate置为RANGE
|
||||
if ($("[name='" + name + "']:first", that.$commonsearch).hasClass("datetimepicker")) {
|
||||
sym = 'RANGE';
|
||||
}
|
||||
} else {
|
||||
value = $("[name='" + name + "']:checked", that.$commonsearch).val();
|
||||
value = process ? process(value) : value;
|
||||
}
|
||||
} else {
|
||||
value = process ? process(obj.val()) : obj.val();
|
||||
}
|
||||
if (removeempty && (value === '' || value == null || ($.isArray(value) && value.length === 0)) && !sym.match(/null/i)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
op[name] = sym;
|
||||
filter[name] = value;
|
||||
});
|
||||
return {op: op, filter: filter};
|
||||
};
|
||||
|
||||
var getQueryParams = function (params, searchQuery, removeempty) {
|
||||
params.filter = typeof params.filter === 'Object' ? params.filter : (params.filter ? JSON.parse(params.filter) : {});
|
||||
params.op = typeof params.op === 'Object' ? params.op : (params.op ? JSON.parse(params.op) : {});
|
||||
|
||||
params.filter = $.extend({}, params.filter, searchQuery.filter);
|
||||
params.op = $.extend({}, params.op, searchQuery.op);
|
||||
//移除empty的值
|
||||
if (removeempty) {
|
||||
$.each(params.filter, function (i, j) {
|
||||
if ((j == '' || j == null || ($.isArray(j) && j.length == 0)) && !params.op[i].match(/null/i)) {
|
||||
delete params.filter[i];
|
||||
delete params.op[i];
|
||||
}
|
||||
});
|
||||
}
|
||||
params.filter = JSON.stringify(params.filter);
|
||||
params.op = JSON.stringify(params.op);
|
||||
return params;
|
||||
};
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
commonSearch: false,
|
||||
titleForm: "Common search",
|
||||
actionForm: "",
|
||||
searchFormTemplate: "",
|
||||
searchFormVisible: true,
|
||||
searchClass: 'searchit',
|
||||
showSearch: true,
|
||||
renderDefault: true,
|
||||
onCommonSearch: function (field, text) {
|
||||
return false;
|
||||
},
|
||||
onPostCommonSearch: function (table) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults.icons, {
|
||||
commonSearchIcon: 'glyphicon-search'
|
||||
});
|
||||
|
||||
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
|
||||
'common-search.bs.table': 'onCommonSearch',
|
||||
'post-common-search.bs.table': 'onPostCommonSearch'
|
||||
});
|
||||
$.extend($.fn.bootstrapTable.locales[$.fn.bootstrapTable.defaults.locale], {
|
||||
formatCommonSearch: function () {
|
||||
return "Common search";
|
||||
},
|
||||
formatCommonSubmitButton: function () {
|
||||
return "Search";
|
||||
},
|
||||
formatCommonResetButton: function () {
|
||||
return "Reset";
|
||||
},
|
||||
formatCommonCloseButton: function () {
|
||||
return "Close";
|
||||
},
|
||||
formatCommonChoose: function () {
|
||||
return "Choose";
|
||||
}
|
||||
});
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales);
|
||||
|
||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||
_initHeader = BootstrapTable.prototype.initHeader,
|
||||
_initToolbar = BootstrapTable.prototype.initToolbar,
|
||||
_load = BootstrapTable.prototype.load,
|
||||
_initSearch = BootstrapTable.prototype.initSearch;
|
||||
|
||||
BootstrapTable.prototype.initHeader = function () {
|
||||
_initHeader.apply(this, Array.prototype.slice.apply(arguments));
|
||||
this.$header.find('th[data-field]').each(function (i) {
|
||||
var column = $(this).data();
|
||||
if (typeof column['width'] !== 'undefined' && column['width'].toString().indexOf("%") === -1) {
|
||||
$(".th-inner", this).outerWidth(column['width']);
|
||||
$(this).css("max-width", column['width']);
|
||||
}
|
||||
});
|
||||
this.options.stateField = this.header.stateField;
|
||||
};
|
||||
BootstrapTable.prototype.initToolbar = function () {
|
||||
_initToolbar.apply(this, Array.prototype.slice.apply(arguments));
|
||||
|
||||
if (!isSearchAvailble(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this,
|
||||
html = [];
|
||||
if (that.options.showSearch) {
|
||||
html.push(sprintf('<div class="columns-%s pull-%s" style="margin-top:10px;margin-bottom:10px;">', this.options.buttonsAlign, this.options.buttonsAlign));
|
||||
html.push(sprintf('<button class="btn btn-default%s' + '" type="button" name="commonSearch" title="%s">', that.options.iconSize === undefined ? '' : ' btn-' + that.options.iconSize, that.options.formatCommonSearch()));
|
||||
html.push(sprintf('<i class="%s %s"></i>', that.options.iconsPrefix, that.options.icons.commonSearchIcon))
|
||||
html.push('</button></div>');
|
||||
}
|
||||
if (that.$toolbar.find(".pull-right").length > 0) {
|
||||
$(html.join('')).insertBefore(that.$toolbar.find(".pull-right:first"));
|
||||
} else {
|
||||
that.$toolbar.append(html.join(''));
|
||||
}
|
||||
|
||||
initCommonSearch(that.columns, that);
|
||||
|
||||
that.$toolbar.find('button[name="commonSearch"]')
|
||||
.off('click').on('click', function () {
|
||||
that.$commonsearch.toggleClass("hidden");
|
||||
return;
|
||||
});
|
||||
|
||||
that.$container.on("click", "." + that.options.searchClass, function () {
|
||||
var value = $(this).data("value");
|
||||
var field = $(this).data("field");
|
||||
var ul = that.$container.closest(".panel-intro").find("ul[data-field='" + field + "']");
|
||||
if (ul.length > 0) {
|
||||
$('li a[data-value="' + value + '"][data-toggle="tab"]', ul).trigger('click');
|
||||
return;
|
||||
}
|
||||
var obj = $("form [name='" + field + "']", that.$commonsearch);
|
||||
if (obj.length > 0) {
|
||||
if (obj.is("select")) {
|
||||
$("option[value='" + value + "']", obj).prop("selected", true);
|
||||
} else if (obj.length > 1) {
|
||||
$("form [name='" + field + "'][value='" + value + "']", that.$commonsearch).prop("checked", true);
|
||||
} else {
|
||||
obj.val(value + "");
|
||||
}
|
||||
obj.trigger("change");
|
||||
$("form", that.$commonsearch).trigger("submit");
|
||||
}
|
||||
});
|
||||
var queryParams = that.options.queryParams;
|
||||
//匹配默认搜索值
|
||||
this.options.queryParams = function (params) {
|
||||
return queryParams(getQueryParams(params, getSearchQuery(that, true)));
|
||||
};
|
||||
this.trigger('post-common-search', that);
|
||||
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.onCommonSearch = function () {
|
||||
var searchQuery = getSearchQuery(this);
|
||||
this.trigger('common-search', this, searchQuery);
|
||||
this.options.pageNumber = 1;
|
||||
//this.options.pageSize = $.fn.bootstrapTable.defaults.pageSize;
|
||||
this.refresh({});
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.load = function (data) {
|
||||
_load.apply(this, Array.prototype.slice.apply(arguments));
|
||||
|
||||
if (!isSearchAvailble(this)) {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.initSearch = function () {
|
||||
_initSearch.apply(this, Array.prototype.slice.apply(arguments));
|
||||
|
||||
if (!isSearchAvailble(this)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var that = this;
|
||||
var fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial;
|
||||
this.data = fp ? $.grep(this.data, function (item, i) {
|
||||
for (var key in fp) {
|
||||
var fval = fp[key].toLowerCase();
|
||||
var value = item[key];
|
||||
value = $.fn.bootstrapTable.utils.calculateObjectValue(that.header,
|
||||
that.header.formatters[$.inArray(key, that.header.fields)],
|
||||
[value, item, i], value);
|
||||
|
||||
if (!($.inArray(key, that.header.fields) !== -1 &&
|
||||
(typeof value === 'string' || typeof value === 'number') &&
|
||||
(value + '').toLowerCase().indexOf(fval) !== -1)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}) : this.data;
|
||||
};
|
||||
}(jQuery);
|
||||
74
public/assets/js/bootstrap-table-template.js
vendored
Normal file
74
public/assets/js/bootstrap-table-template.js
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
/**
|
||||
* 将BootstrapTable的行使用自定义的模板来渲染
|
||||
*
|
||||
* @author: karson
|
||||
* @version: v0.0.1
|
||||
*
|
||||
* @update 2017-06-24 <http://github.com/fastadminnet/fastadmin>
|
||||
*/
|
||||
|
||||
!function ($) {
|
||||
'use strict';
|
||||
|
||||
$.extend($.fn.bootstrapTable.defaults, {
|
||||
//是否启用模板渲染
|
||||
templateView: false,
|
||||
//数据格式化的模板ID或格式函数
|
||||
templateFormatter: "itemtpl",
|
||||
//添加的父类的class
|
||||
templateParentClass: "row row-flex",
|
||||
//向table添加的class
|
||||
templateTableClass: "table-template",
|
||||
|
||||
});
|
||||
|
||||
var BootstrapTable = $.fn.bootstrapTable.Constructor,
|
||||
_initContainer = BootstrapTable.prototype.initContainer,
|
||||
_initBody = BootstrapTable.prototype.initBody,
|
||||
_initRow = BootstrapTable.prototype.initRow;
|
||||
|
||||
BootstrapTable.prototype.initContainer = function () {
|
||||
_initContainer.apply(this, Array.prototype.slice.apply(arguments));
|
||||
var that = this;
|
||||
if (!that.options.templateView) {
|
||||
return;
|
||||
}
|
||||
that.options.cardView = true;
|
||||
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.initBody = function () {
|
||||
var that = this;
|
||||
$.extend(that.options, {
|
||||
showHeader: !that.options.templateView ? $.fn.bootstrapTable.defaults.showHeader : false,
|
||||
showFooter: !that.options.templateView ? $.fn.bootstrapTable.defaults.showFooter : false,
|
||||
});
|
||||
$(that.$el).toggleClass(that.options.templateTableClass, that.options.templateView);
|
||||
|
||||
_initBody.apply(this, Array.prototype.slice.apply(arguments));
|
||||
|
||||
if (!that.options.templateView) {
|
||||
return;
|
||||
} else {
|
||||
//由于Bootstrap是基于Table的,添加一个父类容器
|
||||
$("> *:not(.no-records-found)", that.$body).wrapAll($("<div />").addClass(that.options.templateParentClass));
|
||||
}
|
||||
};
|
||||
|
||||
BootstrapTable.prototype.initRow = function (item, i, data, parentDom) {
|
||||
var that = this;
|
||||
//如果未启用则使用原生的initRow方法
|
||||
if (!that.options.templateView) {
|
||||
return _initRow.apply(that, Array.prototype.slice.apply(arguments));
|
||||
}
|
||||
var $content = '';
|
||||
if (typeof that.options.templateFormatter === 'function') {
|
||||
$content = that.options.templateFormatter.call(that, item, i, data);
|
||||
} else {
|
||||
var Template = require('template');
|
||||
$content = Template(that.options.templateFormatter, {item: item, i: i, data: data});
|
||||
}
|
||||
return $content;
|
||||
};
|
||||
|
||||
}(jQuery);
|
||||
3851
public/assets/js/dropzone.js
Normal file
3851
public/assets/js/dropzone.js
Normal file
File diff suppressed because it is too large
Load Diff
1
public/assets/js/dropzone.min.js
vendored
Normal file
1
public/assets/js/dropzone.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
511
public/assets/js/echarts-theme.js
Normal file
511
public/assets/js/echarts-theme.js
Normal file
@@ -0,0 +1,511 @@
|
||||
(function (root, factory) {
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
// AMD. Register as an anonymous module.
|
||||
define(['exports', 'echarts'], factory);
|
||||
} else if (typeof exports === 'object' && typeof exports.nodeName !== 'string') {
|
||||
// CommonJS
|
||||
factory(exports, require('echarts'));
|
||||
} else {
|
||||
// Browser globals
|
||||
factory({}, root.echarts);
|
||||
}
|
||||
}(this, function (exports, echarts) {
|
||||
var log = function (msg) {
|
||||
if (typeof console !== 'undefined') {
|
||||
console && console.error && console.error(msg);
|
||||
}
|
||||
};
|
||||
if (!echarts) {
|
||||
log('ECharts is not Loaded');
|
||||
return;
|
||||
}
|
||||
echarts.registerTheme('walden', {
|
||||
"color": [
|
||||
"#3fb1e3",
|
||||
"#6be6c1",
|
||||
"#626c91",
|
||||
"#a0a7e6",
|
||||
"#c4ebad",
|
||||
"#96dee8"
|
||||
],
|
||||
"backgroundColor": "rgba(252,252,252,0)",
|
||||
"textStyle": {},
|
||||
"title": {
|
||||
"textStyle": {
|
||||
"color": "#666666"
|
||||
},
|
||||
"subtextStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"line": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": "2"
|
||||
}
|
||||
},
|
||||
"lineStyle": {
|
||||
"normal": {
|
||||
"width": "3"
|
||||
}
|
||||
},
|
||||
"symbolSize": "8",
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": false
|
||||
},
|
||||
"radar": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": "2"
|
||||
}
|
||||
},
|
||||
"lineStyle": {
|
||||
"normal": {
|
||||
"width": "3"
|
||||
}
|
||||
},
|
||||
"symbolSize": "8",
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": false
|
||||
},
|
||||
"bar": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"barBorderWidth": 0,
|
||||
"barBorderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"barBorderWidth": 0,
|
||||
"barBorderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"pie": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"scatter": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"boxplot": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parallel": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"sankey": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"funnel": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"gauge": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
}
|
||||
},
|
||||
"candlestick": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"color": "#e6a0d2",
|
||||
"color0": "transparent",
|
||||
"borderColor": "#e6a0d2",
|
||||
"borderColor0": "#3fb1e3",
|
||||
"borderWidth": "2"
|
||||
}
|
||||
}
|
||||
},
|
||||
"graph": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"borderWidth": 0,
|
||||
"borderColor": "#ccc"
|
||||
}
|
||||
},
|
||||
"lineStyle": {
|
||||
"normal": {
|
||||
"width": "1",
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"symbolSize": "8",
|
||||
"symbol": "emptyCircle",
|
||||
"smooth": false,
|
||||
"color": [
|
||||
"#3fb1e3",
|
||||
"#6be6c1",
|
||||
"#626c91",
|
||||
"#a0a7e6",
|
||||
"#c4ebad",
|
||||
"#96dee8"
|
||||
],
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#ffffff"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"map": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"areaColor": "#eeeeee",
|
||||
"borderColor": "#aaaaaa",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"emphasis": {
|
||||
"areaColor": "rgba(63,177,227,0.25)",
|
||||
"borderColor": "#3fb1e3",
|
||||
"borderWidth": 1
|
||||
}
|
||||
},
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#ffffff"
|
||||
}
|
||||
},
|
||||
"emphasis": {
|
||||
"textStyle": {
|
||||
"color": "rgb(63,177,227)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"geo": {
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"areaColor": "#eeeeee",
|
||||
"borderColor": "#aaaaaa",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"emphasis": {
|
||||
"areaColor": "rgba(63,177,227,0.25)",
|
||||
"borderColor": "#3fb1e3",
|
||||
"borderWidth": 1
|
||||
}
|
||||
},
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#ffffff"
|
||||
}
|
||||
},
|
||||
"emphasis": {
|
||||
"textStyle": {
|
||||
"color": "rgb(63,177,227)"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"categoryAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": [
|
||||
"#eeeeee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": [
|
||||
"rgba(250,250,250,0.05)",
|
||||
"rgba(200,200,200,0.02)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"valueAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": [
|
||||
"#eeeeee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": [
|
||||
"rgba(250,250,250,0.05)",
|
||||
"rgba(200,200,200,0.02)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"logAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": [
|
||||
"#eeeeee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": [
|
||||
"rgba(250,250,250,0.05)",
|
||||
"rgba(200,200,200,0.02)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeAxis": {
|
||||
"axisLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": "#cccccc"
|
||||
}
|
||||
},
|
||||
"axisTick": {
|
||||
"show": false,
|
||||
"lineStyle": {
|
||||
"color": "#333"
|
||||
}
|
||||
},
|
||||
"axisLabel": {
|
||||
"show": true,
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"splitLine": {
|
||||
"show": true,
|
||||
"lineStyle": {
|
||||
"color": [
|
||||
"#eeeeee"
|
||||
]
|
||||
}
|
||||
},
|
||||
"splitArea": {
|
||||
"show": false,
|
||||
"areaStyle": {
|
||||
"color": [
|
||||
"rgba(250,250,250,0.05)",
|
||||
"rgba(200,200,200,0.02)"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"toolbox": {
|
||||
"iconStyle": {
|
||||
"normal": {
|
||||
"borderColor": "#999999"
|
||||
},
|
||||
"emphasis": {
|
||||
"borderColor": "#666666"
|
||||
}
|
||||
}
|
||||
},
|
||||
"legend": {
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"axisPointer": {
|
||||
"lineStyle": {
|
||||
"color": "#cccccc",
|
||||
"width": 1
|
||||
},
|
||||
"crossStyle": {
|
||||
"color": "#cccccc",
|
||||
"width": 1
|
||||
}
|
||||
}
|
||||
},
|
||||
"timeline": {
|
||||
"lineStyle": {
|
||||
"color": "#626c91",
|
||||
"width": 1
|
||||
},
|
||||
"itemStyle": {
|
||||
"normal": {
|
||||
"color": "#626c91",
|
||||
"borderWidth": 1
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#626c91"
|
||||
}
|
||||
},
|
||||
"controlStyle": {
|
||||
"normal": {
|
||||
"color": "#626c91",
|
||||
"borderColor": "#626c91",
|
||||
"borderWidth": 0.5
|
||||
},
|
||||
"emphasis": {
|
||||
"color": "#626c91",
|
||||
"borderColor": "#626c91",
|
||||
"borderWidth": 0.5
|
||||
}
|
||||
},
|
||||
"checkpointStyle": {
|
||||
"color": "#3fb1e3",
|
||||
"borderColor": "rgba(63,177,227,0.15)"
|
||||
},
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#626c91"
|
||||
}
|
||||
},
|
||||
"emphasis": {
|
||||
"textStyle": {
|
||||
"color": "#626c91"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"visualMap": {
|
||||
"color": [
|
||||
"#2a99c9",
|
||||
"#afe8ff"
|
||||
]
|
||||
},
|
||||
"dataZoom": {
|
||||
"backgroundColor": "rgba(255,255,255,0)",
|
||||
"dataBackgroundColor": "rgba(222,222,222,1)",
|
||||
"fillerColor": "rgba(114,230,212,0.25)",
|
||||
"handleColor": "#cccccc",
|
||||
"handleSize": "100%",
|
||||
"textStyle": {
|
||||
"color": "#999999"
|
||||
}
|
||||
},
|
||||
"markPoint": {
|
||||
"label": {
|
||||
"normal": {
|
||||
"textStyle": {
|
||||
"color": "#ffffff"
|
||||
}
|
||||
},
|
||||
"emphasis": {
|
||||
"textStyle": {
|
||||
"color": "#ffffff"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}));
|
||||
22
public/assets/js/echarts.min.js
vendored
Normal file
22
public/assets/js/echarts.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
389
public/assets/js/fast.js
Normal file
389
public/assets/js/fast.js
Normal file
@@ -0,0 +1,389 @@
|
||||
define(['jquery', 'bootstrap', 'toastr', 'layer', 'lang'], function ($, undefined, Toastr, Layer, Lang) {
|
||||
var Fast = {
|
||||
config: {
|
||||
//toastr默认配置
|
||||
toastr: {
|
||||
"closeButton": true,
|
||||
"debug": false,
|
||||
"newestOnTop": false,
|
||||
"progressBar": false,
|
||||
"positionClass": "toast-top-center",
|
||||
"preventDuplicates": false,
|
||||
"onclick": null,
|
||||
"showDuration": "300",
|
||||
"hideDuration": "1000",
|
||||
"timeOut": "5000",
|
||||
"extendedTimeOut": "1000",
|
||||
"showEasing": "swing",
|
||||
"hideEasing": "linear",
|
||||
"showMethod": "fadeIn",
|
||||
"hideMethod": "fadeOut"
|
||||
}
|
||||
},
|
||||
events: {
|
||||
//请求成功的回调
|
||||
onAjaxSuccess: function (ret, onAjaxSuccess) {
|
||||
var data = typeof ret.data !== 'undefined' ? ret.data : null;
|
||||
var msg = typeof ret.msg !== 'undefined' && ret.msg ? ret.msg : __('Operation completed');
|
||||
|
||||
if (typeof onAjaxSuccess === 'function') {
|
||||
var result = onAjaxSuccess.call(this, data, ret);
|
||||
if (result === false)
|
||||
return;
|
||||
}
|
||||
Toastr.success(msg);
|
||||
},
|
||||
//请求错误的回调
|
||||
onAjaxError: function (ret, onAjaxError) {
|
||||
var data = typeof ret.data !== 'undefined' ? ret.data : null;
|
||||
if (typeof onAjaxError === 'function') {
|
||||
var result = onAjaxError.call(this, data, ret);
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Toastr.error(ret.msg);
|
||||
},
|
||||
//服务器响应数据后
|
||||
onAjaxResponse: function (response) {
|
||||
try {
|
||||
var ret = typeof response === 'object' ? response : JSON.parse(response);
|
||||
if (!ret.hasOwnProperty('code')) {
|
||||
$.extend(ret, {code: -2, msg: response, data: null});
|
||||
}
|
||||
} catch (e) {
|
||||
var ret = {code: -1, msg: e.message, data: null};
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
},
|
||||
api: {
|
||||
//发送Ajax请求
|
||||
ajax: function (options, success, error) {
|
||||
options = typeof options === 'string' ? {url: options} : options;
|
||||
var index;
|
||||
if (typeof options.loading === 'undefined' || options.loading) {
|
||||
index = Layer.load(options.loading || 0);
|
||||
}
|
||||
options = $.extend({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
xhrFields: {
|
||||
withCredentials: true
|
||||
},
|
||||
success: function (ret) {
|
||||
index && Layer.close(index);
|
||||
ret = Fast.events.onAjaxResponse(ret);
|
||||
if (ret.code === 1) {
|
||||
Fast.events.onAjaxSuccess(ret, success);
|
||||
} else {
|
||||
Fast.events.onAjaxError(ret, error);
|
||||
}
|
||||
},
|
||||
error: function (xhr) {
|
||||
index && Layer.close(index);
|
||||
var ret = {code: xhr.status, msg: xhr.statusText, data: null};
|
||||
Fast.events.onAjaxError(ret, error);
|
||||
}
|
||||
}, options);
|
||||
return $.ajax(options);
|
||||
},
|
||||
//修复URL
|
||||
fixurl: function (url) {
|
||||
if (url.substr(0, 1) !== "/") {
|
||||
var r = new RegExp('^(?:[a-z]+:)?//', 'i');
|
||||
if (!r.test(url)) {
|
||||
url = Config.moduleurl + "/" + url;
|
||||
}
|
||||
} else if (url.substr(0, 8) === "/addons/") {
|
||||
url = Config.__PUBLIC__.replace(/(\/*$)/g, "") + url;
|
||||
}
|
||||
return url;
|
||||
},
|
||||
//获取修复后可访问的cdn链接
|
||||
cdnurl: function (url, domain) {
|
||||
var rule = new RegExp("^((?:[a-z]+:)?\\/\\/|data:image\\/)", "i");
|
||||
var cdnurl = Config.upload.cdnurl;
|
||||
if (typeof domain === 'undefined' || domain === true || cdnurl.indexOf("/") === 0) {
|
||||
url = rule.test(url) || (cdnurl && url.indexOf(cdnurl) === 0) ? url : cdnurl + url;
|
||||
}
|
||||
if (domain && !rule.test(url)) {
|
||||
domain = typeof domain === 'string' ? domain : location.origin;
|
||||
url = domain + url;
|
||||
}
|
||||
return url;
|
||||
},
|
||||
//查询Url参数
|
||||
query: function (name, url) {
|
||||
if (!url) {
|
||||
url = window.location.href;
|
||||
}
|
||||
if (!name)
|
||||
return '';
|
||||
name = name.replace(/[\[\]]/g, "\\$&");
|
||||
var regex = new RegExp("[?&/]" + name + "([=/]([^&#/?]*)|&|#|$)"),
|
||||
results = regex.exec(url);
|
||||
if (!results)
|
||||
return null;
|
||||
if (!results[2])
|
||||
return '';
|
||||
return decodeURIComponent(results[2].replace(/\+/g, " "));
|
||||
},
|
||||
//打开一个弹出窗口
|
||||
open: function (url, title, options) {
|
||||
title = options && options.title ? options.title : (title ? title : "");
|
||||
url = Fast.api.fixurl(url);
|
||||
url = url + (url.indexOf("?") > -1 ? "&" : "?") + "dialog=1";
|
||||
var area = Fast.config.openArea != undefined ? Fast.config.openArea : [$(window).width() > 800 ? '800px' : '95%', $(window).height() > 600 ? '600px' : '95%'];
|
||||
var success = options && typeof options.success === 'function' ? options.success : $.noop;
|
||||
if (options && typeof options.success === 'function') {
|
||||
delete options.success;
|
||||
}
|
||||
options = $.extend({
|
||||
type: 2,
|
||||
title: title,
|
||||
shadeClose: true,
|
||||
shade: false,
|
||||
maxmin: true,
|
||||
moveOut: true,
|
||||
area: area,
|
||||
content: url,
|
||||
zIndex: Layer.zIndex,
|
||||
success: function (layero, index) {
|
||||
var that = this;
|
||||
//存储callback事件
|
||||
$(layero).data("callback", that.callback);
|
||||
//$(layero).removeClass("layui-layer-border");
|
||||
Layer.setTop(layero);
|
||||
try {
|
||||
var frame = Layer.getChildFrame('html', index);
|
||||
var layerfooter = frame.find(".layer-footer");
|
||||
Fast.api.layerfooter(layero, index, that);
|
||||
|
||||
//绑定事件
|
||||
if (layerfooter.length > 0) {
|
||||
// 监听窗口内的元素及属性变化
|
||||
// Firefox和Chrome早期版本中带有前缀
|
||||
var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
|
||||
if (MutationObserver) {
|
||||
// 选择目标节点
|
||||
var target = layerfooter[0];
|
||||
// 创建观察者对象
|
||||
var observer = new MutationObserver(function (mutations) {
|
||||
Fast.api.layerfooter(layero, index, that);
|
||||
mutations.forEach(function (mutation) {
|
||||
});
|
||||
});
|
||||
// 配置观察选项:
|
||||
var config = {attributes: true, childList: true, characterData: true, subtree: true}
|
||||
// 传入目标节点和观察选项
|
||||
observer.observe(target, config);
|
||||
// 随后,你还可以停止观察
|
||||
// observer.disconnect();
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
|
||||
}
|
||||
if ($(layero).height() > $(window).height()) {
|
||||
//当弹出窗口大于浏览器可视高度时,重定位
|
||||
Layer.style(index, {
|
||||
top: 0,
|
||||
height: $(window).height()
|
||||
});
|
||||
}
|
||||
success.call(this, layero, index);
|
||||
}
|
||||
}, options ? options : {});
|
||||
if ($(window).width() < 480 || (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream && top.$(".tab-pane.active").length > 0)) {
|
||||
if (top.$(".tab-pane.active").length > 0) {
|
||||
options.area = [top.$(".tab-pane.active").width() + "px", top.$(".tab-pane.active").height() + "px"];
|
||||
options.offset = [top.$(".tab-pane.active").scrollTop() + "px", "0px"];
|
||||
} else {
|
||||
options.area = [$(window).width() + "px", $(window).height() + "px"];
|
||||
options.offset = ["0px", "0px"];
|
||||
}
|
||||
}
|
||||
return Layer.open(options);
|
||||
},
|
||||
//关闭窗口并回传数据
|
||||
close: function (data) {
|
||||
var index = parent.Layer.getFrameIndex(window.name);
|
||||
var callback = parent.$("#layui-layer" + index).data("callback");
|
||||
//再执行关闭
|
||||
parent.Layer.close(index);
|
||||
//再调用回传函数
|
||||
if (typeof callback === 'function') {
|
||||
callback.call(undefined, data);
|
||||
}
|
||||
},
|
||||
layerfooter: function (layero, index, that) {
|
||||
var frame = Layer.getChildFrame('html', index);
|
||||
var layerfooter = frame.find(".layer-footer");
|
||||
if (layerfooter.length > 0) {
|
||||
$(".layui-layer-footer", layero).remove();
|
||||
var footer = $("<div />").addClass('layui-layer-btn layui-layer-footer');
|
||||
footer.html(layerfooter.html());
|
||||
if ($(".row", footer).length === 0) {
|
||||
$(">", footer).wrapAll("<div class='row'></div>");
|
||||
}
|
||||
footer.insertAfter(layero.find('.layui-layer-content'));
|
||||
//绑定事件
|
||||
footer.on("click", ".btn", function () {
|
||||
if ($(this).hasClass("disabled") || $(this).parent().hasClass("disabled")) {
|
||||
return;
|
||||
}
|
||||
var index = footer.find('.btn').index(this);
|
||||
$(".btn:eq(" + index + ")", layerfooter).trigger("click");
|
||||
});
|
||||
|
||||
var titHeight = layero.find('.layui-layer-title').outerHeight() || 0;
|
||||
var btnHeight = layero.find('.layui-layer-btn').outerHeight() || 0;
|
||||
//重设iframe高度
|
||||
$("iframe", layero).height(layero.height() - titHeight - btnHeight);
|
||||
}
|
||||
//修复iOS下弹出窗口的高度和iOS下iframe无法滚动的BUG
|
||||
if (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream) {
|
||||
var titHeight = layero.find('.layui-layer-title').outerHeight() || 0;
|
||||
var btnHeight = layero.find('.layui-layer-btn').outerHeight() || 0;
|
||||
$("iframe", layero).parent().css("height", layero.height() - titHeight - btnHeight);
|
||||
$("iframe", layero).css("height", "100%");
|
||||
}
|
||||
},
|
||||
success: function (options, callback) {
|
||||
var type = typeof options === 'function';
|
||||
if (type) {
|
||||
callback = options;
|
||||
}
|
||||
return Layer.msg(__('Operation completed'), $.extend({
|
||||
offset: 0, icon: 1
|
||||
}, type ? {} : options), callback);
|
||||
},
|
||||
error: function (options, callback) {
|
||||
var type = typeof options === 'function';
|
||||
if (type) {
|
||||
callback = options;
|
||||
}
|
||||
return Layer.msg(__('Operation failed'), $.extend({
|
||||
offset: 0, icon: 2
|
||||
}, type ? {} : options), callback);
|
||||
},
|
||||
msg: function (message, url) {
|
||||
var callback = typeof url === 'function' ? url : function () {
|
||||
if (typeof url !== 'undefined' && url) {
|
||||
location.href = url;
|
||||
}
|
||||
};
|
||||
Layer.msg(message, {
|
||||
time: 2000
|
||||
}, callback);
|
||||
},
|
||||
escape: function (text) {
|
||||
if (typeof text === 'string') {
|
||||
return text
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>')
|
||||
.replace(/"/g, '"')
|
||||
.replace(/'/g, ''')
|
||||
.replace(/`/g, '`');
|
||||
}
|
||||
return text;
|
||||
},
|
||||
toastr: Toastr,
|
||||
layer: Layer
|
||||
},
|
||||
lang: function () {
|
||||
var args = arguments,
|
||||
string = args[0],
|
||||
i = 1;
|
||||
string = string.toLowerCase();
|
||||
//string = typeof Lang[string] != 'undefined' ? Lang[string] : string;
|
||||
if (typeof Lang !== 'undefined' && typeof Lang[string] !== 'undefined') {
|
||||
if (typeof Lang[string] == 'object')
|
||||
return Lang[string];
|
||||
string = Lang[string];
|
||||
} else if (string.indexOf('.') !== -1 && false) {
|
||||
var arr = string.split('.');
|
||||
var current = Lang[arr[0]];
|
||||
for (var i = 1; i < arr.length; i++) {
|
||||
current = typeof current[arr[i]] != 'undefined' ? current[arr[i]] : '';
|
||||
if (typeof current != 'object')
|
||||
break;
|
||||
}
|
||||
if (typeof current == 'object')
|
||||
return current;
|
||||
string = current;
|
||||
} else {
|
||||
string = args[0];
|
||||
}
|
||||
return string.replace(/%((%)|s|d)/g, function (m) {
|
||||
// m is the matched format, e.g. %s, %d
|
||||
var val = null;
|
||||
if (m[2]) {
|
||||
val = m[2];
|
||||
} else {
|
||||
val = args[i];
|
||||
// A switch statement so that the formatter can be extended. Default is %s
|
||||
switch (m) {
|
||||
case '%d':
|
||||
val = parseFloat(val);
|
||||
if (isNaN(val)) {
|
||||
val = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return val;
|
||||
});
|
||||
},
|
||||
init: function () {
|
||||
// jQuery兼容处理
|
||||
$.fn.extend({
|
||||
size: function () {
|
||||
return $(this).length;
|
||||
}
|
||||
});
|
||||
// 对相对地址进行处理
|
||||
$.ajaxSetup({
|
||||
beforeSend: function (xhr, setting) {
|
||||
setting.url = Fast.api.fixurl(setting.url);
|
||||
}
|
||||
});
|
||||
Layer.config({
|
||||
skin: 'layui-layer-fast'
|
||||
});
|
||||
// 绑定ESC关闭窗口事件
|
||||
$(window).keyup(function (e) {
|
||||
if (e.keyCode == 27) {
|
||||
if ($(".layui-layer").length > 0) {
|
||||
var index = 0;
|
||||
$(".layui-layer").each(function () {
|
||||
index = Math.max(index, parseInt($(this).attr("times")));
|
||||
});
|
||||
if (index) {
|
||||
Layer.close(index);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
//公共代码
|
||||
//配置Toastr的参数
|
||||
Toastr.options = Fast.config.toastr;
|
||||
}
|
||||
};
|
||||
//将Layer暴露到全局中去
|
||||
window.Layer = Layer;
|
||||
//将Toastr暴露到全局中去
|
||||
window.Toastr = Toastr;
|
||||
//将语言方法暴露到全局中去
|
||||
window.__ = Fast.lang;
|
||||
//将Fast渲染至全局
|
||||
window.Fast = Fast;
|
||||
|
||||
//默认初始化执行的代码
|
||||
Fast.init();
|
||||
return Fast;
|
||||
});
|
||||
3
public/assets/js/frontend-init.js
Normal file
3
public/assets/js/frontend-init.js
Normal file
@@ -0,0 +1,3 @@
|
||||
define(['frontend'], function (Frontend) {
|
||||
|
||||
});
|
||||
115
public/assets/js/frontend.js
Normal file
115
public/assets/js/frontend.js
Normal file
@@ -0,0 +1,115 @@
|
||||
define(['fast', 'template', 'moment'], function (Fast, Template, Moment) {
|
||||
var Frontend = {
|
||||
api: Fast.api,
|
||||
init: function () {
|
||||
var si = {};
|
||||
//发送验证码
|
||||
$(document).on("click", ".btn-captcha", function (e) {
|
||||
var type = $(this).data("type") ? $(this).data("type") : 'mobile';
|
||||
var btn = this;
|
||||
Frontend.api.sendcaptcha = function (btn, type, data, callback) {
|
||||
$(btn).addClass("disabled", true).text("发送中...");
|
||||
|
||||
Frontend.api.ajax({url: $(btn).data("url"), data: data}, function (data, ret) {
|
||||
clearInterval(si[type]);
|
||||
var seconds = 60;
|
||||
si[type] = setInterval(function () {
|
||||
seconds--;
|
||||
if (seconds <= 0) {
|
||||
clearInterval(si);
|
||||
$(btn).removeClass("disabled").text("发送验证码");
|
||||
} else {
|
||||
$(btn).addClass("disabled").text(seconds + "秒后可再次发送");
|
||||
}
|
||||
}, 1000);
|
||||
if (typeof callback == 'function') {
|
||||
callback.call(this, data, ret);
|
||||
}
|
||||
}, function () {
|
||||
$(btn).removeClass("disabled").text('发送验证码');
|
||||
});
|
||||
};
|
||||
if (['mobile', 'email'].indexOf(type) > -1) {
|
||||
var element = $(this).data("input-id") ? $("#" + $(this).data("input-id")) : $("input[name='" + type + "']", $(this).closest("form"));
|
||||
var text = type === 'email' ? '邮箱' : '手机号码';
|
||||
if (element.val() === "") {
|
||||
Layer.msg(text + "不能为空!");
|
||||
element.focus();
|
||||
return false;
|
||||
} else if (type === 'mobile' && !element.val().match(/^1[3-9]\d{9}$/)) {
|
||||
Layer.msg("请输入正确的" + text + "!");
|
||||
element.focus();
|
||||
return false;
|
||||
} else if (type === 'email' && !element.val().match(/^[\w\+\-]+(\.[\w\+\-]+)*@[a-z\d\-]+(\.[a-z\d\-]+)*\.([a-z]{2,4})$/)) {
|
||||
Layer.msg("请输入正确的" + text + "!");
|
||||
element.focus();
|
||||
return false;
|
||||
}
|
||||
element.isValid(function (v) {
|
||||
if (v) {
|
||||
var data = {event: $(btn).data("event")};
|
||||
data[type] = element.val();
|
||||
Frontend.api.sendcaptcha(btn, type, data);
|
||||
} else {
|
||||
Layer.msg("请确认已经输入了正确的" + text + "!");
|
||||
}
|
||||
});
|
||||
} else {
|
||||
var data = {event: $(btn).data("event")};
|
||||
Frontend.api.sendcaptcha(btn, type, data, function (data, ret) {
|
||||
Layer.open({title: false, area: ["400px", "430px"], content: "<img src='" + data.image + "' width='400' height='400' /><div class='text-center panel-title'>扫一扫关注公众号获取验证码</div>", type: 1});
|
||||
});
|
||||
}
|
||||
return false;
|
||||
});
|
||||
//tooltip和popover
|
||||
if (!('ontouchstart' in document.documentElement)) {
|
||||
$('body').tooltip({selector: '[data-toggle="tooltip"]'});
|
||||
}
|
||||
$('body').popover({selector: '[data-toggle="popover"]'});
|
||||
|
||||
// 手机端左右滑动切换菜单栏
|
||||
if ('ontouchstart' in document.documentElement) {
|
||||
var startX, startY, moveEndX, moveEndY, relativeX, relativeY, element;
|
||||
element = $('body', document);
|
||||
element.on("touchstart", function (e) {
|
||||
startX = e.originalEvent.changedTouches[0].pageX;
|
||||
startY = e.originalEvent.changedTouches[0].pageY;
|
||||
});
|
||||
element.on("touchend", function (e) {
|
||||
moveEndX = e.originalEvent.changedTouches[0].pageX;
|
||||
moveEndY = e.originalEvent.changedTouches[0].pageY;
|
||||
relativeX = moveEndX - startX;
|
||||
relativeY = moveEndY - startY;
|
||||
|
||||
// 判断标准
|
||||
//右滑
|
||||
if (relativeX > 45) {
|
||||
if ((Math.abs(relativeX) - Math.abs(relativeY)) > 50) {
|
||||
element.addClass("sidebar-open");
|
||||
}
|
||||
}
|
||||
//左滑
|
||||
else if (relativeX < -45) {
|
||||
if ((Math.abs(relativeX) - Math.abs(relativeY)) > 50) {
|
||||
element.removeClass("sidebar-open");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
$(document).on("click", ".sidebar-toggle", function () {
|
||||
$("body").toggleClass("sidebar-open");
|
||||
});
|
||||
}
|
||||
};
|
||||
Frontend.api = $.extend(Fast.api, Frontend.api);
|
||||
//将Template渲染至全局,以便于在子框架中调用
|
||||
window.Template = Template;
|
||||
//将Moment渲染至全局,以便于在子框架中调用
|
||||
window.Moment = Moment;
|
||||
//将Frontend渲染至全局,以便于在子框架中调用
|
||||
window.Frontend = Frontend;
|
||||
|
||||
Frontend.init();
|
||||
return Frontend;
|
||||
});
|
||||
195
public/assets/js/frontend/user.js
Normal file
195
public/assets/js/frontend/user.js
Normal file
@@ -0,0 +1,195 @@
|
||||
define(['jquery', 'bootstrap', 'frontend', 'form', 'template'], function ($, undefined, Frontend, Form, Template) {
|
||||
var validatoroptions = {
|
||||
invalid: function (form, errors) {
|
||||
$.each(errors, function (i, j) {
|
||||
Layer.msg(j);
|
||||
});
|
||||
}
|
||||
};
|
||||
var Controller = {
|
||||
login: function () {
|
||||
|
||||
//本地验证未通过时提示
|
||||
$("#login-form").data("validator-options", validatoroptions);
|
||||
|
||||
//为表单绑定事件
|
||||
Form.api.bindevent($("#login-form"), function (data, ret) {
|
||||
setTimeout(function () {
|
||||
location.href = ret.url ? ret.url : "/";
|
||||
}, 1000);
|
||||
});
|
||||
|
||||
//忘记密码
|
||||
$(document).on("click", ".btn-forgot", function () {
|
||||
var id = "resetpwdtpl";
|
||||
var content = Template(id, {});
|
||||
Layer.open({
|
||||
type: 1,
|
||||
title: __('Reset password'),
|
||||
area: [$(window).width() < 450 ? ($(window).width() - 10) + "px" : "450px", "355px"],
|
||||
content: content,
|
||||
success: function (layero) {
|
||||
var rule = $("#resetpwd-form input[name='captcha']").data("rule");
|
||||
Form.api.bindevent($("#resetpwd-form", layero), function (data) {
|
||||
Layer.closeAll();
|
||||
});
|
||||
$(layero).on("change", "input[name=type]", function () {
|
||||
var type = $(this).val();
|
||||
$("div.form-group[data-type]").addClass("hide");
|
||||
$("div.form-group[data-type='" + type + "']").removeClass("hide");
|
||||
$('#resetpwd-form').validator("setField", {
|
||||
captcha: rule.replace(/remote\((.*)\)/, "remote(" + $(this).data("check-url") + ", event=resetpwd, " + type + ":#" + type + ")")
|
||||
});
|
||||
$(".btn-captcha").data("url", $(this).data("send-url")).data("type", type);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
register: function () {
|
||||
//本地验证未通过时提示
|
||||
$("#register-form").data("validator-options", validatoroptions);
|
||||
|
||||
//为表单绑定事件
|
||||
Form.api.bindevent($("#register-form"), function (data, ret) {
|
||||
setTimeout(function () {
|
||||
location.href = ret.url ? ret.url : "/";
|
||||
}, 1000);
|
||||
}, function (data) {
|
||||
$("input[name=captcha]").next(".input-group-btn").find("img").trigger("click");
|
||||
});
|
||||
},
|
||||
changepwd: function () {
|
||||
//本地验证未通过时提示
|
||||
$("#changepwd-form").data("validator-options", validatoroptions);
|
||||
|
||||
//为表单绑定事件
|
||||
Form.api.bindevent($("#changepwd-form"), function (data, ret) {
|
||||
setTimeout(function () {
|
||||
location.href = ret.url ? ret.url : "/";
|
||||
}, 1000);
|
||||
});
|
||||
},
|
||||
profile: function () {
|
||||
// 给上传按钮添加上传成功事件
|
||||
$("#faupload-avatar").data("upload-success", function (data) {
|
||||
var url = Fast.api.cdnurl(data.url);
|
||||
$(".profile-user-img").prop("src", url);
|
||||
Toastr.success(__('Uploaded successful'));
|
||||
});
|
||||
Form.api.bindevent($("#profile-form"));
|
||||
$(document).on("click", ".btn-change", function () {
|
||||
var that = this;
|
||||
var id = $(this).data("type") + "tpl";
|
||||
var content = Template(id, {});
|
||||
Layer.open({
|
||||
type: 1,
|
||||
title: "修改",
|
||||
area: [$(window).width() < 450 ? ($(window).width() - 10) + "px" : "450px", "355px"],
|
||||
content: content,
|
||||
success: function (layero) {
|
||||
var form = $("form", layero);
|
||||
Form.api.bindevent(form, function (data) {
|
||||
location.reload();
|
||||
Layer.closeAll();
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
attachment: function () {
|
||||
require(['table'], function (Table) {
|
||||
|
||||
// 初始化表格参数配置
|
||||
Table.api.init({
|
||||
extend: {
|
||||
index_url: 'user/attachment',
|
||||
}
|
||||
});
|
||||
var urlArr = [];
|
||||
var multiple = Fast.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,
|
||||
fixedColumns: true,
|
||||
fixedRightNumber: 1,
|
||||
columns: [
|
||||
[
|
||||
{field: 'state', checkbox: multiple, visible: multiple, operate: false},
|
||||
{field: 'id', title: __('Id'), operate: false},
|
||||
{
|
||||
field: 'url', title: __('Preview'), formatter: 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>';
|
||||
}
|
||||
},
|
||||
{
|
||||
field: 'filename', title: __('Filename'), formatter: 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>';
|
||||
}, operate: 'like'
|
||||
},
|
||||
{field: 'imagewidth', title: __('Imagewidth'), operate: false},
|
||||
{field: 'imageheight', title: __('Imageheight'), operate: false},
|
||||
{field: 'mimetype', title: __('Mimetype'), formatter: Table.api.formatter.search},
|
||||
{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({url: row.url, multiple: multiple});
|
||||
},
|
||||
}, formatter: function () {
|
||||
return '<a href="javascript:;" class="btn btn-danger btn-chooseone btn-xs"><i class="fa fa-check"></i> ' + __('Choose') + '</a>';
|
||||
}
|
||||
}
|
||||
]
|
||||
]
|
||||
});
|
||||
|
||||
// 选中多个
|
||||
$(document).on("click", ".btn-choose-multi", function () {
|
||||
Fast.api.close({url: urlArr.join(","), multiple: multiple});
|
||||
});
|
||||
|
||||
// 为表格绑定事件
|
||||
Table.api.bindevent(table);
|
||||
require(['upload'], function (Upload) {
|
||||
Upload.api.upload($("#toolbar .faupload"), function () {
|
||||
$(".btn-refresh").trigger("click");
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
};
|
||||
return Controller;
|
||||
});
|
||||
322
public/assets/js/html5shiv.js
vendored
Normal file
322
public/assets/js/html5shiv.js
vendored
Normal file
@@ -0,0 +1,322 @@
|
||||
/**
|
||||
* @preserve HTML5 Shiv 3.7.2 | @afarkas @jdalton @jon_neal @rem | MIT/GPL2 Licensed
|
||||
*/
|
||||
;(function(window, document) {
|
||||
/*jshint evil:true */
|
||||
/** version */
|
||||
var version = '3.7.2';
|
||||
|
||||
/** Preset options */
|
||||
var options = window.html5 || {};
|
||||
|
||||
/** Used to skip problem elements */
|
||||
var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
|
||||
|
||||
/** Not all elements can be cloned in IE **/
|
||||
var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
|
||||
|
||||
/** Detect whether the browser supports default html5 styles */
|
||||
var supportsHtml5Styles;
|
||||
|
||||
/** Name of the expando, to work with multiple documents or to re-shiv one document */
|
||||
var expando = '_html5shiv';
|
||||
|
||||
/** The id for the the documents expando */
|
||||
var expanID = 0;
|
||||
|
||||
/** Cached data for each document */
|
||||
var expandoData = {};
|
||||
|
||||
/** Detect whether the browser supports unknown elements */
|
||||
var supportsUnknownElements;
|
||||
|
||||
(function() {
|
||||
try {
|
||||
var a = document.createElement('a');
|
||||
a.innerHTML = '<xyz></xyz>';
|
||||
//if the hidden property is implemented we can assume, that the browser supports basic HTML5 Styles
|
||||
supportsHtml5Styles = ('hidden' in a);
|
||||
|
||||
supportsUnknownElements = a.childNodes.length == 1 || (function() {
|
||||
// assign a false positive if unable to shiv
|
||||
(document.createElement)('a');
|
||||
var frag = document.createDocumentFragment();
|
||||
return (
|
||||
typeof frag.cloneNode == 'undefined' ||
|
||||
typeof frag.createDocumentFragment == 'undefined' ||
|
||||
typeof frag.createElement == 'undefined'
|
||||
);
|
||||
}());
|
||||
} catch(e) {
|
||||
// assign a false positive if detection fails => unable to shiv
|
||||
supportsHtml5Styles = true;
|
||||
supportsUnknownElements = true;
|
||||
}
|
||||
|
||||
}());
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Creates a style sheet with the given CSS text and adds it to the document.
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @param {String} cssText The CSS text.
|
||||
* @returns {StyleSheet} The style element.
|
||||
*/
|
||||
function addStyleSheet(ownerDocument, cssText) {
|
||||
var p = ownerDocument.createElement('p'),
|
||||
parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
|
||||
|
||||
p.innerHTML = 'x<style>' + cssText + '</style>';
|
||||
return parent.insertBefore(p.lastChild, parent.firstChild);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the value of `html5.elements` as an array.
|
||||
* @private
|
||||
* @returns {Array} An array of shived element node names.
|
||||
*/
|
||||
function getElements() {
|
||||
var elements = html5.elements;
|
||||
return typeof elements == 'string' ? elements.split(' ') : elements;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extends the built-in list of html5 elements
|
||||
* @memberOf html5
|
||||
* @param {String|Array} newElements whitespace separated list or array of new element names to shiv
|
||||
* @param {Document} ownerDocument The context document.
|
||||
*/
|
||||
function addElements(newElements, ownerDocument) {
|
||||
var elements = html5.elements;
|
||||
if(typeof elements != 'string'){
|
||||
elements = elements.join(' ');
|
||||
}
|
||||
if(typeof newElements != 'string'){
|
||||
newElements = newElements.join(' ');
|
||||
}
|
||||
html5.elements = elements +' '+ newElements;
|
||||
shivDocument(ownerDocument);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the data associated to the given document
|
||||
* @private
|
||||
* @param {Document} ownerDocument The document.
|
||||
* @returns {Object} An object of data.
|
||||
*/
|
||||
function getExpandoData(ownerDocument) {
|
||||
var data = expandoData[ownerDocument[expando]];
|
||||
if (!data) {
|
||||
data = {};
|
||||
expanID++;
|
||||
ownerDocument[expando] = expanID;
|
||||
expandoData[expanID] = data;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived element for the given nodeName and document
|
||||
* @memberOf html5
|
||||
* @param {String} nodeName name of the element
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived element.
|
||||
*/
|
||||
function createElement(nodeName, ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createElement(nodeName);
|
||||
}
|
||||
if (!data) {
|
||||
data = getExpandoData(ownerDocument);
|
||||
}
|
||||
var node;
|
||||
|
||||
if (data.cache[nodeName]) {
|
||||
node = data.cache[nodeName].cloneNode();
|
||||
} else if (saveClones.test(nodeName)) {
|
||||
node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
|
||||
} else {
|
||||
node = data.createElem(nodeName);
|
||||
}
|
||||
|
||||
// Avoid adding some elements to fragments in IE < 9 because
|
||||
// * Attributes like `name` or `type` cannot be set/changed once an element
|
||||
// is inserted into a document/fragment
|
||||
// * Link elements with `src` attributes that are inaccessible, as with
|
||||
// a 403 response, will cause the tab/window to crash
|
||||
// * Script elements appended to fragments will execute when their `src`
|
||||
// or `text` property is set
|
||||
return node.canHaveChildren && !reSkip.test(nodeName) && !node.tagUrn ? data.frag.appendChild(node) : node;
|
||||
}
|
||||
|
||||
/**
|
||||
* returns a shived DocumentFragment for the given document
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The context document.
|
||||
* @returns {Object} The shived DocumentFragment.
|
||||
*/
|
||||
function createDocumentFragment(ownerDocument, data){
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
if(supportsUnknownElements){
|
||||
return ownerDocument.createDocumentFragment();
|
||||
}
|
||||
data = data || getExpandoData(ownerDocument);
|
||||
var clone = data.frag.cloneNode(),
|
||||
i = 0,
|
||||
elems = getElements(),
|
||||
l = elems.length;
|
||||
for(;i<l;i++){
|
||||
clone.createElement(elems[i]);
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shivs the `createElement` and `createDocumentFragment` methods of the document.
|
||||
* @private
|
||||
* @param {Document|DocumentFragment} ownerDocument The document.
|
||||
* @param {Object} data of the document.
|
||||
*/
|
||||
function shivMethods(ownerDocument, data) {
|
||||
if (!data.cache) {
|
||||
data.cache = {};
|
||||
data.createElem = ownerDocument.createElement;
|
||||
data.createFrag = ownerDocument.createDocumentFragment;
|
||||
data.frag = data.createFrag();
|
||||
}
|
||||
|
||||
|
||||
ownerDocument.createElement = function(nodeName) {
|
||||
//abort shiv
|
||||
if (!html5.shivMethods) {
|
||||
return data.createElem(nodeName);
|
||||
}
|
||||
return createElement(nodeName, ownerDocument, data);
|
||||
};
|
||||
|
||||
ownerDocument.createDocumentFragment = Function('h,f', 'return function(){' +
|
||||
'var n=f.cloneNode(),c=n.createElement;' +
|
||||
'h.shivMethods&&(' +
|
||||
// unroll the `createElement` calls
|
||||
getElements().join().replace(/[\w\-:]+/g, function(nodeName) {
|
||||
data.createElem(nodeName);
|
||||
data.frag.createElement(nodeName);
|
||||
return 'c("' + nodeName + '")';
|
||||
}) +
|
||||
');return n}'
|
||||
)(html5, data.frag);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* Shivs the given document.
|
||||
* @memberOf html5
|
||||
* @param {Document} ownerDocument The document to shiv.
|
||||
* @returns {Document} The shived document.
|
||||
*/
|
||||
function shivDocument(ownerDocument) {
|
||||
if (!ownerDocument) {
|
||||
ownerDocument = document;
|
||||
}
|
||||
var data = getExpandoData(ownerDocument);
|
||||
|
||||
if (html5.shivCSS && !supportsHtml5Styles && !data.hasCSS) {
|
||||
data.hasCSS = !!addStyleSheet(ownerDocument,
|
||||
// corrects block display not defined in IE6/7/8/9
|
||||
'article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}' +
|
||||
// adds styling not present in IE6/7/8/9
|
||||
'mark{background:#FF0;color:#000}' +
|
||||
// hides non-rendered elements
|
||||
'template{display:none}'
|
||||
);
|
||||
}
|
||||
if (!supportsUnknownElements) {
|
||||
shivMethods(ownerDocument, data);
|
||||
}
|
||||
return ownerDocument;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* The `html5` object is exposed so that more elements can be shived and
|
||||
* existing shiving can be detected on iframes.
|
||||
* @type Object
|
||||
* @example
|
||||
*
|
||||
* // options can be changed before the script is included
|
||||
* html5 = { 'elements': 'mark section', 'shivCSS': false, 'shivMethods': false };
|
||||
*/
|
||||
var html5 = {
|
||||
|
||||
/**
|
||||
* An array or space separated string of node names of the elements to shiv.
|
||||
* @memberOf html5
|
||||
* @type Array|String
|
||||
*/
|
||||
'elements': options.elements || 'abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video',
|
||||
|
||||
/**
|
||||
* current version of html5shiv
|
||||
*/
|
||||
'version': version,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the HTML5 style sheet should be inserted.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivCSS': (options.shivCSS !== false),
|
||||
|
||||
/**
|
||||
* Is equal to true if a browser supports creating unknown/HTML5 elements
|
||||
* @memberOf html5
|
||||
* @type boolean
|
||||
*/
|
||||
'supportsUnknownElements': supportsUnknownElements,
|
||||
|
||||
/**
|
||||
* A flag to indicate that the document's `createElement` and `createDocumentFragment`
|
||||
* methods should be overwritten.
|
||||
* @memberOf html5
|
||||
* @type Boolean
|
||||
*/
|
||||
'shivMethods': (options.shivMethods !== false),
|
||||
|
||||
/**
|
||||
* A string to describe the type of `html5` object ("default" or "default print").
|
||||
* @memberOf html5
|
||||
* @type String
|
||||
*/
|
||||
'type': 'default',
|
||||
|
||||
// shivs the document according to the specified `html5` object options
|
||||
'shivDocument': shivDocument,
|
||||
|
||||
//creates a shived element
|
||||
createElement: createElement,
|
||||
|
||||
//creates a shived documentFragment
|
||||
createDocumentFragment: createDocumentFragment,
|
||||
|
||||
//extends list of elements
|
||||
addElements: addElements
|
||||
};
|
||||
|
||||
/*--------------------------------------------------------------------------*/
|
||||
|
||||
// expose html5
|
||||
window.html5 = html5;
|
||||
|
||||
// shiv the document
|
||||
shivDocument(document);
|
||||
|
||||
}(this, document));
|
||||
6
public/assets/js/jquery.drag.min.js
vendored
Normal file
6
public/assets/js/jquery.drag.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
public/assets/js/jquery.drop.min.js
vendored
Normal file
6
public/assets/js/jquery.drop.min.js
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
/*!
|
||||
* jquery.event.drop - v 2.2
|
||||
* Copyright (c) 2010 Three Dub Media - http://threedubmedia.com
|
||||
* Open Source MIT License - http://threedubmedia.com/code/license
|
||||
*/
|
||||
;(function(d){d.fn.drop=function(i,e,h){var g=typeof i=="string"?i:"",f=d.isFunction(i)?i:d.isFunction(e)?e:null;if(g.indexOf("drop")!==0){g="drop"+g}h=(i==f?e:h)||{};return f?this.bind(g,h,f):this.trigger(g)};d.drop=function(e){e=e||{};b.multi=e.multi===true?Infinity:e.multi===false?1:!isNaN(e.multi)?e.multi:b.multi;b.delay=e.delay||b.delay;b.tolerance=d.isFunction(e.tolerance)?e.tolerance:e.tolerance===null?null:b.tolerance;b.mode=e.mode||b.mode||"intersect"};var c=d.event,a=c.special,b=d.event.special.drop={multi:1,delay:20,mode:"overlap",targets:[],datakey:"dropdata",noBubble:true,add:function(f){var e=d.data(this,b.datakey);e.related+=1},remove:function(){d.data(this,b.datakey).related-=1},setup:function(){if(d.data(this,b.datakey)){return}var e={related:0,active:[],anyactive:0,winner:0,location:{}};d.data(this,b.datakey,e);b.targets.push(this);return false},teardown:function(){var f=d.data(this,b.datakey)||{};if(f.related){return}d.removeData(this,b.datakey);var e=this;b.targets=d.grep(b.targets,function(g){return(g!==e)})},handler:function(g,e){var f,h;if(!e){return}switch(g.type){case"mousedown":case"touchstart":h=d(b.targets);if(typeof e.drop=="string"){h=h.filter(e.drop)}h.each(function(){var i=d.data(this,b.datakey);i.active=[];i.anyactive=0;i.winner=0});e.droppable=h;a.drag.hijack(g,"dropinit",e);break;case"mousemove":case"touchmove":b.event=g;if(!b.timer){b.tolerate(e)}break;case"mouseup":case"touchend":b.timer=clearTimeout(b.timer);if(e.propagates){a.drag.hijack(g,"drop",e);a.drag.hijack(g,"dropend",e)}break}},locate:function(k,h){var l=d.data(k,b.datakey),g=d(k),i=g.offset()||{},e=g.outerHeight(),j=g.outerWidth(),f={elem:k,width:j,height:e,top:i.top,left:i.left,right:i.left+j,bottom:i.top+e};if(l){l.location=f;l.index=h;l.elem=k}return f},contains:function(e,f){return((f[0]||f.left)>=e.left&&(f[0]||f.right)<=e.right&&(f[1]||f.top)>=e.top&&(f[1]||f.bottom)<=e.bottom)},modes:{intersect:function(f,e,g){return this.contains(g,[f.pageX,f.pageY])?1000000000:this.modes.overlap.apply(this,arguments)},overlap:function(f,e,g){return Math.max(0,Math.min(g.bottom,e.bottom)-Math.max(g.top,e.top))*Math.max(0,Math.min(g.right,e.right)-Math.max(g.left,e.left))},fit:function(f,e,g){return this.contains(g,e)?1:0},middle:function(f,e,g){return this.contains(g,[e.left+e.width*0.5,e.top+e.height*0.5])?1:0}},sort:function(f,e){return(e.winner-f.winner)||(f.index-e.index)},tolerate:function(q){var k,e,n,j,l,m,g,p=0,f,h=q.interactions.length,r=[b.event.pageX,b.event.pageY],o=b.tolerance||b.modes[b.mode];do{if(f=q.interactions[p]){if(!f){return}f.drop=[];l=[];m=f.droppable.length;if(o){n=b.locate(f.proxy)}k=0;do{if(g=f.droppable[k]){j=d.data(g,b.datakey);e=j.location;if(!e){continue}j.winner=o?o.call(b,b.event,n,e):b.contains(e,r)?1:0;l.push(j)}}while(++k<m);l.sort(b.sort);k=0;do{if(j=l[k]){if(j.winner&&f.drop.length<b.multi){if(!j.active[p]&&!j.anyactive){if(a.drag.hijack(b.event,"dropstart",q,p,j.elem)[0]!==false){j.active[p]=1;j.anyactive+=1}else{j.winner=0}}if(j.winner){f.drop.push(j.elem)}}else{if(j.active[p]&&j.anyactive==1){a.drag.hijack(b.event,"dropend",q,p,j.elem);j.active[p]=0;j.anyactive-=1}}}}while(++k<m)}}while(++p<h);if(b.last&&r[0]==b.last.pageX&&r[1]==b.last.pageY){delete b.timer}else{b.timer=setTimeout(function(){b.tolerate(q)},b.delay)}b.last=b.event}};a.dropinit=a.dropstart=a.dropend=b})(jQuery);
|
||||
160
public/assets/js/require-backend.js
Normal file
160
public/assets/js/require-backend.js
Normal file
@@ -0,0 +1,160 @@
|
||||
require.config({
|
||||
urlArgs: "v=" + requirejs.s.contexts._.config.config.site.version,
|
||||
packages: [{
|
||||
name: 'moment',
|
||||
location: '../libs/moment',
|
||||
main: 'moment'
|
||||
}],
|
||||
//在打包压缩时将会把include中的模块合并到主文件中
|
||||
include: ['css', 'layer', 'toastr', 'fast', 'backend', 'backend-init', 'table', 'form', 'dragsort', 'addtabs', 'selectpage', 'bootstrap-daterangepicker'],
|
||||
paths: {
|
||||
'lang': "empty:",
|
||||
'form': 'require-form',
|
||||
'table': 'require-table',
|
||||
'upload': 'require-upload',
|
||||
'dropzone': 'dropzone.min',
|
||||
'echarts': 'echarts.min',
|
||||
'echarts-theme': 'echarts-theme',
|
||||
'adminlte': 'adminlte',
|
||||
'bootstrap-table-commonsearch': 'bootstrap-table-commonsearch',
|
||||
'bootstrap-table-template': 'bootstrap-table-template',
|
||||
//
|
||||
// 以下的包从bower的libs目录加载
|
||||
'jquery': '../libs/jquery/dist/jquery.min',
|
||||
'bootstrap': '../libs/bootstrap/dist/js/bootstrap.min',
|
||||
'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min',
|
||||
'bootstrap-daterangepicker': '../libs/bootstrap-daterangepicker/daterangepicker',
|
||||
'bootstrap-select': '../libs/bootstrap-select/dist/js/bootstrap-select.min',
|
||||
'bootstrap-select-lang': '../libs/bootstrap-select/dist/js/i18n/defaults-zh_CN',
|
||||
'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min',
|
||||
'bootstrap-table-export': '../libs/bootstrap-table/dist/extensions/export/bootstrap-table-export.min',
|
||||
'bootstrap-table-fixed-columns': '../libs/bootstrap-table/dist/extensions/fixed-columns/bootstrap-table-fixed-columns',
|
||||
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
|
||||
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
|
||||
'bootstrap-table-jumpto': '../libs/bootstrap-table/dist/extensions/page-jumpto/bootstrap-table-jumpto',
|
||||
'bootstrap-slider': '../libs/bootstrap-slider/bootstrap-slider',
|
||||
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
|
||||
'dragsort': '../libs/fastadmin-dragsort/jquery.dragsort',
|
||||
'sortable': '../libs/Sortable/Sortable.min',
|
||||
'addtabs': '../libs/fastadmin-addtabs/jquery.addtabs',
|
||||
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
||||
'validator': '../libs/nice-validator/dist/jquery.validator',
|
||||
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
||||
'toastr': '../libs/toastr/toastr',
|
||||
'jstree': '../libs/jstree/dist/jstree.min',
|
||||
'layer': '../libs/fastadmin-layer/dist/layer',
|
||||
'cookie': '../libs/jquery.cookie/jquery.cookie',
|
||||
'cxselect': '../libs/fastadmin-cxselect/js/jquery.cxselect',
|
||||
'template': '../libs/art-template/dist/template-native',
|
||||
'selectpage': '../libs/fastadmin-selectpage/selectpage',
|
||||
'citypicker': '../libs/fastadmin-citypicker/dist/js/city-picker.min',
|
||||
'citypicker-data': '../libs/fastadmin-citypicker/dist/js/city-picker.data',
|
||||
},
|
||||
// shim依赖配置
|
||||
shim: {
|
||||
'addons': ['backend'],
|
||||
'bootstrap': ['jquery'],
|
||||
'bootstrap-table': {
|
||||
deps: ['bootstrap'],
|
||||
exports: '$.fn.bootstrapTable'
|
||||
},
|
||||
'bootstrap-table-lang': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-export': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-fixed-columns': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-mobile': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-advancedsearch': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-commonsearch': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-template': {
|
||||
deps: ['bootstrap-table', 'template'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-jumpto': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'tableexport': {
|
||||
deps: ['jquery'],
|
||||
exports: '$.fn.extend'
|
||||
},
|
||||
'slimscroll': {
|
||||
deps: ['jquery'],
|
||||
exports: '$.fn.extend'
|
||||
},
|
||||
'adminlte': {
|
||||
deps: ['bootstrap', 'slimscroll'],
|
||||
exports: '$.AdminLTE'
|
||||
},
|
||||
'bootstrap-daterangepicker': [
|
||||
'moment/locale/zh-cn'
|
||||
],
|
||||
'bootstrap-datetimepicker': [
|
||||
'moment/locale/zh-cn',
|
||||
],
|
||||
'bootstrap-select-lang': ['bootstrap-select'],
|
||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css'],
|
||||
'validator-lang': ['validator'],
|
||||
'citypicker': ['citypicker-data', 'css!../libs/fastadmin-citypicker/dist/css/city-picker.css']
|
||||
},
|
||||
baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径
|
||||
map: {
|
||||
'*': {
|
||||
'css': '../libs/require-css/css.min'
|
||||
}
|
||||
},
|
||||
waitSeconds: 60,
|
||||
charset: 'utf-8' // 文件编码
|
||||
});
|
||||
|
||||
require(['jquery', 'bootstrap'], function ($, undefined) {
|
||||
//初始配置
|
||||
var Config = requirejs.s.contexts._.config.config;
|
||||
//将Config渲染到全局
|
||||
window.Config = Config;
|
||||
// 配置语言包的路径
|
||||
var paths = {};
|
||||
paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername + '&lang=' + Config.language;
|
||||
// 避免目录冲突
|
||||
paths['backend/'] = 'backend/';
|
||||
require.config({paths: paths});
|
||||
|
||||
// 初始化
|
||||
$(function () {
|
||||
require(['fast'], function (Fast) {
|
||||
require(['backend', 'backend-init', 'addons'], function (Backend, undefined, Addons) {
|
||||
//加载相应模块
|
||||
if (Config.jsname) {
|
||||
require([Config.jsname], function (Controller) {
|
||||
if (Controller.hasOwnProperty(Config.actionname)) {
|
||||
Controller[Config.actionname]();
|
||||
} else {
|
||||
if (Controller.hasOwnProperty("_empty")) {
|
||||
Controller._empty();
|
||||
}
|
||||
}
|
||||
}, function (e) {
|
||||
console.error(e);
|
||||
// 这里可捕获模块加载的错误
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
77
public/assets/js/require-backend.min.js
vendored
Normal file
77
public/assets/js/require-backend.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/assets/js/require-css.min.js
vendored
Normal file
1
public/assets/js/require-css.min.js
vendored
Normal file
@@ -0,0 +1 @@
|
||||
define(function(){if("undefined"==typeof window)return{load:function(e,t,n){n()}};var e=document.getElementsByTagName("head")[0],t=window.navigator.userAgent.match(/Trident\/([^ ;]*)|AppleWebKit\/([^ ;]*)|Opera\/([^ ;]*)|rv\:([^ ;]*)(.*?)Gecko\/([^ ;]*)|MSIE\s([^ ;]*)|AndroidWebKit\/([^ ;]*)/)||0,n=!1,r=!0;t[1]||t[7]?n=parseInt(t[1])<6||parseInt(t[7])<=9:t[2]||t[8]?r=!1:t[4]&&(n=parseInt(t[4])<18);var o={};o.pluginBuilder="./css-builder";var a,i,s,l=function(){a=document.createElement("style"),e.appendChild(a),i=a.styleSheet||a.sheet},u=0,d=[],c=function(e){u++,32==u&&(l(),u=0),i.addImport(e),a.onload=function(){f()}},f=function(){s();var e=d.shift();return e?(s=e[1],void c(e[0])):void(s=null)},h=function(e,t){if(i&&i.addImport||l(),i&&i.addImport)s?d.push([e,t]):(c(e),s=t);else{a.textContent='@import "'+e+'";';var n=setInterval(function(){try{a.sheet.cssRules,clearInterval(n),t()}catch(e){}},10)}},p=function(t,n){var o=document.createElement("link");if(o.type="text/css",o.rel="stylesheet",r)o.onload=function(){o.onload=function(){},setTimeout(n,7)};else var a=setInterval(function(){for(var e=0;e<document.styleSheets.length;e++){var t=document.styleSheets[e];if(t.href==o.href)return clearInterval(a),n()}},10);o.href=t,e.appendChild(o)};return o.normalize=function(e,t){return".css"==e.substr(e.length-4,4)&&(e=e.substr(0,e.length-4)),t(e)},o.load=function(e,t,r){(n?h:p)(t.toUrl(e+".css"),r)},o});
|
||||
756
public/assets/js/require-form.js
Normal file
756
public/assets/js/require-form.js
Normal file
@@ -0,0 +1,756 @@
|
||||
define(['jquery', 'bootstrap', 'upload', 'validator', 'validator-lang'], function ($, undefined, Upload, Validator, undefined) {
|
||||
var Form = {
|
||||
config: {
|
||||
fieldlisttpl: '<dd class="form-inline"><input type="text" name="<%=name%>[<%=index%>][key]" class="form-control" value="<%=key%>" placeholder="<%=options.keyPlaceholder||\'\'%>" size="10" /> <input type="text" name="<%=name%>[<%=index%>][value]" class="form-control" value="<%=value%>" placeholder="<%=options.valuePlaceholder||\'\'%>" /> <span class="btn btn-sm btn-danger btn-remove"><i class="fa fa-times"></i></span> <span class="btn btn-sm btn-primary btn-dragsort"><i class="fa fa-arrows"></i></span></dd>'
|
||||
},
|
||||
events: {
|
||||
validator: function (form, success, error, submit) {
|
||||
if (!form.is("form"))
|
||||
return;
|
||||
//绑定表单事件
|
||||
form.validator($.extend({
|
||||
rules: {
|
||||
username: [/^\w{3,30}$/, __('Username must be 3 to 30 characters')],
|
||||
password: [/^[\S]{6,30}$/, __('Password must be 6 to 30 characters')]
|
||||
},
|
||||
validClass: 'has-success',
|
||||
invalidClass: 'has-error',
|
||||
bindClassTo: '.form-group',
|
||||
formClass: 'n-default n-bootstrap',
|
||||
msgClass: 'n-right',
|
||||
stopOnError: true,
|
||||
display: function (elem) {
|
||||
return $(elem).closest('.form-group').find(".control-label").text().replace(/\:/, '');
|
||||
},
|
||||
dataFilter: function (data) {
|
||||
if (data.code === 1) {
|
||||
return data.msg ? {"ok": data.msg} : '';
|
||||
} else {
|
||||
return data.msg;
|
||||
}
|
||||
},
|
||||
target: function (input) {
|
||||
var target = $(input).data("target");
|
||||
if (target && $(target).length > 0) {
|
||||
return $(target);
|
||||
}
|
||||
var $formitem = $(input).closest('.form-group'),
|
||||
$msgbox = $formitem.find('span.msg-box');
|
||||
if (!$msgbox.length) {
|
||||
return [];
|
||||
}
|
||||
return $msgbox;
|
||||
},
|
||||
valid: function (ret) {
|
||||
var that = this, submitBtn = $(".layer-footer [type=submit]", form);
|
||||
that.holdSubmit(true);
|
||||
submitBtn.addClass("disabled");
|
||||
//验证通过提交表单
|
||||
var submitResult = Form.api.submit($(ret), function (data, ret) {
|
||||
that.holdSubmit(false);
|
||||
submitBtn.removeClass("disabled");
|
||||
if (false === $(this).triggerHandler("success.form", [data, ret])) {
|
||||
return false;
|
||||
}
|
||||
if (typeof success === 'function') {
|
||||
if (false === success.call($(this), data, ret)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
//提示及关闭当前窗口
|
||||
var msg = ret.hasOwnProperty("msg") && ret.msg !== "" ? ret.msg : __('Operation completed');
|
||||
parent.Toastr.success(msg);
|
||||
parent.$(".btn-refresh").trigger("click");
|
||||
if (window.name) {
|
||||
var index = parent.Layer.getFrameIndex(window.name);
|
||||
parent.Layer.close(index);
|
||||
}
|
||||
return false;
|
||||
}, function (data, ret) {
|
||||
that.holdSubmit(false);
|
||||
if (false === $(this).triggerHandler("error.form", [data, ret])) {
|
||||
return false;
|
||||
}
|
||||
submitBtn.removeClass("disabled");
|
||||
if (typeof error === 'function') {
|
||||
if (false === error.call($(this), data, ret)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}, submit);
|
||||
//如果提交失败则释放锁定
|
||||
if (!submitResult) {
|
||||
that.holdSubmit(false);
|
||||
submitBtn.removeClass("disabled");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}, form.data("validator-options") || {}));
|
||||
|
||||
//移除提交按钮的disabled类
|
||||
$(".layer-footer [type=submit],.fixed-footer [type=submit],.normal-footer [type=submit]", form).removeClass("disabled");
|
||||
//自定义关闭按钮事件
|
||||
form.on("click", ".layer-close", function () {
|
||||
if (window.name) {
|
||||
var index = parent.Layer.getFrameIndex(window.name);
|
||||
parent.Layer.close(index);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
},
|
||||
selectpicker: function (form) {
|
||||
//绑定select元素事件
|
||||
if ($(".selectpicker", form).length > 0) {
|
||||
require(['bootstrap-select', 'bootstrap-select-lang'], function () {
|
||||
$.fn.selectpicker.Constructor.BootstrapVersion = '3';
|
||||
$('.selectpicker', form).selectpicker();
|
||||
$(form).on("reset", function () {
|
||||
setTimeout(function () {
|
||||
$('.selectpicker').selectpicker('refresh').trigger("change");
|
||||
}, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
selectpage: function (form) {
|
||||
//绑定selectpage元素事件
|
||||
if ($(".selectpage", form).length > 0) {
|
||||
require(['selectpage'], function () {
|
||||
$('.selectpage', form).selectPage({
|
||||
eAjaxSuccess: function (data) {
|
||||
data.list = typeof data.rows !== 'undefined' ? data.rows : (typeof data.list !== 'undefined' ? data.list : []);
|
||||
data.totalRow = typeof data.total !== 'undefined' ? data.total : (typeof data.totalRow !== 'undefined' ? data.totalRow : data.list.length);
|
||||
return data;
|
||||
}
|
||||
});
|
||||
});
|
||||
//给隐藏的元素添加上validate验证触发事件
|
||||
$(document).on("change", ".sp_hidden", function () {
|
||||
$(this).trigger("validate");
|
||||
});
|
||||
$(document).on("change", ".sp_input", function () {
|
||||
$(this).closest(".sp_container").find(".sp_hidden").trigger("change");
|
||||
});
|
||||
$(form).on("reset", function () {
|
||||
setTimeout(function () {
|
||||
$(".selectpage", form).each(function () {
|
||||
var selectpage = $(this).data("selectPageObject");
|
||||
selectpage.elem.hidden.val($(this).val());
|
||||
$(this).selectPageRefresh();
|
||||
});
|
||||
}, 1);
|
||||
});
|
||||
}
|
||||
},
|
||||
cxselect: function (form) {
|
||||
//绑定cxselect元素事件
|
||||
if ($("[data-toggle='cxselect']", form).length > 0) {
|
||||
require(['cxselect'], function () {
|
||||
$.cxSelect.defaults.jsonName = 'name';
|
||||
$.cxSelect.defaults.jsonValue = 'value';
|
||||
$.cxSelect.defaults.jsonSpace = 'data';
|
||||
$("[data-toggle='cxselect']", form).cxSelect();
|
||||
});
|
||||
}
|
||||
},
|
||||
citypicker: function (form) {
|
||||
//绑定城市远程插件
|
||||
if ($("[data-toggle='city-picker']", form).length > 0) {
|
||||
require(['citypicker'], function () {
|
||||
$(form).on("reset", function () {
|
||||
setTimeout(function () {
|
||||
$("[data-toggle='city-picker']").citypicker('refresh');
|
||||
}, 1);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
datetimepicker: function (form) {
|
||||
//绑定日期时间元素事件
|
||||
if ($(".datetimepicker", form).length > 0) {
|
||||
require(['bootstrap-datetimepicker'], function () {
|
||||
var options = {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
icons: {
|
||||
time: 'fa fa-clock-o',
|
||||
date: 'fa fa-calendar',
|
||||
up: 'fa fa-chevron-up',
|
||||
down: 'fa fa-chevron-down',
|
||||
previous: 'fa fa-chevron-left',
|
||||
next: 'fa fa-chevron-right',
|
||||
today: 'fa fa-history',
|
||||
clear: 'fa fa-trash',
|
||||
close: 'fa fa-remove'
|
||||
},
|
||||
showTodayButton: true,
|
||||
showClose: true
|
||||
};
|
||||
$('.datetimepicker', form).parent().css('position', 'relative');
|
||||
$('.datetimepicker', form).datetimepicker(options).on('dp.change', function (e) {
|
||||
$(this, document).trigger("changed");
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
daterangepicker: function (form) {
|
||||
//绑定日期时间元素事件
|
||||
if ($(".datetimerange", form).length > 0) {
|
||||
require(['bootstrap-daterangepicker'], function () {
|
||||
var ranges = {};
|
||||
ranges[__('Today')] = [Moment().startOf('day'), Moment().endOf('day')];
|
||||
ranges[__('Yesterday')] = [Moment().subtract(1, 'days').startOf('day'), Moment().subtract(1, 'days').endOf('day')];
|
||||
ranges[__('Last 7 Days')] = [Moment().subtract(6, 'days').startOf('day'), Moment().endOf('day')];
|
||||
ranges[__('Last 30 Days')] = [Moment().subtract(29, 'days').startOf('day'), Moment().endOf('day')];
|
||||
ranges[__('This Month')] = [Moment().startOf('month'), Moment().endOf('month')];
|
||||
ranges[__('Last Month')] = [Moment().subtract(1, 'month').startOf('month'), Moment().subtract(1, 'month').endOf('month')];
|
||||
var options = {
|
||||
timePicker: false,
|
||||
autoUpdateInput: false,
|
||||
timePickerSeconds: true,
|
||||
timePicker24Hour: true,
|
||||
autoApply: true,
|
||||
locale: {
|
||||
format: 'YYYY-MM-DD HH:mm:ss',
|
||||
customRangeLabel: __("Custom Range"),
|
||||
applyLabel: __("Apply"),
|
||||
cancelLabel: __("Clear"),
|
||||
},
|
||||
ranges: ranges,
|
||||
};
|
||||
var origincallback = function (start, end) {
|
||||
$(this.element).val(start.format(this.locale.format) + " - " + end.format(this.locale.format));
|
||||
$(this.element).trigger('change').trigger('validate');
|
||||
};
|
||||
$(".datetimerange", form).each(function () {
|
||||
var callback = typeof $(this).data('callback') == 'function' ? $(this).data('callback') : origincallback;
|
||||
$(this).on('apply.daterangepicker', function (ev, picker) {
|
||||
callback.call(picker, picker.startDate, picker.endDate);
|
||||
});
|
||||
$(this).on('cancel.daterangepicker', function (ev, picker) {
|
||||
$(this).val('').trigger('change').trigger('validate');
|
||||
});
|
||||
$(this).daterangepicker($.extend(true, {}, options, $(this).data() || {}, $(this).data("daterangepicker-options") || {}));
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
/**
|
||||
* 绑定上传事件
|
||||
* @param form
|
||||
* @deprecated Use faupload instead.
|
||||
*/
|
||||
plupload: function (form) {
|
||||
Form.events.faupload(form);
|
||||
},
|
||||
/**
|
||||
* 绑定上传事件
|
||||
* @param form
|
||||
*/
|
||||
faupload: function (form) {
|
||||
//绑定上传元素事件
|
||||
if ($(".plupload,.faupload", form).length > 0) {
|
||||
Upload.api.upload($(".plupload,.faupload", form));
|
||||
}
|
||||
},
|
||||
faselect: function (form) {
|
||||
//绑定fachoose选择附件事件
|
||||
if ($(".faselect,.fachoose", form).length > 0) {
|
||||
$(".faselect,.fachoose", form).off('click').on('click', function () {
|
||||
var that = this;
|
||||
var multiple = $(this).data("multiple") ? $(this).data("multiple") : false;
|
||||
var mimetype = $(this).data("mimetype") ? $(this).data("mimetype") : '';
|
||||
var admin_id = $(this).data("admin-id") ? $(this).data("admin-id") : '';
|
||||
var user_id = $(this).data("user-id") ? $(this).data("user-id") : '';
|
||||
mimetype = mimetype.replace(/\/\*/ig, '/');
|
||||
var url = $(this).data("url") ? $(this).data("url") : (typeof Backend !== 'undefined' ? "general/attachment/select" : "user/attachment");
|
||||
parent.Fast.api.open(url + "?element_id=" + $(this).attr("id") + "&multiple=" + multiple + "&mimetype=" + mimetype + "&admin_id=" + admin_id + "&user_id=" + user_id, __('Choose'), {
|
||||
callback: function (data) {
|
||||
var button = $(that);
|
||||
var maxcount = $(button).data("maxcount");
|
||||
var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
|
||||
maxcount = typeof maxcount !== "undefined" ? maxcount : 0;
|
||||
if (input_id && data.multiple) {
|
||||
var urlArr = [];
|
||||
var inputObj = $("#" + input_id);
|
||||
var value = $.trim(inputObj.val());
|
||||
if (value !== "") {
|
||||
urlArr.push(inputObj.val());
|
||||
}
|
||||
var nums = value === '' ? 0 : value.split(/\,/).length;
|
||||
var files = data.url !== "" ? data.url.split(/\,/) : [];
|
||||
$.each(files, function (i, j) {
|
||||
var url = Config.upload.fullmode ? Fast.api.cdnurl(j) : j;
|
||||
urlArr.push(url);
|
||||
});
|
||||
if (maxcount > 0) {
|
||||
var remains = maxcount - nums;
|
||||
if (files.length > remains) {
|
||||
Toastr.error(__('You can choose up to %d file%s', remains));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var result = urlArr.join(",");
|
||||
inputObj.val(result).trigger("change").trigger("validate");
|
||||
} else if (input_id) {
|
||||
var url = Config.upload.fullmode ? Fast.api.cdnurl(data.url) : data.url;
|
||||
$("#" + input_id).val(url).trigger("change").trigger("validate");
|
||||
}
|
||||
|
||||
// 触发选择文件自定义事件
|
||||
button.trigger("fa.event.selectedfile", data);
|
||||
}
|
||||
});
|
||||
return false;
|
||||
});
|
||||
}
|
||||
},
|
||||
fieldlist: function (form) {
|
||||
//绑定fieldlist
|
||||
if ($(".fieldlist", form).length > 0) {
|
||||
require(['dragsort', 'template'], function (undefined, Template) {
|
||||
//刷新隐藏textarea的值
|
||||
var refresh = function (container) {
|
||||
var data = {};
|
||||
var name = container.data("name");
|
||||
var textarea = $("textarea[name='" + name + "']", form);
|
||||
var template = container.data("template");
|
||||
$.each($("input,select,textarea", container).serializeArray(), function (i, j) {
|
||||
var reg = /\[(\w+)\]\[(\w+)\]$/g;
|
||||
var match = reg.exec(j.name);
|
||||
if (!match)
|
||||
return true;
|
||||
match[1] = "x" + parseInt(match[1]);
|
||||
if (typeof data[match[1]] == 'undefined') {
|
||||
data[match[1]] = {};
|
||||
}
|
||||
data[match[1]][match[2]] = j.value;
|
||||
});
|
||||
//使用数组保存
|
||||
var usearray = container.data("usearray") || false;
|
||||
//保留空数据
|
||||
var keepempty = container.data("keepempty") || false;
|
||||
|
||||
var result = template || usearray ? [] : {};
|
||||
var keys = Object.keys(Object.values(data)[0] || {});
|
||||
|
||||
var isassociative = !usearray && keys.indexOf("value") > -1 && (keys.length === 1 || (keys.length === 2 && keys.indexOf("key") > -1));
|
||||
if(isassociative && keys.length ===2){
|
||||
result = {};
|
||||
}
|
||||
|
||||
$.each(data, function (i, j) {
|
||||
if (j) {
|
||||
if (isassociative) {
|
||||
if (keys.length === 2) {
|
||||
if (j.key != '' || keepempty) {
|
||||
result['__PLACEHOLDKEY__' + j.key] = j.value;
|
||||
}
|
||||
} else {
|
||||
//一维数组
|
||||
result.push(j.value);
|
||||
}
|
||||
} else {
|
||||
result.push(j);
|
||||
}
|
||||
}
|
||||
});
|
||||
textarea.val(JSON.stringify(result).replace(/__PLACEHOLDKEY__/g, ''));
|
||||
};
|
||||
//追加一行数据
|
||||
var append = function (container, row, initial) {
|
||||
var tagName = container.data("tag") || (container.is("table") ? "tr" : "dd");
|
||||
var index = container.data("index");
|
||||
var name = container.data("name");
|
||||
var template = container.data("template");
|
||||
var data = container.data();
|
||||
index = index ? parseInt(index) : 0;
|
||||
container.data("index", index + 1);
|
||||
row = row ? row : {};
|
||||
row = typeof row.key === 'undefined' || typeof row.value === 'undefined' ? {key: '', value: row} : row;
|
||||
var options = container.data("fieldlist-options") || {};
|
||||
var vars = {index: index, name: name, data: data, options: options, key: row.key, value: row.value, row: row.value};
|
||||
var html = template ? Template(template, vars) : Template.render(Form.config.fieldlisttpl, vars);
|
||||
var obj = $(html);
|
||||
if ((options.deleteBtn === false || options.removeBtn === false) && initial)
|
||||
obj.find(".btn-remove").remove();
|
||||
if (options.dragsortBtn === false && initial)
|
||||
obj.find(".btn-dragsort").remove();
|
||||
if ((options.readonlyKey === true || options.disableKey === true) && initial) {
|
||||
obj.find("input[name$='[key]']").prop("readonly", true);
|
||||
}
|
||||
obj.attr("fieldlist-item", true);
|
||||
obj.insertAfter($(tagName + "[fieldlist-item]", container).length > 0 ? $(tagName + "[fieldlist-item]:last", container) : $(tagName + ":first", container));
|
||||
if ($(".btn-append,.append", container).length > 0) {
|
||||
//兼容旧版本事件
|
||||
$(".btn-append,.append", container).trigger("fa.event.appendfieldlist", obj);
|
||||
} else {
|
||||
//新版本事件
|
||||
container.trigger("fa.event.appendfieldlist", obj);
|
||||
}
|
||||
return obj;
|
||||
};
|
||||
var fieldlist = $(".fieldlist", form);
|
||||
//表单重置
|
||||
form.on("reset", function () {
|
||||
setTimeout(function () {
|
||||
fieldlist.trigger("fa.event.refreshfieldlist");
|
||||
});
|
||||
});
|
||||
//监听文本框改变事件
|
||||
$(document).on('change keyup changed', ".fieldlist input,.fieldlist textarea,.fieldlist select", function () {
|
||||
var container = $(this).closest(".fieldlist");
|
||||
refresh(container);
|
||||
});
|
||||
//追加控制(点击按钮)
|
||||
fieldlist.on("click", ".btn-append,.append", function (e, row) {
|
||||
var container = $(this).closest(".fieldlist");
|
||||
append(container, row);
|
||||
refresh(container);
|
||||
});
|
||||
//移除控制(点击按钮)
|
||||
fieldlist.on("click", ".btn-remove", function () {
|
||||
var container = $(this).closest(".fieldlist");
|
||||
var tagName = container.data("tag") || (container.is("table") ? "tr" : "dd");
|
||||
$(this).closest(tagName).remove();
|
||||
refresh(container);
|
||||
});
|
||||
//追加控制(通过事件)
|
||||
fieldlist.on("fa.event.appendtofieldlist", function (e, row) {
|
||||
var container = $(this);
|
||||
append(container, row);
|
||||
refresh(container);
|
||||
});
|
||||
//根据textarea内容重新渲染
|
||||
fieldlist.on("fa.event.refreshfieldlist", function () {
|
||||
var container = $(this);
|
||||
var textarea = $("textarea[name='" + container.data("name") + "']", form);
|
||||
//先清空已有的数据
|
||||
$("[fieldlist-item]", container).remove();
|
||||
var json = {};
|
||||
try {
|
||||
var val = textarea.val().replace(/"(\d+)"\:/g, "\"__PLACEHOLDERKEY__$1\":");
|
||||
json = JSON.parse(val);
|
||||
} catch (e) {
|
||||
}
|
||||
$.each(json, function (i, j) {
|
||||
append(container, {key: i.toString().replace("__PLACEHOLDERKEY__", ""), value: j}, true);
|
||||
});
|
||||
});
|
||||
//拖拽排序
|
||||
fieldlist.each(function () {
|
||||
var container = $(this);
|
||||
var tagName = container.data("tag") || (container.is("table") ? "tr" : "dd");
|
||||
container.dragsort({
|
||||
itemSelector: tagName,
|
||||
dragSelector: ".btn-dragsort",
|
||||
dragEnd: function () {
|
||||
refresh(container);
|
||||
},
|
||||
placeHolderTemplate: $("<" + tagName + "/>")
|
||||
});
|
||||
if (typeof container.data("options") === 'object' && container.data("options").appendBtn === false) {
|
||||
$(".btn-append,.append", container).hide();
|
||||
}
|
||||
$("textarea[name='" + container.data("name") + "']", form).on("fa.event.refreshfieldlist", function () {
|
||||
//兼容旧版本事件
|
||||
$(this).closest(".fieldlist").trigger("fa.event.refreshfieldlist");
|
||||
});
|
||||
});
|
||||
fieldlist.trigger("fa.event.refreshfieldlist");
|
||||
});
|
||||
}
|
||||
},
|
||||
switcher: function (form) {
|
||||
form.on("click", "[data-toggle='switcher']", function () {
|
||||
if ($(this).hasClass("disabled")) {
|
||||
return false;
|
||||
}
|
||||
var switcher = $.proxy(function () {
|
||||
var input = $(this).prev("input");
|
||||
input = $(this).data("input-id") ? $("#" + $(this).data("input-id")) : input;
|
||||
if (input.length > 0) {
|
||||
var yes = $(this).data("yes");
|
||||
var no = $(this).data("no");
|
||||
if (input.val() == yes) {
|
||||
input.val(no);
|
||||
$("i", this).addClass("fa-flip-horizontal text-gray");
|
||||
} else {
|
||||
input.val(yes);
|
||||
$("i", this).removeClass("fa-flip-horizontal text-gray");
|
||||
}
|
||||
input.trigger('change');
|
||||
}
|
||||
}, this);
|
||||
if (typeof $(this).data("confirm") !== 'undefined') {
|
||||
Layer.confirm($(this).data("confirm"), function (index) {
|
||||
switcher();
|
||||
Layer.close(index);
|
||||
});
|
||||
} else {
|
||||
switcher();
|
||||
}
|
||||
|
||||
return false;
|
||||
});
|
||||
},
|
||||
bindevent: function (form) {
|
||||
|
||||
},
|
||||
slider: function (form) {
|
||||
if ($("[data-role='slider'],input.slider", form).length > 0) {
|
||||
require(['bootstrap-slider'], function () {
|
||||
$("[data-role='slider'],input.slider").removeClass('hidden').css('width', function (index, value) {
|
||||
return $(this).parents('.form-control').width();
|
||||
}).slider().on('slide', function (ev) {
|
||||
var data = $(this).data();
|
||||
if (typeof data.unit !== 'undefined') {
|
||||
$(this).parents('.form-control').siblings('.value').text(ev.value + data.unit);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
tagsinput: function (form) {
|
||||
if ($("[data-role='tagsinput']", form).length > 0) {
|
||||
require(['tagsinput', 'autocomplete'], function () {
|
||||
$("[data-role='tagsinput']").tagsinput();
|
||||
form.on("reset", function () {
|
||||
setTimeout(function () {
|
||||
$("[data-role='tagsinput']").tagsinput('reset');
|
||||
}, 0);
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
autocomplete: function (form) {
|
||||
if ($("[data-role='autocomplete']", form).length > 0) {
|
||||
require(['autocomplete'], function () {
|
||||
$("[data-role='autocomplete']").autocomplete({
|
||||
onSelect: function () {
|
||||
$(this).trigger('change').trigger('validate');
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
},
|
||||
favisible: function (form) {
|
||||
if ($("[data-favisible]", form).length == 0) {
|
||||
return;
|
||||
}
|
||||
var checkCondition = function (condition) {
|
||||
var conditionArr = condition.split(/&&/);
|
||||
var success = 0;
|
||||
var baseregex = /^([a-z0-9\_]+)([>|<|=|\!]=?)(.*)$/i, strregex = /^('|")(.*)('|")$/, regregex = /^regex:(.*)$/;
|
||||
// @formatter:off
|
||||
var operator_result = {
|
||||
'>': function (a, b) {
|
||||
return a > b;
|
||||
},
|
||||
'>=': function (a, b) {
|
||||
return a >= b;
|
||||
},
|
||||
'<': function (a, b) {
|
||||
return a < b;
|
||||
},
|
||||
'<=': function (a, b) {
|
||||
return a <= b;
|
||||
},
|
||||
'==': function (a, b) {
|
||||
return a == b;
|
||||
},
|
||||
'!=': function (a, b) {
|
||||
return a != b;
|
||||
},
|
||||
'in': function (a, b) {
|
||||
return b.split(/\,/).indexOf(a) > -1;
|
||||
},
|
||||
'regex': function (a, b) {
|
||||
var regParts = b.match(/^\/(.*?)\/([gim]*)$/);
|
||||
var regexp = regParts ? new RegExp(regParts[1], regParts[2]) : new RegExp(b);
|
||||
return regexp.test(a);
|
||||
}
|
||||
};
|
||||
// @formatter:on
|
||||
var $disabledElements = form.find(':disabled').removeAttr('disabled');
|
||||
var dataArr = form.serializeArray(), dataObj = {}, fieldName, fieldValue;
|
||||
$disabledElements.attr('disabled', 'disabled');
|
||||
$(dataArr).each(function (i, field) {
|
||||
fieldName = field.name;
|
||||
fieldValue = field.value;
|
||||
fieldName = fieldName.substr(-2) === '[]' ? fieldName.substr(0, fieldName.length - 2) : fieldName;
|
||||
dataObj[fieldName] = typeof dataObj[fieldName] !== 'undefined' ? [dataObj[fieldName], fieldValue].join(',') : fieldValue;
|
||||
});
|
||||
|
||||
$.each(conditionArr, function (i, item) {
|
||||
var basematches = baseregex.exec(item);
|
||||
if (basematches) {
|
||||
var name = basematches[1], operator = basematches[2], value = basematches[3].toString();
|
||||
if (operator === '=') {
|
||||
var strmatches = strregex.exec(value);
|
||||
operator = strmatches ? '==' : 'in';
|
||||
value = strmatches ? strmatches[2] : value;
|
||||
}
|
||||
var regmatches = regregex.exec(value);
|
||||
if (regmatches) {
|
||||
operator = 'regex';
|
||||
value = regmatches[1];
|
||||
}
|
||||
var chkname = "row[" + name + "]";
|
||||
if (typeof dataObj[chkname] === 'undefined') {
|
||||
return false;
|
||||
}
|
||||
var objvalue = dataObj[chkname];
|
||||
if ($.isArray(objvalue)) {
|
||||
objvalue = dataObj[chkname].join(",");
|
||||
}
|
||||
if (['>', '>=', '<', '<='].indexOf(operator) > -1) {
|
||||
objvalue = parseFloat(objvalue);
|
||||
value = parseFloat(value);
|
||||
}
|
||||
var result = operator_result[operator](objvalue, value);
|
||||
success += (result ? 1 : 0);
|
||||
}
|
||||
});
|
||||
return success === conditionArr.length;
|
||||
};
|
||||
form.on("keyup change click configchange", "input,textarea,select", function () {
|
||||
$("[data-favisible][data-favisible!='']", form).each(function () {
|
||||
var visible = $(this).data("favisible");
|
||||
var groupArr = visible ? visible.toString().split(/\|\|/) : [];
|
||||
var success = 0;
|
||||
$.each(groupArr, function (i, j) {
|
||||
if (checkCondition(j)) {
|
||||
success++;
|
||||
}
|
||||
});
|
||||
if (success > 0) {
|
||||
$(this).removeClass("hidden");
|
||||
} else {
|
||||
$(this).addClass("hidden");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//追加上忽略元素
|
||||
setTimeout(function () {
|
||||
var validator = form.data('validator');
|
||||
if (validator) {
|
||||
validator.options.ignore += ((validator.options.ignore ? ',' : '') + '.hidden[data-favisible] :hidden,.hidden[data-favisible]:hidden');
|
||||
}
|
||||
}, 0);
|
||||
|
||||
$("input,textarea,select", form).trigger("configchange");
|
||||
}
|
||||
},
|
||||
api: {
|
||||
submit: function (form, success, error, submit) {
|
||||
if (form.length === 0) {
|
||||
Toastr.error("表单未初始化完成,无法提交");
|
||||
return false;
|
||||
}
|
||||
if (typeof submit === 'function') {
|
||||
if (false === submit.call(form, success, error)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var type = form.attr("method") ? form.attr("method").toUpperCase() : 'GET';
|
||||
type = type && (type === 'GET' || type === 'POST') ? type : 'GET';
|
||||
url = form.attr("action");
|
||||
url = url ? url : location.href;
|
||||
//修复当存在多选项元素时提交的BUG
|
||||
var params = {};
|
||||
var multipleList = $("[name$='[]']", form);
|
||||
if (multipleList.length > 0) {
|
||||
var postFields = form.serializeArray().map(function (obj) {
|
||||
return $(obj).prop("name");
|
||||
});
|
||||
$.each(multipleList, function (i, j) {
|
||||
if (postFields.indexOf($(this).prop("name")) < 0) {
|
||||
params[$(this).prop("name")] = '';
|
||||
}
|
||||
});
|
||||
}
|
||||
//调用Ajax请求方法
|
||||
Fast.api.ajax({
|
||||
type: type,
|
||||
url: url,
|
||||
data: form.serialize() + (Object.keys(params).length > 0 ? '&' + $.param(params) : ''),
|
||||
dataType: 'json',
|
||||
complete: function (xhr) {
|
||||
var token = xhr.getResponseHeader('__token__');
|
||||
if (token) {
|
||||
$("input[name='__token__']").val(token);
|
||||
}
|
||||
}
|
||||
}, function (data, ret) {
|
||||
$('.form-group', form).removeClass('has-feedback has-success has-error');
|
||||
if (data && typeof data === 'object') {
|
||||
//刷新客户端token
|
||||
if (typeof data.token !== 'undefined') {
|
||||
$("input[name='__token__']").val(data.token);
|
||||
}
|
||||
//调用客户端事件
|
||||
if (typeof data.callback !== 'undefined' && typeof data.callback === 'function') {
|
||||
data.callback.call(form, data);
|
||||
}
|
||||
}
|
||||
if (typeof success === 'function') {
|
||||
if (false === success.call(form, data, ret)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}, function (data, ret) {
|
||||
if (data && typeof data === 'object' && typeof data.token !== 'undefined') {
|
||||
$("input[name='__token__']").val(data.token);
|
||||
}
|
||||
if (typeof error === 'function') {
|
||||
if (false === error.call(form, data, ret)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
return true;
|
||||
},
|
||||
bindevent: function (form, success, error, submit) {
|
||||
|
||||
form = typeof form === 'object' ? form : $(form);
|
||||
|
||||
var events = Form.events;
|
||||
|
||||
events.bindevent(form);
|
||||
|
||||
events.validator(form, success, error, submit);
|
||||
|
||||
events.selectpicker(form);
|
||||
|
||||
events.daterangepicker(form);
|
||||
|
||||
events.selectpage(form);
|
||||
|
||||
events.cxselect(form);
|
||||
|
||||
events.citypicker(form);
|
||||
|
||||
events.datetimepicker(form);
|
||||
|
||||
events.faupload(form);
|
||||
|
||||
events.faselect(form);
|
||||
|
||||
events.fieldlist(form);
|
||||
|
||||
events.slider(form);
|
||||
|
||||
events.switcher(form);
|
||||
|
||||
events.tagsinput(form);
|
||||
|
||||
events.autocomplete(form);
|
||||
|
||||
events.favisible(form);
|
||||
},
|
||||
custom: {}
|
||||
},
|
||||
};
|
||||
return Form;
|
||||
});
|
||||
153
public/assets/js/require-frontend.js
Normal file
153
public/assets/js/require-frontend.js
Normal file
@@ -0,0 +1,153 @@
|
||||
require.config({
|
||||
urlArgs: "v=" + requirejs.s.contexts._.config.config.site.version,
|
||||
packages: [{
|
||||
name: 'moment',
|
||||
location: '../libs/moment',
|
||||
main: 'moment'
|
||||
}],
|
||||
//在打包压缩时将会把include中的模块合并到主文件中
|
||||
include: ['css', 'layer', 'toastr', 'fast', 'frontend', 'frontend-init', 'table', 'form', 'dragsort', 'selectpage'],
|
||||
paths: {
|
||||
'lang': "empty:",
|
||||
'form': 'require-form',
|
||||
'table': 'require-table',
|
||||
'upload': 'require-upload',
|
||||
'dropzone': 'dropzone.min',
|
||||
'echarts': 'echarts.min',
|
||||
'echarts-theme': 'echarts-theme',
|
||||
'adminlte': 'adminlte',
|
||||
'bootstrap-table-commonsearch': 'bootstrap-table-commonsearch',
|
||||
'bootstrap-table-template': 'bootstrap-table-template',
|
||||
//
|
||||
// 以下的包从bower的libs目录加载
|
||||
'jquery': '../libs/jquery/dist/jquery.min',
|
||||
'bootstrap': '../libs/bootstrap/dist/js/bootstrap.min',
|
||||
'bootstrap-datetimepicker': '../libs/eonasdan-bootstrap-datetimepicker/build/js/bootstrap-datetimepicker.min',
|
||||
'bootstrap-daterangepicker': '../libs/bootstrap-daterangepicker/daterangepicker',
|
||||
'bootstrap-select': '../libs/bootstrap-select/dist/js/bootstrap-select.min',
|
||||
'bootstrap-select-lang': '../libs/bootstrap-select/dist/js/i18n/defaults-zh_CN',
|
||||
'bootstrap-table': '../libs/bootstrap-table/dist/bootstrap-table.min',
|
||||
'bootstrap-table-export': '../libs/bootstrap-table/dist/extensions/export/bootstrap-table-export.min',
|
||||
'bootstrap-table-fixed-columns': '../libs/bootstrap-table/dist/extensions/fixed-columns/bootstrap-table-fixed-columns',
|
||||
'bootstrap-table-mobile': '../libs/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile',
|
||||
'bootstrap-table-lang': '../libs/bootstrap-table/dist/locale/bootstrap-table-zh-CN',
|
||||
'bootstrap-table-jumpto': '../libs/bootstrap-table/dist/extensions/page-jumpto/bootstrap-table-jumpto',
|
||||
'tableexport': '../libs/tableExport.jquery.plugin/tableExport.min',
|
||||
'dragsort': '../libs/fastadmin-dragsort/jquery.dragsort',
|
||||
'sortable': '../libs/Sortable/Sortable.min',
|
||||
'addtabs': '../libs/fastadmin-addtabs/jquery.addtabs',
|
||||
'slimscroll': '../libs/jquery-slimscroll/jquery.slimscroll',
|
||||
'validator': '../libs/nice-validator/dist/jquery.validator',
|
||||
'validator-lang': '../libs/nice-validator/dist/local/zh-CN',
|
||||
'toastr': '../libs/toastr/toastr',
|
||||
'jstree': '../libs/jstree/dist/jstree.min',
|
||||
'layer': '../libs/fastadmin-layer/dist/layer',
|
||||
'cookie': '../libs/jquery.cookie/jquery.cookie',
|
||||
'cxselect': '../libs/fastadmin-cxselect/js/jquery.cxselect',
|
||||
'template': '../libs/art-template/dist/template-native',
|
||||
'selectpage': '../libs/fastadmin-selectpage/selectpage',
|
||||
'citypicker': '../libs/fastadmin-citypicker/dist/js/city-picker.min',
|
||||
'citypicker-data': '../libs/fastadmin-citypicker/dist/js/city-picker.data'
|
||||
},
|
||||
// shim依赖配置
|
||||
shim: {
|
||||
'addons': ['frontend'],
|
||||
'bootstrap': ['jquery'],
|
||||
'bootstrap-table': {
|
||||
deps: ['bootstrap'],
|
||||
exports: '$.fn.bootstrapTable'
|
||||
},
|
||||
'bootstrap-table-lang': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-export': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-fixed-columns': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-mobile': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-advancedsearch': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-commonsearch': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-template': {
|
||||
deps: ['bootstrap-table', 'template'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'bootstrap-table-jumpto': {
|
||||
deps: ['bootstrap-table'],
|
||||
exports: '$.fn.bootstrapTable.defaults'
|
||||
},
|
||||
'tableexport': {
|
||||
deps: ['jquery'],
|
||||
exports: '$.fn.extend'
|
||||
},
|
||||
'slimscroll': {
|
||||
deps: ['jquery'],
|
||||
exports: '$.fn.extend'
|
||||
},
|
||||
'adminlte': {
|
||||
deps: ['bootstrap', 'slimscroll'],
|
||||
exports: '$.AdminLTE'
|
||||
},
|
||||
'bootstrap-daterangepicker': [
|
||||
'moment/locale/zh-cn'
|
||||
],
|
||||
'bootstrap-datetimepicker': [
|
||||
'moment/locale/zh-cn',
|
||||
],
|
||||
'bootstrap-select-lang': ['bootstrap-select'],
|
||||
'jstree': ['css!../libs/jstree/dist/themes/default/style.css'],
|
||||
'validator-lang': ['validator'],
|
||||
'citypicker': ['citypicker-data', 'css!../libs/fastadmin-citypicker/dist/css/city-picker.css']
|
||||
},
|
||||
baseUrl: requirejs.s.contexts._.config.config.site.cdnurl + '/assets/js/', //资源基础路径
|
||||
map: {
|
||||
'*': {
|
||||
'css': '../libs/require-css/css.min'
|
||||
}
|
||||
},
|
||||
waitSeconds: 60,
|
||||
charset: 'utf-8' // 文件编码
|
||||
});
|
||||
|
||||
require(['jquery', 'bootstrap'], function ($, undefined) {
|
||||
//初始配置
|
||||
var Config = requirejs.s.contexts._.config.config;
|
||||
//将Config渲染到全局
|
||||
window.Config = Config;
|
||||
// 配置语言包的路径
|
||||
var paths = {};
|
||||
paths['lang'] = Config.moduleurl + '/ajax/lang?callback=define&controllername=' + Config.controllername + '&lang=' + Config.language;
|
||||
// 避免目录冲突
|
||||
paths['frontend/'] = 'frontend/';
|
||||
require.config({paths: paths});
|
||||
|
||||
// 初始化
|
||||
$(function () {
|
||||
require(['fast'], function (Fast) {
|
||||
require(['frontend', 'frontend-init', 'addons'], function (Frontend, Addons) {
|
||||
//加载相应模块
|
||||
if (Config.jsname) {
|
||||
require([Config.jsname], function (Controller) {
|
||||
Controller[Config.actionname] != undefined && Controller[Config.actionname]();
|
||||
}, function (e) {
|
||||
console.error(e);
|
||||
// 这里可捕获模块加载的错误
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
68
public/assets/js/require-frontend.min.js
vendored
Normal file
68
public/assets/js/require-frontend.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1087
public/assets/js/require-table.js
Normal file
1087
public/assets/js/require-table.js
Normal file
File diff suppressed because it is too large
Load Diff
468
public/assets/js/require-upload.js
Normal file
468
public/assets/js/require-upload.js
Normal file
@@ -0,0 +1,468 @@
|
||||
define(['jquery', 'bootstrap', 'dropzone', 'template'], function ($, undefined, Dropzone, Template) {
|
||||
var Upload = {
|
||||
list: {},
|
||||
options: {},
|
||||
config: {
|
||||
container: document.body,
|
||||
classname: '.plupload:not([initialized]),.faupload:not([initialized])',
|
||||
previewtpl: '<li class="col-xs-3"><a href="<%=fullurl%>" data-url="<%=url%>" target="_blank" class="thumbnail"><img src="<%=fullurl%>" onerror="this.src=\'' + Fast.api.fixurl("ajax/icon") + '?suffix=<%=suffix%>\';this.onerror=null;" class="img-responsive"></a><a href="javascript:;" class="btn btn-danger btn-xs btn-trash"><i class="fa fa-trash"></i></a></li>',
|
||||
},
|
||||
events: {
|
||||
//初始化
|
||||
onInit: function () {
|
||||
|
||||
},
|
||||
//上传成功的回调
|
||||
onUploadSuccess: function (up, ret, file) {
|
||||
var button = up.element;
|
||||
var onUploadSuccess = up.options.onUploadSuccess;
|
||||
var data = typeof ret.data !== 'undefined' ? ret.data : null;
|
||||
//上传成功后回调
|
||||
if (button) {
|
||||
//如果有文本框则填充
|
||||
var input_id = $(button).data("input-id") ? $(button).data("input-id") : "";
|
||||
if (input_id) {
|
||||
var urlArr = [];
|
||||
var inputObj = $("#" + input_id);
|
||||
if ($(button).data("multiple") && inputObj.val() !== "") {
|
||||
urlArr.push(inputObj.val());
|
||||
}
|
||||
var url = Config.upload.fullmode ? (data.fullurl ? data.fullurl : Fast.api.cdnurl(data.url)) : data.url;
|
||||
urlArr.push(url);
|
||||
inputObj.val(urlArr.join(",")).trigger("change").trigger("validate");
|
||||
}
|
||||
//如果有回调函数
|
||||
var onDomUploadSuccess = $(button).data("upload-success");
|
||||
if (onDomUploadSuccess) {
|
||||
if (typeof onDomUploadSuccess !== 'function' && typeof Upload.api.custom[onDomUploadSuccess] === 'function') {
|
||||
onDomUploadSuccess = Upload.api.custom[onDomUploadSuccess];
|
||||
}
|
||||
if (typeof onDomUploadSuccess === 'function') {
|
||||
var result = onDomUploadSuccess.call(button, data, ret, up, file);
|
||||
if (result === false)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof onUploadSuccess === 'function') {
|
||||
var result = onUploadSuccess.call(button, data, ret, up, file);
|
||||
if (result === false)
|
||||
return;
|
||||
}
|
||||
},
|
||||
//上传错误的回调
|
||||
onUploadError: function (up, ret, file) {
|
||||
var button = up.element;
|
||||
var onUploadError = up.options.onUploadError;
|
||||
var data = typeof ret.data !== 'undefined' ? ret.data : null;
|
||||
if (button) {
|
||||
var onDomUploadError = $(button).data("upload-error");
|
||||
if (onDomUploadError) {
|
||||
if (typeof onDomUploadError !== 'function' && typeof Upload.api.custom[onDomUploadError] === 'function') {
|
||||
onDomUploadError = Upload.api.custom[onDomUploadError];
|
||||
}
|
||||
if (typeof onDomUploadError === 'function') {
|
||||
var result = onDomUploadError.call(button, data, ret, up, file);
|
||||
if (result === false)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof onUploadError === 'function') {
|
||||
var result = onUploadError.call(button, data, ret, up, file);
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
Toastr.error(ret.msg.toString().replace(/(<([^>]+)>)/gi, "") + "(code:" + ret.code + ")");
|
||||
},
|
||||
//服务器响应数据后
|
||||
onUploadResponse: function (response, up, file) {
|
||||
try {
|
||||
var ret = typeof response === 'object' ? response : JSON.parse(response);
|
||||
if (!ret.hasOwnProperty('code')) {
|
||||
$.extend(ret, {code: -2, msg: response, data: null});
|
||||
}
|
||||
} catch (e) {
|
||||
var ret = {code: -1, msg: e.message, data: null};
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
//上传全部结束后
|
||||
onUploadComplete: function (up, files) {
|
||||
var button = up.element;
|
||||
var onUploadComplete = up.options.onUploadComplete;
|
||||
if (button) {
|
||||
var onDomUploadComplete = $(button).data("upload-complete");
|
||||
if (onDomUploadComplete) {
|
||||
if (typeof onDomUploadComplete !== 'function' && typeof Upload.api.custom[onDomUploadComplete] === 'function') {
|
||||
onDomUploadComplete = Upload.api.custom[onDomUploadComplete];
|
||||
}
|
||||
if (typeof onDomUploadComplete === 'function') {
|
||||
var result = onDomUploadComplete.call(button, files);
|
||||
if (result === false)
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof onUploadComplete === 'function') {
|
||||
var result = onUploadComplete.call(button, files);
|
||||
if (result === false) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
api: {
|
||||
//上传接口
|
||||
upload: function (element, onUploadSuccess, onUploadError, onUploadComplete) {
|
||||
element = typeof element === 'undefined' ? Upload.config.classname : element;
|
||||
$(element, Upload.config.container).each(function () {
|
||||
if ($(this).attr("initialized")) {
|
||||
return true;
|
||||
}
|
||||
$(this).attr("initialized", true);
|
||||
var that = this;
|
||||
var id = $(this).prop("id") || $(this).prop("name") || Dropzone.uuidv4();
|
||||
var url = $(this).data("url");
|
||||
var maxsize = $(this).data("maxsize");
|
||||
var maxcount = $(this).data("maxcount");
|
||||
var mimetype = $(this).data("mimetype");
|
||||
var multipart = $(this).data("multipart");
|
||||
var multiple = $(this).data("multiple");
|
||||
|
||||
//填充ID
|
||||
var input_id = $(that).data("input-id") ? $(that).data("input-id") : "";
|
||||
//预览ID
|
||||
var preview_id = $(that).data("preview-id") ? $(that).data("preview-id") : "";
|
||||
|
||||
//上传URL
|
||||
url = url ? url : Config.upload.uploadurl;
|
||||
url = Fast.api.fixurl(url);
|
||||
var chunking = false, chunkSize = Config.upload.chunksize || 2097152, timeout = Config.upload.timeout || 600000;
|
||||
|
||||
//最大可上传文件大小
|
||||
maxsize = typeof maxsize !== "undefined" ? maxsize : Config.upload.maxsize;
|
||||
//文件类型
|
||||
mimetype = typeof mimetype !== "undefined" ? mimetype : Config.upload.mimetype;
|
||||
//请求的表单参数
|
||||
multipart = typeof multipart !== "undefined" ? multipart : Config.upload.multipart;
|
||||
//是否支持批量上传
|
||||
multiple = typeof multiple !== "undefined" ? multiple : Config.upload.multiple;
|
||||
//后缀特殊处理
|
||||
mimetype = mimetype.split(",").map(function (k) {
|
||||
return k.indexOf("/") > -1 ? k : (!k || k === "*" || k.charAt(0) === "." ? k : "." + k);
|
||||
}).join(",");
|
||||
mimetype = mimetype === '*' ? null : mimetype;
|
||||
|
||||
//最大文件限制转换成mb
|
||||
var maxFilesize = (function (maxsize) {
|
||||
var matches = maxsize.toString().match(/^([0-9\.]+)(\w+)$/);
|
||||
var size = matches ? parseFloat(matches[1]) : parseFloat(maxsize),
|
||||
unit = matches ? matches[2].toLowerCase() : 'b';
|
||||
var unitDict = {'b': 0, 'k': 1, 'kb': 1, 'm': 2, 'mb': 2, 'gb': 3, 'g': 3, 'tb': 4, 't': 4};
|
||||
var y = typeof unitDict[unit] !== 'undefined' ? unitDict[unit] : 0;
|
||||
var bytes = size * Math.pow(1024, y);
|
||||
return bytes / Math.pow(1024, 2);
|
||||
}(maxsize));
|
||||
|
||||
var options = $(this).data() || {};
|
||||
options = $.extend(true, {}, options, $(this).data("upload-options") || {});
|
||||
delete options.success;
|
||||
delete options.url;
|
||||
multipart = $.isArray(multipart) ? {} : multipart;
|
||||
var params = $(this).data("params") || {};
|
||||
var category = typeof params.category !== 'undefined' ? params.category : ($(this).data("category") || '');
|
||||
if (category) {
|
||||
// multipart.category = category;
|
||||
}
|
||||
|
||||
Upload.list[id] = new Dropzone(this, $.extend({
|
||||
url: url,
|
||||
params: function (files, xhr, chunk) {
|
||||
var params = multipart;
|
||||
if (chunk) {
|
||||
return $.extend({}, params, {
|
||||
filesize: chunk.file.size,
|
||||
filename: chunk.file.name,
|
||||
chunkid: chunk.file.upload.uuid,
|
||||
chunkindex: chunk.index,
|
||||
chunkcount: chunk.file.upload.totalChunkCount,
|
||||
chunksize: this.options.chunkSize,
|
||||
chunkfilesize: chunk.dataBlock.data.size,
|
||||
width: chunk.file.width || 0,
|
||||
height: chunk.file.height || 0,
|
||||
type: chunk.file.type,
|
||||
});
|
||||
}
|
||||
return params;
|
||||
},
|
||||
chunking: chunking,
|
||||
chunkSize: chunkSize,
|
||||
maxFilesize: maxFilesize,
|
||||
acceptedFiles: mimetype,
|
||||
maxFiles: (maxcount && parseInt(maxcount) > 1 ? maxcount : (multiple ? null : 1)),
|
||||
timeout: timeout,
|
||||
parallelUploads: 1,
|
||||
previewsContainer: false,
|
||||
dictDefaultMessage: __("Drop files here to upload"),
|
||||
dictFallbackMessage: __("Your browser does not support drag'n'drop file uploads"),
|
||||
dictFallbackText: __("Please use the fallback form below to upload your files like in the olden days"),
|
||||
dictFileTooBig: __("File is too big (%sMiB), Max filesize: %sMiB", "{{filesize}}", "{{maxFilesize}}"),
|
||||
dictInvalidFileType: __("You can't upload files of this type"),
|
||||
dictResponseError: __("Server responded with %s code.", "{{statusCode}}"),
|
||||
dictCancelUpload: __("Cancel upload"),
|
||||
dictUploadCanceled: __("Upload canceled"),
|
||||
dictCancelUploadConfirmation: __("Are you sure you want to cancel this upload?"),
|
||||
dictRemoveFile: __("Remove file"),
|
||||
dictMaxFilesExceeded: __("You can only upload a maximum of %s files", "{{maxFiles}}"),
|
||||
init: function () {
|
||||
Upload.events.onInit.call(this);
|
||||
//必须添加dz-message,否则点击icon无法唤起上传窗口
|
||||
$(">i", this.element).addClass("dz-message");
|
||||
this.options.elementHtml = $(this.element).html();
|
||||
},
|
||||
sending: function (file, xhr, formData) {
|
||||
if (typeof file.category !== 'undefined') {
|
||||
formData.append('category', file.category);
|
||||
}
|
||||
},
|
||||
addedfile: function (file) {
|
||||
var params = $(this.element).data("params") || {};
|
||||
var category = typeof params.category !== 'undefined' ? params.category : ($(this.element).data("category") || '');
|
||||
file.category = typeof category === 'function' ? category.call(this, file) : category;
|
||||
},
|
||||
addedfiles: function (files) {
|
||||
if (this.options.maxFiles && (!this.options.maxFiles || this.options.maxFiles > 1) && this.options.inputId) {
|
||||
var inputObj = $("#" + this.options.inputId);
|
||||
if (inputObj.length > 0) {
|
||||
var value = $.trim(inputObj.val());
|
||||
var nums = value === '' ? 0 : value.split(/\,/).length;
|
||||
var remain = this.options.maxFiles - nums;
|
||||
if (remain === 0 || files.length > remain) {
|
||||
files = Array.prototype.slice.call(files, remain);
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
this.removeFile(files[i]);
|
||||
}
|
||||
Toastr.error(__("You can only upload a maximum of %s files", this.options.maxFiles));
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
success: function (file, response) {
|
||||
var ret = Upload.events.onUploadResponse(response, this, file);
|
||||
file.ret = ret;
|
||||
if (ret.code === 1) {
|
||||
Upload.events.onUploadSuccess(this, ret, file);
|
||||
} else {
|
||||
Upload.events.onUploadError(this, ret, file);
|
||||
}
|
||||
},
|
||||
error: function (file, response, xhr) {
|
||||
var responseObj = $("<div>" + (xhr && typeof xhr.responseText !== 'undefined' ? xhr.responseText : response) + "</div>");
|
||||
responseObj.find("style, title, script").remove();
|
||||
var msg = responseObj.text() || __('Network error');
|
||||
var ret = {code: 0, data: null, msg: msg};
|
||||
Upload.events.onUploadError(this, ret, file);
|
||||
},
|
||||
uploadprogress: function (file, progress, bytesSent) {
|
||||
if (file.upload.chunked) {
|
||||
$(this.element).prop("disabled", true).html("<i class='fa fa-upload'></i> " + __('Upload') + Math.floor((file.upload.bytesSent / file.size) * 100) + "%");
|
||||
}
|
||||
},
|
||||
totaluploadprogress: function (progress, bytesSent) {
|
||||
if (this.getActiveFiles().length > 0 && !this.options.chunking) {
|
||||
$(this.element).prop("disabled", true).html("<i class='fa fa-upload'></i> " + __('Upload') + Math.floor(progress) + "%");
|
||||
}
|
||||
},
|
||||
queuecomplete: function () {
|
||||
Upload.events.onUploadComplete(this, this.files);
|
||||
this.removeAllFiles(true);
|
||||
$(this.element).prop("disabled", false).html(this.options.elementHtml);
|
||||
},
|
||||
chunkSuccess: function (chunk, file, response) {
|
||||
},
|
||||
chunksUploaded: function (file, done) {
|
||||
var that = this;
|
||||
Fast.api.ajax({
|
||||
url: this.options.url,
|
||||
data: $.extend({}, multipart, {
|
||||
action: 'merge',
|
||||
filesize: file.size,
|
||||
filename: file.name,
|
||||
chunkid: file.upload.uuid,
|
||||
chunkcount: file.upload.totalChunkCount,
|
||||
})
|
||||
}, function (data, ret) {
|
||||
done(JSON.stringify(ret));
|
||||
return false;
|
||||
}, function (data, ret) {
|
||||
file.accepted = false;
|
||||
that._errorProcessing([file], ret.msg);
|
||||
});
|
||||
},
|
||||
onUploadSuccess: onUploadSuccess,
|
||||
onUploadError: onUploadError,
|
||||
onUploadComplete: onUploadComplete,
|
||||
}, Upload.options, options));
|
||||
|
||||
//拖动排序
|
||||
if (preview_id && multiple) {
|
||||
require(['dragsort'], function () {
|
||||
$("#" + preview_id).dragsort({
|
||||
dragSelector: "li a:not(.btn-trash)",
|
||||
dragEnd: function () {
|
||||
$("#" + preview_id).trigger("fa.preview.change");
|
||||
},
|
||||
placeHolderTemplate: '<li class="col-xs-3"></li>'
|
||||
});
|
||||
});
|
||||
}
|
||||
//刷新隐藏textarea的值
|
||||
var refresh = function (name) {
|
||||
var data = {};
|
||||
var textarea = $("textarea[name='" + name + "']");
|
||||
var container = textarea.prev("ul");
|
||||
$.each($("input,select,textarea", container).serializeArray(), function (i, j) {
|
||||
var reg = /\[?(\w+)\]?\[(\w+)\]$/g;
|
||||
var match = reg.exec(j.name);
|
||||
if (!match)
|
||||
return true;
|
||||
if (!isNaN(match[2])) {
|
||||
data[i] = j.value;
|
||||
} else {
|
||||
match[1] = "x" + parseInt(match[1]);
|
||||
if (typeof data[match[1]] === 'undefined') {
|
||||
data[match[1]] = {};
|
||||
}
|
||||
data[match[1]][match[2]] = j.value;
|
||||
}
|
||||
});
|
||||
var result = [];
|
||||
$.each(data, function (i, j) {
|
||||
result.push(j);
|
||||
});
|
||||
textarea.val(JSON.stringify(result));
|
||||
};
|
||||
if (preview_id && input_id) {
|
||||
$(document.body).on("keyup change", "#" + input_id, function (e) {
|
||||
var inputStr = $("#" + input_id).val();
|
||||
var inputArr = inputStr.split(/\,/);
|
||||
var previewObj = $("#" + preview_id);
|
||||
previewObj.empty();
|
||||
var tpl = previewObj.data("template") ? previewObj.data("template") : "";
|
||||
var extend = previewObj.next().is("textarea") ? previewObj.next("textarea").val() : "{}";
|
||||
var json = {};
|
||||
try {
|
||||
json = JSON.parse(extend);
|
||||
} catch (e) {
|
||||
}
|
||||
$.each(inputArr, function (i, j) {
|
||||
if (!j) {
|
||||
return true;
|
||||
}
|
||||
var suffix = /[\.]?([a-zA-Z0-9]+)$/.exec(j);
|
||||
suffix = suffix ? suffix[1] : 'file';
|
||||
var btnData = $(that).data();
|
||||
var fullurl = typeof btnData.cdnurl!=='undefined' ? Fast.api.cdnurl(j, btnData.cdnurl) : Fast.api.cdnurl(j);
|
||||
j = Config.upload.fullmode ? fullurl : j;
|
||||
var value = (json && typeof json[i] !== 'undefined' ? json[i] : null);
|
||||
var data = {url: j, fullurl: fullurl, data: btnData, key: i, index: i, value: value, row: value, suffix: suffix};
|
||||
var html = tpl ? Template(tpl, data) : Template.render(Upload.config.previewtpl, data);
|
||||
previewObj.append(html);
|
||||
});
|
||||
refresh(previewObj.data("name"));
|
||||
});
|
||||
$("#" + input_id).trigger("change");
|
||||
}
|
||||
if (preview_id) {
|
||||
//监听文本框改变事件
|
||||
$("#" + preview_id).on('change keyup', "input,textarea,select", function () {
|
||||
refresh($(this).closest("ul").data("name"));
|
||||
});
|
||||
// 监听事件
|
||||
$(document.body).on("fa.preview.change", "#" + preview_id, function () {
|
||||
var urlArr = [];
|
||||
$("#" + preview_id + " [data-url]").each(function (i, j) {
|
||||
urlArr.push($(this).data("url"));
|
||||
});
|
||||
if (input_id) {
|
||||
$("#" + input_id).val(urlArr.join(","));
|
||||
}
|
||||
refresh($("#" + preview_id).data("name"));
|
||||
});
|
||||
// 移除按钮事件
|
||||
$(document.body).on("click", "#" + preview_id + " .btn-trash", function () {
|
||||
$(this).closest("li").remove();
|
||||
$("#" + preview_id).trigger("fa.preview.change");
|
||||
});
|
||||
}
|
||||
if (input_id) {
|
||||
$("#" + input_id).closest("form").on("reset", function () {
|
||||
setTimeout($.proxy(function () {
|
||||
$("#" + input_id, this).trigger("change");
|
||||
}, this), 0);
|
||||
});
|
||||
//粘贴上传、拖拽上传
|
||||
$("body").on('paste drop', "#" + input_id, function (event) {
|
||||
var originEvent = event.originalEvent;
|
||||
var button = $(".plupload[data-input-id='" + $(this).attr("id") + "'],.faupload[data-input-id='" + $(this).attr("id") + "']");
|
||||
if (event.type === 'paste' && originEvent.clipboardData && originEvent.clipboardData.items) {
|
||||
var items = originEvent.clipboardData.items;
|
||||
if ((items.length === 1 && items[0].type.indexOf("text") > -1) || (items.length === 2 && items[1].type.indexOf("text") > -1)) {
|
||||
|
||||
} else {
|
||||
Upload.list[button.attr("id")].paste(originEvent);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (event.type === 'drop' && originEvent.dataTransfer && originEvent.dataTransfer.files) {
|
||||
Upload.list[button.attr("id")].drop(originEvent);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
},
|
||||
/**
|
||||
* @deprecated Use upload instead.
|
||||
*/
|
||||
plupload: function (element, onUploadSuccess, onUploadError, onUploadComplete) {
|
||||
return Upload.api.upload(element, onUploadSuccess, onUploadError, onUploadComplete);
|
||||
},
|
||||
/**
|
||||
* @deprecated Use upload instead.
|
||||
*/
|
||||
faupload: function (element, onUploadSuccess, onUploadError, onUploadComplete) {
|
||||
return Upload.api.upload(element, onUploadSuccess, onUploadError, onUploadComplete);
|
||||
},
|
||||
// AJAX异步上传
|
||||
send: function (file, onUploadSuccess, onUploadError, onUploadComplete) {
|
||||
var index = Layer.msg(__('Uploading'), {offset: 't', time: 0});
|
||||
var id = "dropzone-" + Dropzone.uuidv4();
|
||||
$('<button type="button" id="' + id + '" class="btn btn-danger hidden faupload" />').appendTo("body");
|
||||
$("#" + id).data("upload-complete", function (files) {
|
||||
Layer.close(index);
|
||||
Upload.list[id].removeAllFiles(true);
|
||||
});
|
||||
Upload.api.upload("#" + id, onUploadSuccess, onUploadError, onUploadComplete);
|
||||
setTimeout(function () {
|
||||
Upload.list[id].addFile(file);
|
||||
}, 1);
|
||||
},
|
||||
custom: {
|
||||
//自定义上传完成回调
|
||||
afteruploadcallback: function (response) {
|
||||
console.log(this, response);
|
||||
alert("Custom Callback,Response URL:" + response.url);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
;
|
||||
|
||||
return Upload;
|
||||
});
|
||||
2146
public/assets/js/require.js
Normal file
2146
public/assets/js/require.js
Normal file
File diff suppressed because it is too large
Load Diff
5
public/assets/js/require.min.js
vendored
Normal file
5
public/assets/js/require.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
5
public/assets/js/respond.min.js
vendored
Normal file
5
public/assets/js/respond.min.js
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
/*! Respond.js v1.4.2: min/max-width media query polyfill * Copyright 2013 Scott Jehl
|
||||
* Licensed under https://github.com/scottjehl/Respond/blob/master/LICENSE-MIT
|
||||
* */
|
||||
|
||||
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='­<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);
|
||||
663
public/assets/js/tagsinput.js
Normal file
663
public/assets/js/tagsinput.js
Normal file
@@ -0,0 +1,663 @@
|
||||
/*
|
||||
* bootstrap-tagsinput v0.8.0
|
||||
*
|
||||
* For details, see the web site: https://github.com/bootstrap-tagsinput/bootstrap-tagsinput
|
||||
*/
|
||||
|
||||
(function ($) {
|
||||
"use strict";
|
||||
|
||||
var defaultOptions = {
|
||||
tagClass: function (item) {
|
||||
return 'label label-info';
|
||||
},
|
||||
focusClass: 'focus',
|
||||
itemValue: function (item) {
|
||||
return item ? item.toString() : item;
|
||||
},
|
||||
itemText: function (item) {
|
||||
return this.itemValue(item);
|
||||
},
|
||||
itemTitle: function (item) {
|
||||
return null;
|
||||
},
|
||||
freeInput: true,
|
||||
addOnBlur: true,
|
||||
maxTags: undefined,
|
||||
maxChars: undefined,
|
||||
confirmKeys: [13, 44],
|
||||
delimiter: ',',
|
||||
inputMinWidth: 80,
|
||||
delimiterRegex: null,
|
||||
cancelConfirmKeysOnEmpty: false,
|
||||
onTagExists: function (item, $tag) {
|
||||
$tag.hide().fadeIn();
|
||||
},
|
||||
trimValue: false,
|
||||
allowDuplicates: false,
|
||||
triggerChange: true
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor function
|
||||
*/
|
||||
function TagsInput(element, options) {
|
||||
this.isInit = true;
|
||||
this.itemsArray = [];
|
||||
|
||||
this.$element = $(element);
|
||||
this.$element.hide();
|
||||
|
||||
this.isSelect = (element.tagName === 'SELECT');
|
||||
this.multiple = (this.isSelect && element.hasAttribute('multiple'));
|
||||
this.objectItems = options && options.itemValue;
|
||||
this.placeholderText = element.hasAttribute('placeholder') ? this.$element.attr('placeholder') : '';
|
||||
this.inputSize = Math.max(1, this.placeholderText.length);
|
||||
|
||||
this.$container = $('<div class="bootstrap-tagsinput"></div>');
|
||||
this.$input = $('<input type="text" placeholder="' + this.placeholderText + '"/>').appendTo(this.$container);
|
||||
|
||||
this.$element.before(this.$container);
|
||||
this.build(options);
|
||||
this.isInit = false;
|
||||
}
|
||||
|
||||
TagsInput.prototype = {
|
||||
constructor: TagsInput,
|
||||
|
||||
/**
|
||||
* Adds the given item as a new tag. Pass true to dontPushVal to prevent
|
||||
* updating the elements val()
|
||||
*/
|
||||
add: function (item, dontPushVal, options) {
|
||||
var self = this;
|
||||
|
||||
if (self.options.maxTags && self.itemsArray.length >= self.options.maxTags)
|
||||
return;
|
||||
|
||||
// Ignore falsey values, except false
|
||||
if (item !== false && !item)
|
||||
return;
|
||||
|
||||
// Trim value
|
||||
if (typeof item === "string" && self.options.trimValue) {
|
||||
item = $.trim(item);
|
||||
}
|
||||
|
||||
// Throw an error when trying to add an object while the itemValue option was not set
|
||||
if (typeof item === "object" && !self.objectItems)
|
||||
throw("Can't add objects when itemValue option is not set");
|
||||
|
||||
// Ignore strings only containg whitespace
|
||||
if (item.toString().match(/^\s*$/))
|
||||
return;
|
||||
|
||||
// If SELECT but not multiple, remove current tag
|
||||
if (self.isSelect && !self.multiple && self.itemsArray.length > 0)
|
||||
self.remove(self.itemsArray[0]);
|
||||
|
||||
if (typeof item === "string" && this.$element[0].tagName === 'INPUT') {
|
||||
var delimiter = (self.options.delimiterRegex) ? self.options.delimiterRegex : self.options.delimiter;
|
||||
var items = item.split(delimiter);
|
||||
if (items.length > 1) {
|
||||
for (var i = 0; i < items.length; i++) {
|
||||
this.add(items[i], true);
|
||||
}
|
||||
|
||||
if (!dontPushVal)
|
||||
self.pushVal(self.options.triggerChange);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
var itemValue = self.options.itemValue(item),
|
||||
itemText = self.options.itemText(item),
|
||||
tagClass = self.options.tagClass(item),
|
||||
itemTitle = self.options.itemTitle(item);
|
||||
|
||||
// Ignore items allready added
|
||||
var existing = $.grep(self.itemsArray, function (item) {
|
||||
return self.options.itemValue(item) === itemValue;
|
||||
})[0];
|
||||
if (existing && !self.options.allowDuplicates) {
|
||||
// Invoke onTagExists
|
||||
if (self.options.onTagExists) {
|
||||
var $existingTag = $(".tag", self.$container).filter(function () {
|
||||
return $(this).data("item") === existing;
|
||||
});
|
||||
self.options.onTagExists(item, $existingTag);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// if length greater than limit
|
||||
if (self.items().toString().length + item.length + 1 > self.options.maxInputLength)
|
||||
return;
|
||||
|
||||
// raise beforeItemAdd arg
|
||||
var beforeItemAddEvent = $.Event('beforeItemAdd', {item: item, cancel: false, options: options});
|
||||
self.$element.trigger(beforeItemAddEvent);
|
||||
if (beforeItemAddEvent.cancel)
|
||||
return;
|
||||
|
||||
// register item in internal array and map
|
||||
self.itemsArray.push(item);
|
||||
|
||||
// add a tag element
|
||||
|
||||
var $tag = $('<span class="tag ' + htmlEncode(tagClass) + (itemTitle !== null ? ('" title="' + itemTitle) : '') + '">' + htmlEncode(itemText) + '<span data-role="remove"></span></span>');
|
||||
$tag.data('item', item);
|
||||
self.findInputWrapper().before($tag);
|
||||
$tag.after(' ');
|
||||
|
||||
// Check to see if the tag exists in its raw or uri-encoded form
|
||||
var optionExists = (
|
||||
$('option[value="' + encodeURIComponent(itemValue) + '"]', self.$element).length ||
|
||||
$('option[value="' + htmlEncode(itemValue) + '"]', self.$element).length
|
||||
);
|
||||
|
||||
// add <option /> if item represents a value not present in one of the <select />'s options
|
||||
if (self.isSelect && !optionExists) {
|
||||
var $option = $('<option selected>' + htmlEncode(itemText) + '</option>');
|
||||
$option.data('item', item);
|
||||
$option.attr('value', itemValue);
|
||||
self.$element.append($option);
|
||||
}
|
||||
|
||||
if (!dontPushVal)
|
||||
self.pushVal(self.options.triggerChange);
|
||||
|
||||
// Add class when reached maxTags
|
||||
if (self.options.maxTags === self.itemsArray.length || self.items().toString().length === self.options.maxInputLength)
|
||||
self.$container.addClass('bootstrap-tagsinput-max');
|
||||
|
||||
// If using autocomplete, once the tag has been added, clear the autocomplete value so it does not stick around in the input.
|
||||
if (self.options.autocomplete) {
|
||||
// self.$input.autocomplete('clear');
|
||||
}
|
||||
|
||||
if (this.isInit) {
|
||||
self.$element.trigger($.Event('itemAddedOnInit', {item: item, options: options}));
|
||||
} else {
|
||||
self.$element.trigger($.Event('itemAdded', {item: item, options: options}));
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the given item. Pass true to dontPushVal to prevent updating the
|
||||
* elements val()
|
||||
*/
|
||||
remove: function (item, dontPushVal, options) {
|
||||
var self = this;
|
||||
|
||||
if (self.objectItems) {
|
||||
if (typeof item === "object")
|
||||
item = $.grep(self.itemsArray, function (other) {
|
||||
return self.options.itemValue(other) == self.options.itemValue(item);
|
||||
});
|
||||
else
|
||||
item = $.grep(self.itemsArray, function (other) {
|
||||
return self.options.itemValue(other) == item;
|
||||
});
|
||||
|
||||
item = item[item.length - 1];
|
||||
}
|
||||
|
||||
if (item) {
|
||||
var beforeItemRemoveEvent = $.Event('beforeItemRemove', {item: item, cancel: false, options: options});
|
||||
self.$element.trigger(beforeItemRemoveEvent);
|
||||
if (beforeItemRemoveEvent.cancel)
|
||||
return;
|
||||
|
||||
$('.tag', self.$container).filter(function () {
|
||||
return $(this).data('item') === item;
|
||||
}).remove();
|
||||
$('option', self.$element).filter(function () {
|
||||
return $(this).data('item') === item;
|
||||
}).remove();
|
||||
if ($.inArray(item, self.itemsArray) !== -1)
|
||||
self.itemsArray.splice($.inArray(item, self.itemsArray), 1);
|
||||
}
|
||||
|
||||
if (!dontPushVal)
|
||||
self.pushVal(self.options.triggerChange);
|
||||
|
||||
// Remove class when reached maxTags
|
||||
if (self.options.maxTags > self.itemsArray.length)
|
||||
self.$container.removeClass('bootstrap-tagsinput-max');
|
||||
|
||||
self.$element.trigger($.Event('itemRemoved', {item: item, options: options}));
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all items
|
||||
*/
|
||||
removeAll: function () {
|
||||
var self = this;
|
||||
|
||||
$('.tag', self.$container).remove();
|
||||
$('option', self.$element).remove();
|
||||
|
||||
while (self.itemsArray.length > 0)
|
||||
self.itemsArray.pop();
|
||||
|
||||
self.pushVal(self.options.triggerChange);
|
||||
},
|
||||
|
||||
/**
|
||||
* Refreshes the tags so they match the text/value of their corresponding
|
||||
* item.
|
||||
*/
|
||||
refresh: function () {
|
||||
var self = this;
|
||||
$('.tag', self.$container).each(function () {
|
||||
var $tag = $(this),
|
||||
item = $tag.data('item'),
|
||||
itemValue = self.options.itemValue(item),
|
||||
itemText = self.options.itemText(item),
|
||||
tagClass = self.options.tagClass(item);
|
||||
|
||||
// Update tag's class and inner text
|
||||
$tag.attr('class', null);
|
||||
$tag.addClass('tag ' + htmlEncode(tagClass));
|
||||
$tag.contents().filter(function () {
|
||||
return this.nodeType == 3;
|
||||
})[0].nodeValue = htmlEncode(itemText);
|
||||
|
||||
if (self.isSelect) {
|
||||
var option = $('option', self.$element).filter(function () {
|
||||
return $(this).data('item') === item;
|
||||
});
|
||||
option.attr('value', itemValue);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* reset the items
|
||||
*/
|
||||
reset: function () {
|
||||
var val = this.$element.val();
|
||||
this.removeAll();
|
||||
this.add(val);
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the items added as tags
|
||||
*/
|
||||
items: function () {
|
||||
return this.itemsArray;
|
||||
},
|
||||
|
||||
/**
|
||||
* Assembly value by retrieving the value of each item, and set it on the
|
||||
* element.
|
||||
*/
|
||||
pushVal: function () {
|
||||
var self = this,
|
||||
val = $.map(self.items(), function (item) {
|
||||
return self.options.itemValue(item).toString();
|
||||
});
|
||||
|
||||
self.$element.val(val, true);
|
||||
|
||||
if (self.options.triggerChange)
|
||||
self.$element.trigger('change');
|
||||
},
|
||||
|
||||
/**
|
||||
* Initializes the tags input behaviour on the element
|
||||
*/
|
||||
build: function (options) {
|
||||
var self = this;
|
||||
|
||||
self.options = $.extend({}, defaultOptions, options);
|
||||
// When itemValue is set, freeInput should always be false
|
||||
if (self.objectItems)
|
||||
self.options.freeInput = false;
|
||||
|
||||
makeOptionItemFunction(self.options, 'itemValue');
|
||||
makeOptionItemFunction(self.options, 'itemText');
|
||||
makeOptionFunction(self.options, 'tagClass');
|
||||
|
||||
if (self.options.autocomplete) {
|
||||
var autocomplete = self.options.autocomplete || {};
|
||||
|
||||
// makeOptionFunction(autocomplete, 'lookup');
|
||||
self.$input.autocomplete($.extend(true, {}, {
|
||||
type: 'post',
|
||||
params: function (q) {
|
||||
var params = {};
|
||||
params['name'] = self.$element.prop("name");
|
||||
params['tags'] = self.$element.val();
|
||||
return params;
|
||||
},
|
||||
onSelect: function (suggestion) {
|
||||
self.add(suggestion.value);
|
||||
self.$input.val('').width(self.options.inputMinWidth).focus();
|
||||
}
|
||||
}, autocomplete));
|
||||
}
|
||||
|
||||
self.$container.on('click', $.proxy(function (event) {
|
||||
if (!self.$element.attr('disabled')) {
|
||||
self.$input.removeAttr('disabled');
|
||||
}
|
||||
self.$input.focus();
|
||||
if (self.options.autocomplete && self.$input.autocomplete().visible) {
|
||||
clearTimeout(self.$input.autocomplete().blurTimeoutId);
|
||||
}
|
||||
}, self));
|
||||
|
||||
if (self.options.addOnBlur && self.options.freeInput) {
|
||||
self.$input.on('focusout', $.proxy(function (event) {
|
||||
// HACK: only process on focusout when no autocomplete opened, to
|
||||
// avoid adding the autocomplete text as tag
|
||||
if (!self.options.autocomplete) {
|
||||
self.add(self.$input.val());
|
||||
self.$input.val('').css("width", self.options.inputMinWidth);
|
||||
} else {
|
||||
var autocomplete = self.$input.autocomplete();
|
||||
setTimeout(function () {
|
||||
if (!autocomplete.visible && self.$input.val() !== '') {
|
||||
self.add(self.$input.val());
|
||||
self.$input.val('').css("width", self.options.inputMinWidth);
|
||||
}
|
||||
}, 210);
|
||||
}
|
||||
}, self));
|
||||
}
|
||||
|
||||
// Toggle the 'focus' css class on the container when it has focus
|
||||
self.$container.on({
|
||||
focusin: function () {
|
||||
self.$container.addClass(self.options.focusClass);
|
||||
},
|
||||
focusout: function () {
|
||||
self.$container.removeClass(self.options.focusClass);
|
||||
},
|
||||
});
|
||||
|
||||
self.$container.on('keydown', 'input', $.proxy(function (event) {
|
||||
var $input = $(event.target),
|
||||
$inputWrapper = self.findInputWrapper();
|
||||
|
||||
if (self.$element.attr('disabled')) {
|
||||
self.$input.attr('disabled', 'disabled');
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event.which) {
|
||||
// BACKSPACE
|
||||
case 8:
|
||||
if (doGetCaretPosition($input[0]) === 0) {
|
||||
var prev = $inputWrapper.prev();
|
||||
if (prev.length) {
|
||||
self.remove(prev.data('item'));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// DELETE
|
||||
case 46:
|
||||
if (doGetCaretPosition($input[0]) === 0) {
|
||||
var next = $inputWrapper.next();
|
||||
if (next.length) {
|
||||
self.remove(next.data('item'));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
// LEFT ARROW
|
||||
case 37:
|
||||
// Try to move the input before the previous tag
|
||||
var $prevTag = $inputWrapper.prev();
|
||||
if ($input.val().length === 0 && $prevTag[0]) {
|
||||
$prevTag.before($inputWrapper);
|
||||
$input.focus();
|
||||
}
|
||||
break;
|
||||
// RIGHT ARROW
|
||||
case 39:
|
||||
// Try to move the input after the next tag
|
||||
var $nextTag = $inputWrapper.next();
|
||||
if ($input.val().length === 0 && $nextTag[0]) {
|
||||
$nextTag.after($inputWrapper);
|
||||
$input.focus();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
// ignore
|
||||
}
|
||||
|
||||
$input.css('width', self.getInputTextWidth());
|
||||
|
||||
}, self));
|
||||
|
||||
self.$container.on('keypress', 'input', $.proxy(function (event) {
|
||||
var $input = $(event.target);
|
||||
|
||||
if (self.$element.attr('disabled')) {
|
||||
self.$input.attr('disabled', 'disabled');
|
||||
return;
|
||||
}
|
||||
|
||||
var text = $input.val(),
|
||||
maxLengthReached = self.options.maxChars && text.length >= self.options.maxChars;
|
||||
if (self.options.freeInput && (keyCombinationInList(event, self.options.confirmKeys) || maxLengthReached)) {
|
||||
// Only attempt to add a tag if there is data in the field
|
||||
if (text.length !== 0) {
|
||||
self.add(maxLengthReached ? text.substr(0, self.options.maxChars) : text);
|
||||
$input.val('').css("width", self.options.inputMinWidth);
|
||||
}
|
||||
|
||||
// If the field is empty, let the event triggered fire as usual
|
||||
if (self.options.cancelConfirmKeysOnEmpty === false) {
|
||||
event.preventDefault();
|
||||
}
|
||||
}
|
||||
|
||||
$input.css('width', self.getInputTextWidth());
|
||||
|
||||
}, self));
|
||||
|
||||
// Remove icon clicked
|
||||
self.$container.on('click', '[data-role=remove]', $.proxy(function (event) {
|
||||
if (self.$element.attr('disabled')) {
|
||||
return;
|
||||
}
|
||||
self.remove($(event.target).closest('.tag').data('item'));
|
||||
}, self));
|
||||
|
||||
// Only add existing value as tags when using strings as tags
|
||||
if (self.options.itemValue === defaultOptions.itemValue) {
|
||||
if (self.$element[0].tagName === 'INPUT') {
|
||||
self.add(self.$element.val());
|
||||
} else {
|
||||
$('option', self.$element).each(function () {
|
||||
self.add($(this).attr('value'), true);
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes all tagsinput behaviour and unregsiter all event handlers
|
||||
*/
|
||||
destroy: function () {
|
||||
var self = this;
|
||||
|
||||
// Unbind events
|
||||
self.$container.off('keypress', 'input');
|
||||
self.$container.off('click', '[role=remove]');
|
||||
|
||||
self.$container.remove();
|
||||
self.$element.removeData('tagsinput');
|
||||
self.$element.show();
|
||||
},
|
||||
|
||||
/**
|
||||
* Sets focus on the tagsinput
|
||||
*/
|
||||
focus: function () {
|
||||
this.$input.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the internal input element
|
||||
*/
|
||||
input: function () {
|
||||
return this.$input;
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns the element which is wrapped around the internal input. This
|
||||
* is normally the $container, but typeahead.js moves the $input element.
|
||||
*/
|
||||
findInputWrapper: function () {
|
||||
var elt = this.$input[0],
|
||||
container = this.$container[0];
|
||||
while (elt && elt.parentNode !== container)
|
||||
elt = elt.parentNode;
|
||||
|
||||
return $(elt);
|
||||
},
|
||||
/**
|
||||
* Get input text width
|
||||
* @returns {number}
|
||||
*/
|
||||
getInputTextWidth: function () {
|
||||
var $input = this.$input;
|
||||
var self = this;
|
||||
var msgspan = $input.next().length > 0 ? $input.next() : $("<span />").addClass("tagsinput-text").insertAfter($input);
|
||||
var textWidth = msgspan.text($input.val()).outerWidth();
|
||||
textWidth = Math.max(textWidth, self.options.inputMinWidth);
|
||||
textWidth = Math.min(textWidth, self.$container.innerWidth());
|
||||
return textWidth;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Register JQuery plugin
|
||||
*/
|
||||
$.fn.tagsinput = function (arg1, arg2, arg3) {
|
||||
var results = [];
|
||||
|
||||
this.each(function () {
|
||||
var tagsinput = $(this).data('tagsinput');
|
||||
// Initialize a new tags input
|
||||
if (!tagsinput) {
|
||||
tagsinput = new TagsInput(this, $.extend(true, {}, arg1, $(this).data('tagsinput-options') || {}));
|
||||
$(this).data('tagsinput', tagsinput);
|
||||
results.push(tagsinput);
|
||||
|
||||
if (this.tagName === 'SELECT') {
|
||||
$('option', $(this)).attr('selected', 'selected');
|
||||
}
|
||||
|
||||
// Init tags from $(this).val()
|
||||
$(this).val($(this).val());
|
||||
} else if (!arg1 && !arg2) {
|
||||
// tagsinput already exists
|
||||
// no function, trying to init
|
||||
results.push(tagsinput);
|
||||
} else if (tagsinput[arg1] !== undefined) {
|
||||
// Invoke function on existing tags input
|
||||
if (tagsinput[arg1].length === 3 && arg3 !== undefined) {
|
||||
var retVal = tagsinput[arg1](arg2, null, arg3);
|
||||
} else {
|
||||
var retVal = tagsinput[arg1](arg2);
|
||||
}
|
||||
if (retVal !== undefined)
|
||||
results.push(retVal);
|
||||
}
|
||||
});
|
||||
|
||||
return results.length > 1 ? results : results[0];
|
||||
};
|
||||
|
||||
$.fn.tagsinput.Constructor = TagsInput;
|
||||
|
||||
/**
|
||||
* Most options support both a string or number as well as a function as
|
||||
* option value. This function makes sure that the option with the given
|
||||
* key in the given options is wrapped in a function
|
||||
*/
|
||||
function makeOptionItemFunction(options, key) {
|
||||
if (typeof options[key] !== 'function') {
|
||||
var propertyName = options[key];
|
||||
options[key] = function (item) {
|
||||
return item[propertyName];
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function makeOptionFunction(options, key) {
|
||||
if (typeof options[key] !== 'function') {
|
||||
var value = options[key];
|
||||
options[key] = function () {
|
||||
return value;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* HtmlEncodes the given value
|
||||
*/
|
||||
var htmlEncodeContainer = $('<div />');
|
||||
|
||||
function htmlEncode(value) {
|
||||
if (value) {
|
||||
return htmlEncodeContainer.text(value).html();
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the position of the caret in the given input field
|
||||
* http://flightschool.acylt.com/devnotes/caret-position-woes/
|
||||
*/
|
||||
function doGetCaretPosition(oField) {
|
||||
var iCaretPos = 0;
|
||||
if (document.selection) {
|
||||
oField.focus();
|
||||
var oSel = document.selection.createRange();
|
||||
oSel.moveStart('character', -oField.value.length);
|
||||
iCaretPos = oSel.text.length;
|
||||
} else if (oField.selectionStart || oField.selectionStart == '0') {
|
||||
iCaretPos = oField.selectionStart;
|
||||
}
|
||||
return (iCaretPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns boolean indicates whether user has pressed an expected key combination.
|
||||
* @param object keyPressEvent: JavaScript event object, refer
|
||||
* http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
|
||||
* @param object lookupList: expected key combinations, as in:
|
||||
* [13, {which: 188, shiftKey: true}]
|
||||
*/
|
||||
function keyCombinationInList(keyPressEvent, lookupList) {
|
||||
var found = false;
|
||||
$.each(lookupList, function (index, keyCombination) {
|
||||
if (typeof (keyCombination) === 'number' && keyPressEvent.which === keyCombination) {
|
||||
found = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (keyPressEvent.which === keyCombination.which) {
|
||||
var alt = !keyCombination.hasOwnProperty('altKey') || keyPressEvent.altKey === keyCombination.altKey,
|
||||
shift = !keyCombination.hasOwnProperty('shiftKey') || keyPressEvent.shiftKey === keyCombination.shiftKey,
|
||||
ctrl = !keyCombination.hasOwnProperty('ctrlKey') || keyPressEvent.ctrlKey === keyCombination.ctrlKey;
|
||||
if (alt && shift && ctrl) {
|
||||
found = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
})(window.jQuery);
|
||||
Reference in New Issue
Block a user