71 Commits
Author SHA1 Message Date
新亮andGitHub 8fd9a005d1 Update README.md 2023-12-23 08:57:01 +08:00
新亮andGitHub 4530dab87b Merge pull request #82 from zhoumengkang/master
日志目录稍做屏蔽
2022-07-31 09:28:47 +08:00
mengkang.zmk bf4a413bd0 清空 logs 目录 2022-07-24 09:03:27 +08:00
周梦康andGitHub 79aa86f278 Merge branch 'xinliangnote:master' into master 2022-07-24 08:53:42 +08:00
mengkang.zmk 866bed5522 清空 logs 目录 2022-07-21 15:55:42 +08:00
新亮 61cc349cb4 fix(1.2.8): 修复生成 swagger doc 后,服务无法启动的问题 2022-07-03 13:23:53 +08:00
mengkang.zmk 6825b4e5b1 Changes 2022-06-24 14:11:41 +08:00
mengkang.zmk 62d7ac5cd9 Merge remote-tracking branch 'origin/master' 2022-06-24 13:57:34 +08:00
mengkang.zmk b630456b90 屏蔽日志文件提交 2022-06-24 13:57:12 +08:00
新亮andGitHub bbe181817c Merge pull request #79 from zhoumengkang/master
与上次类似的登录窗口打开的 js 兼容性调整
2022-06-18 17:46:15 +08:00
周梦康andGitHub 15e99398cb Merge branch 'xinliangnote:master' into master 2022-06-16 14:32:28 +08:00
mengkang.zmk dd19eab5d5 同上 2022-06-16 14:09:09 +08:00
新亮andGitHub 7cdb8ee6b4 Merge pull request #78 from zhoumengkang/master
解决 chrome 打开新窗口被拦截的问题
2022-06-13 16:48:48 +08:00
周梦康andGitHub 400e0bb3f2 解决父窗口和子窗口跳转的问题 2022-06-12 22:10:17 +08:00
周梦康andGitHub 14f6853c2b Update httpclient.js
解决 chrome 打开新创被拦截的问题
参考 https://blog.csdn.net/oscar999/article/details/124505724
2022-06-12 18:44:37 +08:00
新亮 4c37a7e6b5 feature(1.2.8): swagger 接口文档新增 Security
- 将 middleware 命名为 interceptor
- 将 deploy 命名为 deployments
- 移除 pkg/errno
- 使用 proposal 目录
- 优化代码
2021-11-28 13:25:27 +08:00
新亮 fc7e58db04 feature(1.2.8): 优化 graph 2021-11-21 15:59:23 +08:00
新亮 4e3c2afafd feature(1.2.8): 调整 internal 目录结构
- 格式化代码
2021-11-21 13:29:50 +08:00
新亮 63499a432e feature(1.2.8): 调整 internal 目录结构 2021-11-21 13:23:27 +08:00
新亮 498033753e feature(1.2.8): 优化代码
- 删除 third_party_request
2021-11-20 17:19:08 +08:00
新亮 b05ed0b59d feature(1.2.8): 优化代码
- cron 相关
- socket 相关
2021-11-20 16:46:13 +08:00
新亮 8ed27cdce1 feature(1.2.8): 使用 embed 打包静态资源
- go version 升级为 1.16
- 使用 embed 特性,将静态资源打包进二进制文件
- 优化代码
2021-11-20 15:01:50 +08:00
新亮 9aa0067e07 perf(时区): 默认设置为中国时区 2021-11-13 15:21:14 +08:00
新亮andGitHub e2cecae7b1 Merge pull request #57 from malphitee/bugfix/malphitee/fix_httpclientjs_date_err
修复月份判定错误导致的签名信息错误
2021-10-01 20:33:09 +08:00
johnnliu e22593b708 修复月份判定的错误 2021-10-01 16:34:30 +08:00
新亮 05f337088e feature(1.2.8): 新增 websocket 模块
- 修改文档
2021-09-20 19:25:53 +08:00
新亮 17be120c06 feature(1.2.8): 新增 websocket 模块
- import gorilla/websocket
- 新增 实用工具箱->WebSocket 栏目
2021-09-20 19:18:15 +08:00
新亮 77e8d58298 fix(mysqlmd): 修复生成数据表 CURD BUG
- 修复当数据表前缀相同时,重复生成的问题,例如 表名:admin、admin_menu
- 修复当字段后缀为数字时,生成错误的问题,例如 字段:test_1、test_2
2021-09-11 16:10:19 +08:00
新亮 f47f57ef3c feature(1.2.7): 新增 cron_server - 后台任务
- 优化代码;
2021-09-05 17:53:50 +08:00
新亮 f17f6a74d2 feature(1.2.7): 依赖组件升级
- gin-gonic/gin 升级至 v1.7.0;
- go-playground/validator/v10 升级至 v10.4.1;
2021-08-29 20:20:01 +08:00
新亮 382c7d3c8f feature(1.2.7): 新增 cron_server - 后台任务
- import jakecoffman/cron ;
- 可在 WEB 界面中进行新增任务、编辑任务、手动执行任务等;
- 新增 cron.log 记录后台任务执行的日志;
- 调整项目初始化,使其支持安装后台任务模块;
2021-08-28 15:09:20 +08:00
新亮 b382919cb5 feature(1.2.7): 新增 WEB 模块 - 后台任务
- 新增数据表:cron_task;
- 后台新增后台任务模块,支持(创建、编辑、启用/禁用、列表);
- 调整项目初始化,使其支持安装后台任务模块;
- 调整服务升级指引,1.2.6 -> 1.2.7;
2021-08-21 21:04:42 +08:00
新亮 22bfb9ad10 fix(gormgen): 修复 gormgen.sh bug
- 当 $GOPATH/bin 不存在时,进行创建目录
2021-08-21 15:22:17 +08:00
新亮andGitHub 4254184098 Merge pull request #48 from anserme/master
bugs fix
2021-07-18 23:03:04 +08:00
anserme bb09c70a60 bug fix 2021-07-18 22:28:06 +08:00
anserme 65873cbfaa bugs fix 2021-07-18 22:25:24 +08:00
anserme 6af343d0b1 bugs fix
修复win下环境变量错误使用的问题
2021-07-16 12:57:20 +08:00
新亮 62367a041a feature(参数验证): 优化 gin 参数验证的错误信息
- 新增 internal/pkg/validation 包,详情:https://github.com/xinliangnote/go-gin-api/issues/44
- 调整 code 包位置,移动至 internal/pkg/code 目录。

Closes #44
2021-07-10 22:38:30 +08:00
新亮 1b013e2023 docs(文档): 修改文档
- 修改 .gitignore 文件
- 修改 README.md 文件
- 修改 en.md 文件
2021-07-10 22:24:43 +08:00
新亮 eba8929b4d feature(安装): 安装时新增选择语言包
- 安装时新增选择语言包
- 优化代码并删除无用的代码
2021-06-26 12:06:20 +08:00
新亮笔记andGitHub 44ca2698cd Merge pull request #42 from anserme/master
fix(代码生成工具):  windows support

- 新增 windows bat 文件  
- 新增 en.md 文件
2021-06-22 16:15:36 +08:00
anserme 2c5683cd14 fix windows support 2021-06-22 15:20:07 +08:00
anserme 8ca47f743d Add en.md 2021-06-22 15:19:08 +08:00
新亮 a3607106d3 upgrade 2021-06-12 16:19:29 +08:00
新亮 6d9a07f5dd upgrade 2021-05-22 16:05:51 +08:00
新亮 a6947b59ac upgrade 2021-05-15 13:01:30 +08:00
新亮 ec3c9f0ccf upgrade 2021-05-09 21:43:23 +08:00
新亮笔记andGitHub 8fbcb5d717 upgrade 2021-05-07 20:12:02 +08:00
新亮笔记andGitHub 6f71852686 upgrade 2021-05-07 20:11:01 +08:00
新亮 9cace3337b upgrade 2021-05-05 17:20:48 +08:00
新亮 0dbd4b0935 upgrade 2021-04-24 10:12:03 +08:00
新亮 1f85d8df61 upgrade 2021-04-18 19:54:31 +08:00
新亮 3e1ef9c658 upgrade 2021-04-10 16:02:34 +08:00
新亮 8a6a34348f # 22 add web - admin/login 2021-04-10 15:05:50 +08:00
新亮 66a5e29c9c #21 add tool - view log 2021-04-04 21:14:15 +08:00
新亮 84cc0c9cbc #20 add web-authorized 2021-03-28 15:52:02 +08:00
新亮 3e918fce59 #18 add web 2021-03-20 22:05:59 +08:00
新亮 36ef904211 #17 add init.sh 2021-03-13 21:44:56 +08:00
新亮 49ccaf9bec #16 optimize handlergen.sh 2021-03-13 21:23:22 +08:00
新亮 4381a9a6f6 #15 optimize gormgen.sh 2021-03-13 14:14:31 +08:00
新亮 5e5db8917d #14 optimize third_party_request 2021-03-13 13:53:52 +08:00
新亮 f7b3dbae5e #13 Where{FieldName}In Where{FieldName}NotIn 2021-03-06 14:12:13 +08:00
新亮 5d7975056c #12 resubmit middlerware 2021-03-06 13:28:38 +08:00
新亮 499e171d63 #11 code generator 2021-02-28 14:14:56 +08:00
新亮 8d6cd2174e #11 code generator 2021-02-28 10:05:29 +08:00
新亮 3823eee2ca #11 code generator 2021-02-27 09:29:34 +08:00
新亮 0b6b9dd69f upgrade 2021-02-20 20:43:39 +08:00
新亮 7327275b7a upgrade 2021-02-20 10:02:53 +08:00
新亮 9b5028e9de upgrade 2021-02-20 09:59:36 +08:00
新亮 cc8012b09d upgrade 2021-02-19 22:00:01 +08:00
新亮 334bfbb4aa upgrade 2021-02-09 09:52:50 +08:00
413 changed files with 51419 additions and 3335 deletions
+19 -5
View File
@@ -1,5 +1,19 @@
/.vscode
.vscode
/.idea
.idea
mfmt
# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
*.idea
# Test binary, built with `go test -c`
*.test
# Output of the go coverage tool, specifically when used with LiteIDE
*.out
# Dependency directories (remove the comment below to include it)
# vendor/
# Project runtime log
logs/*.log
+36
View File
@@ -0,0 +1,36 @@
# FROM 基于 golang:1.16-alpine
FROM golang:1.16-alpine AS builder
# ENV 设置环境变量
ENV GOPATH=/opt/repo
ENV GO111MODULE=on
ENV GOPROXY=https://goproxy.io,direct
# COPY 源路径 目标路径
COPY . $GOPATH/src/github.com/xinliangnote/go-gin-api
# RUN 执行 go build .
RUN cd $GOPATH/src/github.com/xinliangnote/go-gin-api && go build .
# FROM 基于 alpine:latest
FROM alpine:latest
# RUN 设置代理镜像
RUN echo -e http://mirrors.ustc.edu.cn/alpine/v3.13/main/ > /etc/apk/repositories
# RUN 设置 Asia/Shanghai 时区
RUN apk --no-cache add tzdata && \
ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \
echo "Asia/Shanghai" > /etc/timezone
# COPY 源路径 目标路径 从镜像中 COPY
COPY --from=builder /opt/repo/src/github.com/xinliangnote/go-gin-api /opt
# EXPOSE 设置端口映射
EXPOSE 9999/tcp
# WORKDIR 设置工作目录
WORKDIR /opt
# CMD 设置启动命令
CMD ["./go-gin-api", "-env", "fat"]
+19 -18
View File
@@ -13,38 +13,39 @@
1. 支持 [Swagger](https://github.com/swaggo/gin-swagger) 接口文档生成
1. 支持 [GraphQL](https://github.com/99designs/gqlgen) 查询语言
1. 支持 trace 项目内部链路追踪
1. 支持 [pprof](https://github.com/gin-contrib/pprof) 性能剖析
1. 支持 [jwt](https://github.com/dgrijalva/jwt-go) 接口鉴权
1. 支持 [pprof](https://github.com/gin-contrib/pprof) 性能剖析
1. 支持 errno 统一定义错误码
1. 支持 [zap](https://go.uber.org/zap) 日志收集
1. 支持 [viper](https://github.com/spf13/viper) 配置文件解析
1. 支持 [grom](https://gorm.io/gorm) 数据库组件
1. 支持 [gorm](https://gorm.io/gorm) 数据库组件
1. 支持 [go-redis](https://github.com/go-redis/redis/v7) 组件
1. 支持 RESTful API 返回值规范
1. 支持 生成数据表 CURD、控制器方法 等代码生成器
1. 支持 [cron](https://github.com/jakecoffman/cron) 定时任务,在后台可界面配置
1. 支持 [websocket](https://github.com/gorilla/websocket) 实时通讯,在后台有界面演示
1. 支持 web 界面,使用的 [Light Year Admin 模板](https://gitee.com/yinqi/Light-Year-Admin-Using-Iframe)
## 文档索引(可加入交流群)
## 文档索引
- 中文文档:[go-gin-api - 语雀](https://www.yuque.com/xinliangnote/go-gin-api/ngc3x5)
- English Document[en.md](https://github.com/xinliangnote/go-gin-api/blob/master/en.md)
go-gin-api 文档由以下几个主要部分组成:
## 轻量版
- 准备工作
- 快速开始
- 目录接口
- 核心封装
- 组件指南
- 工具包
为了满足开发者对于简单、轻量级 API 框架的需求,开发了 gin-api-mono,旨在提供更便捷的业务开发体验。
**地址:[https://www.yuque.com/xinliangnote/go-gin-api/ngc3x5](https://www.yuque.com/xinliangnote/go-gin-api/ngc3x5)**
相比于 go-gin-api,首先 gin-api-mono 去掉了一些集成的功能和界面,使得整个框架更加简洁、轻量。其次 gin-api-mono 对框架代码进行了升级,以确保其在性能和稳定性方面的优势。这样,开发者就可以更灵活地选择所需的功能,并获得更好的性能和稳定性。
详见链接:https://xiaobot.net/post/e9f7ef4c-81b1-4ffc-9053-bec55c3abb12
## 其他
查看 Jaeger 链路追踪代码,请查看 [v1.0版](https://github.com/xinliangnote/go-gin-api/releases/tag/v1.0),文档点这里 [jaeger.md](https://github.com/xinliangnote/go-gin-api/blob/master/docs/jaeger.md) 。
查看 Jaeger 链路追踪 Demo 代码,请查看 [v1.0 ](https://github.com/xinliangnote/go-gin-api/releases/tag/v1.0) ,链接地址:http://127.0.0.1:9999/jaeger_test
## Special Thanks
调用的其他服务端 Demo 代码为 [https://github.com/xinliangnote/go-jaeger-demo](https://github.com/xinliangnote/go-jaeger-demo)
[@koketama](https://github.com/koketama)
## 联系作者
## Learning together
![](https://github.com/xinliangnote/Go/blob/master/00-基础语法/images/qr.jpg)
![联系作者](https://i.loli.net/2021/07/02/cwiLQ13CRgJIS86.jpg)
+11
View File
@@ -0,0 +1,11 @@
package assets
import "embed"
var (
//go:embed bootstrap
Bootstrap embed.FS
//go:embed templates
Templates embed.FS
)
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+4303
View File
File diff suppressed because it is too large Load Diff
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

File diff suppressed because one or more lines are too long
+1
View File
@@ -0,0 +1 @@
!function(r,e){"object"==typeof exports?module.exports=exports=e(require("./core")):"function"==typeof define&&define.amd?define(["./core"],e):e(r.CryptoJS)}(this,function(r){var s;return s=r.lib.WordArray,r.enc.Base64={stringify:function(r){var e=r.words,t=r.sigBytes,a=this._map;r.clamp();for(var n=[],o=0;o<t;o+=3)for(var i=(e[o>>>2]>>>24-o%4*8&255)<<16|(e[o+1>>>2]>>>24-(o+1)%4*8&255)<<8|e[o+2>>>2]>>>24-(o+2)%4*8&255,f=0;f<4&&o+.75*f<t;f++)n.push(a.charAt(i>>>6*(3-f)&63));var c=a.charAt(64);if(c)for(;n.length%4;)n.push(c);return n.join("")},parse:function(r){var e=r.length,t=this._map,a=this._reverseMap;if(!a){a=this._reverseMap=[];for(var n=0;n<t.length;n++)a[t.charCodeAt(n)]=n}var o=t.charAt(64);if(o){var i=r.indexOf(o);-1!==i&&(e=i)}return function(r,e,t){for(var a=[],n=0,o=0;o<e;o++)if(o%4){var i=t[r.charCodeAt(o-1)]<<o%4*2,f=t[r.charCodeAt(o)]>>>6-o%4*2,c=i|f;a[n>>>2]|=c<<24-n%4*8,n++}return s.create(a,n)}(r,e,a)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="},r.enc.Base64});
@@ -0,0 +1,18 @@
;(function (root, factory, undef) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"), require("./sha256"), require("./hmac"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core", "./sha256", "./hmac"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
return CryptoJS.HmacSHA256;
}));
@@ -0,0 +1,78 @@
// original:https://locutus.io/php/array/ksort/
function ksort(inputArr, sort_flags) {
var tmp_arr = {},
keys = [],
sorter, i, k, that = this,
strictForIn = false,
populateArr = {};
switch (sort_flags) {
case 'SORT_STRING':
// compare items as strings
sorter = function (a, b) {
return that.strnatcmp(a, b);
};
break;
case 'SORT_LOCALE_STRING':
// compare items as strings, original by the current locale (set with i18n_loc_set_default() as of PHP6)
var loc = this.i18n_loc_get_default();
sorter = this.php_js.i18nLocales[loc].sorting;
break;
case 'SORT_NUMERIC':
// compare items numerically
sorter = function (a, b) {
return ((a + 0) - (b + 0));
};
break;
// case 'SORT_REGULAR': // compare items normally (don't change types)
default:
sorter = function (a, b) {
var aFloat = parseFloat(a),
bFloat = parseFloat(b),
aNumeric = aFloat + '' === a,
bNumeric = bFloat + '' === b;
if (aNumeric && bNumeric) {
return aFloat > bFloat ? 1 : aFloat < bFloat ? -1 : 0;
} else if (aNumeric && !bNumeric) {
return 1;
} else if (!aNumeric && bNumeric) {
return -1;
}
return a > b ? 1 : a < b ? -1 : 0;
};
break;
}
// Make a list of key names
for (k in inputArr) {
if (inputArr.hasOwnProperty(k)) {
keys.push(k);
}
}
keys.sort(sorter);
// BEGIN REDUNDANT
this.php_js = this.php_js || {};
this.php_js.ini = this.php_js.ini || {};
// END REDUNDANT
strictForIn = this.php_js.ini['phpjs.strictForIn'] && this.php_js.ini['phpjs.strictForIn'].local_value && this.php_js
.ini['phpjs.strictForIn'].local_value !== 'off';
populateArr = strictForIn ? inputArr : populateArr;
// Rebuild array with sorted key names
for (i = 0; i < keys.length; i++) {
k = keys[i];
tmp_arr[k] = inputArr[k];
if (strictForIn) {
delete inputArr[k];
}
}
for (i in tmp_arr) {
if (tmp_arr.hasOwnProperty(i)) {
populateArr[i] = tmp_arr[i];
}
}
return strictForIn || populateArr;
}
+2
View File
@@ -0,0 +1,2 @@
!function(n){"use strict";function d(n,t){var r=(65535&n)+(65535&t);return(n>>16)+(t>>16)+(r>>16)<<16|65535&r}function f(n,t,r,e,o,u){return d((c=d(d(t,n),d(e,u)))<<(f=o)|c>>>32-f,r);var c,f}function l(n,t,r,e,o,u,c){return f(t&r|~t&e,n,t,o,u,c)}function v(n,t,r,e,o,u,c){return f(t&e|r&~e,n,t,o,u,c)}function g(n,t,r,e,o,u,c){return f(t^r^e,n,t,o,u,c)}function m(n,t,r,e,o,u,c){return f(r^(t|~e),n,t,o,u,c)}function i(n,t){var r,e,o,u;n[t>>5]|=128<<t%32,n[14+(t+64>>>9<<4)]=t;for(var c=1732584193,f=-271733879,i=-1732584194,a=271733878,h=0;h<n.length;h+=16)c=l(r=c,e=f,o=i,u=a,n[h],7,-680876936),a=l(a,c,f,i,n[h+1],12,-389564586),i=l(i,a,c,f,n[h+2],17,606105819),f=l(f,i,a,c,n[h+3],22,-1044525330),c=l(c,f,i,a,n[h+4],7,-176418897),a=l(a,c,f,i,n[h+5],12,1200080426),i=l(i,a,c,f,n[h+6],17,-1473231341),f=l(f,i,a,c,n[h+7],22,-45705983),c=l(c,f,i,a,n[h+8],7,1770035416),a=l(a,c,f,i,n[h+9],12,-1958414417),i=l(i,a,c,f,n[h+10],17,-42063),f=l(f,i,a,c,n[h+11],22,-1990404162),c=l(c,f,i,a,n[h+12],7,1804603682),a=l(a,c,f,i,n[h+13],12,-40341101),i=l(i,a,c,f,n[h+14],17,-1502002290),c=v(c,f=l(f,i,a,c,n[h+15],22,1236535329),i,a,n[h+1],5,-165796510),a=v(a,c,f,i,n[h+6],9,-1069501632),i=v(i,a,c,f,n[h+11],14,643717713),f=v(f,i,a,c,n[h],20,-373897302),c=v(c,f,i,a,n[h+5],5,-701558691),a=v(a,c,f,i,n[h+10],9,38016083),i=v(i,a,c,f,n[h+15],14,-660478335),f=v(f,i,a,c,n[h+4],20,-405537848),c=v(c,f,i,a,n[h+9],5,568446438),a=v(a,c,f,i,n[h+14],9,-1019803690),i=v(i,a,c,f,n[h+3],14,-187363961),f=v(f,i,a,c,n[h+8],20,1163531501),c=v(c,f,i,a,n[h+13],5,-1444681467),a=v(a,c,f,i,n[h+2],9,-51403784),i=v(i,a,c,f,n[h+7],14,1735328473),c=g(c,f=v(f,i,a,c,n[h+12],20,-1926607734),i,a,n[h+5],4,-378558),a=g(a,c,f,i,n[h+8],11,-2022574463),i=g(i,a,c,f,n[h+11],16,1839030562),f=g(f,i,a,c,n[h+14],23,-35309556),c=g(c,f,i,a,n[h+1],4,-1530992060),a=g(a,c,f,i,n[h+4],11,1272893353),i=g(i,a,c,f,n[h+7],16,-155497632),f=g(f,i,a,c,n[h+10],23,-1094730640),c=g(c,f,i,a,n[h+13],4,681279174),a=g(a,c,f,i,n[h],11,-358537222),i=g(i,a,c,f,n[h+3],16,-722521979),f=g(f,i,a,c,n[h+6],23,76029189),c=g(c,f,i,a,n[h+9],4,-640364487),a=g(a,c,f,i,n[h+12],11,-421815835),i=g(i,a,c,f,n[h+15],16,530742520),c=m(c,f=g(f,i,a,c,n[h+2],23,-995338651),i,a,n[h],6,-198630844),a=m(a,c,f,i,n[h+7],10,1126891415),i=m(i,a,c,f,n[h+14],15,-1416354905),f=m(f,i,a,c,n[h+5],21,-57434055),c=m(c,f,i,a,n[h+12],6,1700485571),a=m(a,c,f,i,n[h+3],10,-1894986606),i=m(i,a,c,f,n[h+10],15,-1051523),f=m(f,i,a,c,n[h+1],21,-2054922799),c=m(c,f,i,a,n[h+8],6,1873313359),a=m(a,c,f,i,n[h+15],10,-30611744),i=m(i,a,c,f,n[h+6],15,-1560198380),f=m(f,i,a,c,n[h+13],21,1309151649),c=m(c,f,i,a,n[h+4],6,-145523070),a=m(a,c,f,i,n[h+11],10,-1120210379),i=m(i,a,c,f,n[h+2],15,718787259),f=m(f,i,a,c,n[h+9],21,-343485551),c=d(c,r),f=d(f,e),i=d(i,o),a=d(a,u);return[c,f,i,a]}function a(n){for(var t="",r=32*n.length,e=0;e<r;e+=8)t+=String.fromCharCode(n[e>>5]>>>e%32&255);return t}function h(n){var t=[];for(t[(n.length>>2)-1]=void 0,e=0;e<t.length;e+=1)t[e]=0;for(var r=8*n.length,e=0;e<r;e+=8)t[e>>5]|=(255&n.charCodeAt(e/8))<<e%32;return t}function e(n){for(var t,r="0123456789abcdef",e="",o=0;o<n.length;o+=1)t=n.charCodeAt(o),e+=r.charAt(t>>>4&15)+r.charAt(15&t);return e}function r(n){return unescape(encodeURIComponent(n))}function o(n){return a(i(h(t=r(n)),8*t.length));var t}function u(n,t){return function(n,t){var r,e,o=h(n),u=[],c=[];for(u[15]=c[15]=void 0,16<o.length&&(o=i(o,8*n.length)),r=0;r<16;r+=1)u[r]=909522486^o[r],c[r]=1549556828^o[r];return e=i(u.concat(h(t)),512+8*t.length),a(i(c.concat(e),640))}(r(n),r(t))}function t(n,t,r){return t?r?u(t,n):e(u(t,n)):r?o(n):e(o(n))}"function"==typeof define&&define.amd?define(function(){return t}):"object"==typeof module&&module.exports?module.exports=t:n.md5=t}(this);
//# sourceMappingURL=md5.min.js.map
@@ -0,0 +1,589 @@
/* ==========================================================
* bootstrap-maxlength.js v1.9.0
*
* Copyright (c) 2013-2020 Maurizio Napoleoni;
*
* Licensed under the terms of the MIT license.
* See: https://github.com/mimo84/bootstrap-maxlength/blob/master/LICENSE
* ========================================================== */
/*global jQuery*/
(function ($) {
'use strict';
/**
* We need an event when the elements are destroyed
* because if an input is removed, we have to remove the
* maxlength object associated (if any).
* From:
* http://stackoverflow.com/questions/2200494/jquery-trigger-event-when-an-element-is-removed-from-the-dom
*/
if (!$.event.special.destroyed) {
$.event.special.destroyed = {
remove: function (o) {
if (o.handler) {
o.handler();
}
}
};
}
$.fn.extend({
maxlength: function (options, callback) {
var documentBody = $('body'),
defaults = {
showOnReady: false, // true to always show when indicator is ready
alwaysShow: true, // if true the indicator it's always shown.
threshold: 0, // Represents how many chars left are needed to show up the counter
warningClass: 'small form-text text-muted',
limitReachedClass: 'small form-text text-danger',
separator: ' / ',
preText: '',
postText: '',
showMaxLength: true,
placement: 'bottom-right-inside',
message: null, // an alternative way to provide the message text
showCharsTyped: true, // show the number of characters typed and not the number of characters remaining
validate: false, // if the browser doesn't support the maxlength attribute, attempt to type more than the indicated chars, will be prevented.
utf8: false, // counts using bytesize rather than length. eg: '£' is counted as 2 characters.
appendToParent: false, // append the indicator to the input field's parent instead of body
twoCharLinebreak: true, // count linebreak as 2 characters to match IE/Chrome textarea validation. As well as DB storage.
customMaxAttribute: null, // null = use maxlength attribute and browser functionality, string = use specified attribute instead.
allowOverMax: false, // Form submit validation is handled on your own. when maxlength has been exceeded 'overmax' class added to element
zIndex: 1099
};
if ($.isFunction(options) && !callback) {
callback = options;
options = {};
}
options = $.extend(defaults, options);
/**
* Return the byte count of the specified character in UTF8 encoding.
* Note: This won't cover UTF-8 characters that are 4 bytes long.
*
* @param input
* @return {number}
*/
function utf8CharByteCount(character) {
var c = character.charCodeAt();
// Not c then 0, else c < 128 then 1, else c < 2048 then 2, else 3
return !c ? 0 : c < 128 ? 1 : c < 2048 ? 2 : 3;
}
/**
* Return the length of the specified input in UTF8 encoding.
*
* @param input
* @return {number}
*/
function utf8Length(string) {
return string.split("")
.map(utf8CharByteCount)
// Prevent reduce from throwing an error if the string is empty.
.concat(0)
.reduce(function (sum, val) {
return sum + val;
});
}
/**
* Return the length of the specified input.
*
* @param input
* @return {number}
*/
function inputLength(input) {
var text = input.val();
if (options.twoCharLinebreak) {
// Count all line breaks as 2 characters
text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n');
} else {
// Remove all double-character (\r\n) linebreaks, so they're counted only once.
text = text.replace(/(?:\r\n|\r|\n)/g, '\n');
}
var currentLength = 0;
if (options.utf8) {
currentLength = utf8Length(text);
} else {
currentLength = text.length;
}
// Remove "C:\fakepath\" from counter when using file input
// Fix https://github.com/mimo84/bootstrap-maxlength/issues/146
if (input.prop("type") === "file" && input.val() !== "") {
currentLength -= 12;
}
return currentLength;
}
/**
* Truncate the text of the specified input.
*
* @param input
* @param limit
*/
function truncateChars(input, maxlength) {
var text = input.val();
if (options.twoCharLinebreak) {
text = text.replace(/\r(?!\n)|\n(?!\r)/g, '\r\n');
if (text[text.length - 1] === '\n') {
maxlength -= text.length % 2;
}
}
if (options.utf8) {
var indexedSize = text.split("").map(utf8CharByteCount);
for (
var removedBytes = 0,
bytesPastMax = utf8Length(text) - maxlength; removedBytes < bytesPastMax; removedBytes += indexedSize.pop()
);
maxlength -= (maxlength - indexedSize.length);
}
input.val(text.substr(0, maxlength));
}
/**
* Return true if the indicator should be showing up.
*
* @param input
* @param threshold
* @param maxlength
* @return {number}
*/
function charsLeftThreshold(input, threshold, maxlength) {
var output = true;
if (!options.alwaysShow && (maxlength - inputLength(input) > threshold)) {
output = false;
}
return output;
}
/**
* Returns how many chars are left to complete the fill up of the form.
*
* @param input
* @param maxlength
* @return {number}
*/
function remainingChars(input, maxlength) {
var length = maxlength - inputLength(input);
return length;
}
/**
* When called displays the indicator.
*
* @param indicator
*/
function showRemaining(currentInput, indicator) {
indicator.css({
display: 'block'
});
currentInput.trigger('maxlength.shown');
}
/**
* When called shows the indicator.
*
* @param indicator
*/
function hideRemaining(currentInput, indicator) {
if (options.alwaysShow) {
return;
}
indicator.css({
display: 'none'
});
currentInput.trigger('maxlength.hidden');
}
/**
* This function updates the value in the indicator
*
* @param maxLengthThisInput
* @param typedChars
* @return String
*/
function updateMaxLengthHTML(currentInputText, maxLengthThisInput, typedChars) {
var output = '';
if (options.message) {
if (typeof options.message === 'function') {
output = options.message(currentInputText, maxLengthThisInput);
} else {
output = options.message.replace('%charsTyped%', typedChars)
.replace('%charsRemaining%', maxLengthThisInput - typedChars)
.replace('%charsTotal%', maxLengthThisInput);
}
} else {
if (options.preText) {
output += options.preText;
}
if (!options.showCharsTyped) {
output += maxLengthThisInput - typedChars;
} else {
output += typedChars;
}
if (options.showMaxLength) {
output += options.separator + maxLengthThisInput;
}
if (options.postText) {
output += options.postText;
}
}
return output;
}
/**
* This function updates the value of the counter in the indicator.
* Wants as parameters: the number of remaining chars, the element currently managed,
* the maxLength for the current input and the indicator generated for it.
*
* @param remaining
* @param currentInput
* @param maxLengthCurrentInput
* @param maxLengthIndicator
*/
function manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator) {
if (maxLengthIndicator) {
maxLengthIndicator.html(updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, (maxLengthCurrentInput - remaining)));
if (remaining > 0) {
if (charsLeftThreshold(currentInput, options.threshold, maxLengthCurrentInput)) {
showRemaining(currentInput, maxLengthIndicator.removeClass(options.limitReachedClass).addClass(options.warningClass));
} else {
hideRemaining(currentInput, maxLengthIndicator);
}
} else {
showRemaining(currentInput, maxLengthIndicator.removeClass(options.warningClass).addClass(options.limitReachedClass));
}
}
if (options.customMaxAttribute) {
// class to use for form validation on custom maxlength attribute
if (remaining < 0) {
currentInput.addClass('overmax');
} else {
currentInput.removeClass('overmax');
}
}
}
/**
* This function returns an object containing all the
* informations about the position of the current input
*
* @param currentInput
* @return object {bottom height left right top width}
*
*/
function getPosition(currentInput) {
var el = currentInput[0];
return $.extend({}, (typeof el.getBoundingClientRect === 'function') ? el.getBoundingClientRect() : {
width: el.offsetWidth,
height: el.offsetHeight
}, currentInput.offset());
}
/**
* This function places the maxLengthIndicator based on placement config object.
*
* @param {object} placement
* @param {$} maxLengthIndicator
* @return null
*
*/
function placeWithCSS(placement, maxLengthIndicator) {
if (!placement || !maxLengthIndicator) {
return;
}
var POSITION_KEYS = [
'top',
'bottom',
'left',
'right',
'position'
];
var cssPos = {};
// filter css properties to position
$.each(POSITION_KEYS, function (i, key) {
var val = options.placement[key];
if (typeof val !== 'undefined') {
cssPos[key] = val;
}
});
maxLengthIndicator.css(cssPos);
return;
}
/**
* This function places the maxLengthIndicator at the
* top / bottom / left / right of the currentInput
*
* @param currentInput
* @param maxLengthIndicator
* @return null
*
*/
function place(currentInput, maxLengthIndicator) {
var pos = getPosition(currentInput);
// Supports custom placement handler
if ($.type(options.placement) === 'function') {
options.placement(currentInput, maxLengthIndicator, pos);
return;
}
// Supports custom placement via css positional properties
if ($.isPlainObject(options.placement)) {
placeWithCSS(options.placement, maxLengthIndicator);
return;
}
var inputOuter = currentInput.outerWidth(),
outerWidth = maxLengthIndicator.outerWidth(),
actualWidth = maxLengthIndicator.width(),
actualHeight = maxLengthIndicator.height();
// get the right position if the indicator is appended to the input's parent
if (options.appendToParent) {
pos.top -= currentInput.parent().offset().top;
pos.left -= currentInput.parent().offset().left;
}
switch (options.placement) {
case 'bottom':
maxLengthIndicator.css({
top: pos.top + pos.height,
left: pos.left + pos.width / 2 - actualWidth / 2
});
break;
case 'top':
maxLengthIndicator.css({
top: pos.top - actualHeight,
left: pos.left + pos.width / 2 - actualWidth / 2
});
break;
case 'left':
maxLengthIndicator.css({
top: pos.top + pos.height / 2 - actualHeight / 2,
left: pos.left - actualWidth
});
break;
case 'right':
maxLengthIndicator.css({
top: pos.top + pos.height / 2 - actualHeight / 2,
left: pos.left + pos.width
});
break;
case 'bottom-right':
maxLengthIndicator.css({
top: pos.top + pos.height,
left: pos.left + pos.width
});
break;
case 'top-right':
maxLengthIndicator.css({
top: pos.top - actualHeight,
left: pos.left + inputOuter
});
break;
case 'top-left':
maxLengthIndicator.css({
top: pos.top - actualHeight,
left: pos.left - outerWidth
});
break;
case 'bottom-left':
maxLengthIndicator.css({
top: pos.top + currentInput.outerHeight(),
left: pos.left - outerWidth
});
break;
case 'centered-right':
maxLengthIndicator.css({
top: pos.top + (actualHeight / 2),
left: pos.left + inputOuter - outerWidth - 3
});
break;
// Some more options for placements
case 'bottom-right-inside':
maxLengthIndicator.css({
top: pos.top + pos.height,
left: pos.left + pos.width - outerWidth
});
break;
case 'top-right-inside':
maxLengthIndicator.css({
top: pos.top - actualHeight,
left: pos.left + inputOuter - outerWidth
});
break;
case 'top-left-inside':
maxLengthIndicator.css({
top: pos.top - actualHeight,
left: pos.left
});
break;
case 'bottom-left-inside':
maxLengthIndicator.css({
top: pos.top + currentInput.outerHeight(),
left: pos.left
});
break;
}
}
/**
* This function returns true if the indicator position needs to
* be recalculated when the currentInput changes
*
* @return {boolean}
*
*/
function isPlacementMutable() {
return options.placement === 'bottom-right-inside' || options.placement === 'top-right-inside' || typeof options.placement === 'function' || (options.message && typeof options.message === 'function');
}
/**
* This function retrieves the maximum length of currentInput
*
* @param currentInput
* @return {number}
*
*/
function getMaxLength(currentInput) {
var max = currentInput.attr('maxlength') || options.customMaxAttribute;
if (options.customMaxAttribute && !options.allowOverMax) {
var custom = currentInput.attr(options.customMaxAttribute);
if (!max || custom < max) {
max = custom;
}
}
if (!max) {
max = currentInput.attr('size');
}
return max;
}
return this.each(function () {
var currentInput = $(this),
maxLengthCurrentInput,
maxLengthIndicator;
$(window).resize(function () {
if (maxLengthIndicator) {
place(currentInput, maxLengthIndicator);
}
});
function firstInit() {
var maxlengthContent = updateMaxLengthHTML(currentInput.val(), maxLengthCurrentInput, '0');
maxLengthCurrentInput = getMaxLength(currentInput);
if (!maxLengthIndicator) {
maxLengthIndicator = $('<span class="bootstrap-maxlength"></span>').css({
display: 'none',
position: 'absolute',
whiteSpace: 'nowrap',
zIndex: options.zIndex
}).html(maxlengthContent);
}
// We need to detect resizes if we are dealing with a textarea:
if (currentInput.is('textarea')) {
currentInput.data('maxlenghtsizex', currentInput.outerWidth());
currentInput.data('maxlenghtsizey', currentInput.outerHeight());
currentInput.mouseup(function () {
if (currentInput.outerWidth() !== currentInput.data('maxlenghtsizex') || currentInput.outerHeight() !== currentInput.data('maxlenghtsizey')) {
place(currentInput, maxLengthIndicator);
}
currentInput.data('maxlenghtsizex', currentInput.outerWidth());
currentInput.data('maxlenghtsizey', currentInput.outerHeight());
});
}
if (options.appendToParent) {
currentInput.parent().append(maxLengthIndicator);
currentInput.parent().css('position', 'relative');
} else {
documentBody.append(maxLengthIndicator);
}
var remaining = remainingChars(currentInput, getMaxLength(currentInput));
manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator);
place(currentInput, maxLengthIndicator);
}
if (options.showOnReady) {
currentInput.ready(function () {
firstInit();
});
} else {
currentInput.focus(function () {
firstInit();
});
}
currentInput.on('maxlength.reposition', function () {
place(currentInput, maxLengthIndicator);
});
currentInput.on('destroyed', function () {
if (maxLengthIndicator) {
maxLengthIndicator.remove();
}
});
currentInput.on('blur', function () {
if (maxLengthIndicator && !options.showOnReady) {
maxLengthIndicator.remove();
}
});
currentInput.on('input', function () {
var maxlength = getMaxLength(currentInput),
remaining = remainingChars(currentInput, maxlength),
output = true;
if (options.validate && remaining < 0) {
truncateChars(currentInput, maxlength);
output = false;
} else {
manageRemainingVisibility(remaining, currentInput, maxLengthCurrentInput, maxLengthIndicator);
}
if (isPlacementMutable()) {
place(currentInput, maxLengthIndicator);
}
return output;
});
});
}
});
}(jQuery));
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,114 @@
.mt-wrapper{
position: relative;
z-index: 1;
}
.mt-nav-bar {
width : 100%;
z-index: 200;
position: absolute;
display: flex;
}
.mt-nav-bar .mt-nav{
background-color: #fff;
}
.mt-nav-panel{
overflow: hidden;
}
.mt-nav-panel ul{
width: 10000px;
}
.mt-nav-panel ul li {
position: relative;
}
.mt-tab-content{
height: 100%;
}
.mt-close-tab {
position: absolute;
font-size: 10px;
width: 16px;
height: 16px;
top: 18px;
right: 10px;
color: #c2c2c2;
cursor: pointer;
display: none;
line-height: 16px;
text-align: center;
vertical-align: 2px;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
border-radius: 50%;
-webkit-transition: all .3s cubic-bezier(.645,.045,.355,1);
transition: all .3s cubic-bezier(.645,.045,.355,1);
-webkit-transform-origin: 100% 50%;
transform-origin: 100% 50%;
}
.mt-close-tab:before {
-webkit-transform: scale(.8);
transform: scale(.8);
display: inline-block;
/*vertical-align: -1px;*/
}
li:hover .mt-close-tab {
display: inline;
}
.mt-hidden-list .mt-close-tab {
display: none !important;
}
.mt-nav-bar a {
cursor: pointer !important;
max-height: 48px;
padding-top: 14px;
padding-bottom: 13px;
}
@media (max-width: 767px){
.mt-tab-content{
/*padding-top: 0 !important;*/
}
}
.mt-tab-content{
-webkit-overflow-scrolling:touch;
overflow:auto;
}
.mt-dragging-tab{
left: auto;
position: absolute !important;
z-index: 9999 !important;
}
.mt-dragging-tab > a{
background: #FBFDFD !important;
}
/*新增*/
.mt-nav-bar .mt-nav .nav-tabs {
margin-bottom: 0px;
border-color: #eceeef;
}
.mt-close-tab:hover {
color: #f96868;
}
.mt-dropdown .caret {
position: absolute;
top: 22px;
}
.mt-dropdown .dropdown-menu {
margin-top: 0px;
}
#contextify-menu {
min-width: 80px!important;
}
.mt-close-tab:hover {
background-color: #f96868;
color: #fff;
}
.mt-nav .nav-tabs a:not([data-type="main"]) {
padding-right: 40px;
}
.mt-nav-tools-left li a,
.mt-nav-tools-right li a {
padding-right: 15px!important;
}
.mt-nav-bar .mt-nav .nav-tabs .mt-dragging {
margin-bottom: -1px;
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,32 @@
document.write('<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-notify/bootstrap-notify.min.js"></script>');
function SuccessNotify(content) {
$.notify({
icon: "mdi mdi-alert",
title: "",
message: content,
url: "",
target: ""
}, {
type: "success",
allow_dismiss: true,
newest_on_top: false,
placement: {
from: "top",
align: "right",
},
offset: {
x: "20",
y: "20"
},
spacing: "10",
z_index: "1031",
delay: "3000",
animate: {
enter: "animated fadeInDown",
exit: "animated fadeOutUp"
},
onClosed: null,
mouse_over: null
});
}
@@ -0,0 +1,453 @@
/*!
* Bootstrap-select v1.13.17 (https://developer.snapappointments.com/bootstrap-select)
*
* Copyright 2012-2020 SnapAppointments, LLC
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
*/
@-webkit-keyframes bs-notify-fadeOut {
0% {
opacity: 0.9;
}
100% {
opacity: 0;
}
}
@-o-keyframes bs-notify-fadeOut {
0% {
opacity: 0.9;
}
100% {
opacity: 0;
}
}
@keyframes bs-notify-fadeOut {
0% {
opacity: 0.9;
}
100% {
opacity: 0;
}
}
select.bs-select-hidden,
.bootstrap-select > select.bs-select-hidden,
select.selectpicker {
display: none !important;
}
.bootstrap-select {
width: 220px \0;
/*IE9 and below*/
vertical-align: middle;
}
.bootstrap-select > .dropdown-toggle {
position: relative;
width: 100%;
text-align: right;
white-space: nowrap;
display: -webkit-inline-box;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-box-align: center;
-webkit-align-items: center;
-ms-flex-align: center;
align-items: center;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
}
.bootstrap-select > .dropdown-toggle:after {
margin-top: -1px;
}
.bootstrap-select > .dropdown-toggle.bs-placeholder,
.bootstrap-select > .dropdown-toggle.bs-placeholder:hover,
.bootstrap-select > .dropdown-toggle.bs-placeholder:focus,
.bootstrap-select > .dropdown-toggle.bs-placeholder:active {
color: #999;
}
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:hover,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:hover,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:hover,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:hover,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:hover,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:hover,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:focus,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:focus,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:focus,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:focus,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:focus,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:focus,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-primary:active,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-secondary:active,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-success:active,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-danger:active,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-info:active,
.bootstrap-select > .dropdown-toggle.bs-placeholder.btn-dark:active {
color: rgba(255, 255, 255, 0.5);
}
.bootstrap-select > select {
position: absolute !important;
bottom: 0;
left: 50%;
display: block !important;
width: 0.5px !important;
height: 100% !important;
padding: 0 !important;
opacity: 0 !important;
border: none;
z-index: 0 !important;
}
.bootstrap-select > select.mobile-device {
top: 0;
left: 0;
display: block !important;
width: 100% !important;
z-index: 2 !important;
}
.has-error .bootstrap-select .dropdown-toggle,
.error .bootstrap-select .dropdown-toggle,
.bootstrap-select.is-invalid .dropdown-toggle,
.was-validated .bootstrap-select select:invalid + .dropdown-toggle {
border-color: #b94a48;
}
.bootstrap-select.is-valid .dropdown-toggle,
.was-validated .bootstrap-select select:valid + .dropdown-toggle {
border-color: #28a745;
}
.bootstrap-select.fit-width {
width: auto !important;
}
.bootstrap-select:not([class*="col-"]):not([class*="form-control"]):not(.input-group-btn) {
width: 220px;
}
.bootstrap-select.form-control {
margin-bottom: 0;
padding: 0;
border: none;
height: auto;
}
:not(.input-group) > .bootstrap-select.form-control:not([class*="col-"]) {
width: 100%;
}
.bootstrap-select.form-control.input-group-btn {
float: none;
z-index: auto;
}
.form-inline .bootstrap-select,
.form-inline .bootstrap-select.form-control:not([class*="col-"]) {
width: auto;
}
.bootstrap-select:not(.input-group-btn),
.bootstrap-select[class*="col-"] {
float: none;
display: inline-block;
margin-left: 0;
}
.bootstrap-select.dropdown-menu-right,
.bootstrap-select[class*="col-"].dropdown-menu-right,
.row .bootstrap-select[class*="col-"].dropdown-menu-right {
float: right;
}
.form-inline .bootstrap-select,
.form-horizontal .bootstrap-select,
.form-group .bootstrap-select {
margin-bottom: 0;
}
.form-group-lg .bootstrap-select.form-control,
.form-group-sm .bootstrap-select.form-control {
padding: 0;
}
.form-group-lg .bootstrap-select.form-control .dropdown-toggle,
.form-group-sm .bootstrap-select.form-control .dropdown-toggle {
height: 100%;
font-size: inherit;
line-height: inherit;
border-radius: inherit;
}
.bootstrap-select.form-control-sm .dropdown-toggle,
.bootstrap-select.form-control-lg .dropdown-toggle {
font-size: inherit;
line-height: inherit;
border-radius: inherit;
}
.bootstrap-select.form-control-sm .dropdown-toggle {
padding: 0.25rem 0.5rem;
}
.bootstrap-select.form-control-lg .dropdown-toggle {
padding: 0.5rem 1rem;
}
.form-inline .bootstrap-select .form-control {
width: 100%;
}
.bootstrap-select.disabled,
.bootstrap-select > .disabled {
cursor: not-allowed;
}
.bootstrap-select.disabled:focus,
.bootstrap-select > .disabled:focus {
outline: none !important;
}
.bootstrap-select.bs-container {
position: absolute;
top: 0;
left: 0;
height: 0 !important;
padding: 0 !important;
}
.bootstrap-select.bs-container .dropdown-menu {
z-index: 1060;
}
.bootstrap-select .dropdown-toggle .filter-option {
position: static;
top: 0;
left: 0;
float: left;
height: 100%;
width: 100%;
text-align: left;
overflow: hidden;
-webkit-box-flex: 0;
-webkit-flex: 0 1 auto;
-ms-flex: 0 1 auto;
flex: 0 1 auto;
}
.bs3.bootstrap-select .dropdown-toggle .filter-option {
padding-right: inherit;
}
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option {
position: absolute;
padding-top: inherit;
padding-bottom: inherit;
padding-left: inherit;
float: none;
}
.input-group .bs3-has-addon.bootstrap-select .dropdown-toggle .filter-option .filter-option-inner {
padding-right: inherit;
}
.bootstrap-select .dropdown-toggle .filter-option-inner-inner {
overflow: hidden;
}
.bootstrap-select .dropdown-toggle .filter-expand {
width: 0 !important;
float: left;
opacity: 0 !important;
overflow: hidden;
}
.bootstrap-select .dropdown-toggle .caret {
position: absolute;
top: 50%;
right: 12px;
margin-top: -2px;
vertical-align: middle;
}
.input-group .bootstrap-select.form-control .dropdown-toggle {
border-radius: inherit;
}
.bootstrap-select[class*="col-"] .dropdown-toggle {
width: 100%;
}
.bootstrap-select .dropdown-menu {
min-width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bootstrap-select .dropdown-menu > .inner:focus {
outline: none !important;
}
.bootstrap-select .dropdown-menu.inner {
position: static;
float: none;
border: 0;
padding: 0;
margin: 0;
border-radius: 0;
-webkit-box-shadow: none;
box-shadow: none;
}
.bootstrap-select .dropdown-menu li {
position: relative;
}
.bootstrap-select .dropdown-menu li.active small {
color: rgba(255, 255, 255, 0.5) !important;
}
.bootstrap-select .dropdown-menu li.disabled a {
cursor: not-allowed;
}
.bootstrap-select .dropdown-menu li a {
cursor: pointer;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
}
.bootstrap-select .dropdown-menu li a.opt {
position: relative;
padding-left: 2.25em;
}
.bootstrap-select .dropdown-menu li a span.check-mark {
display: none;
}
.bootstrap-select .dropdown-menu li a span.text {
display: inline-block;
}
.bootstrap-select .dropdown-menu li small {
padding-left: 0.5em;
}
.bootstrap-select .dropdown-menu .notify {
position: absolute;
bottom: 5px;
width: 96%;
margin: 0 2%;
min-height: 26px;
padding: 3px 5px;
background: #f5f5f5;
border: 1px solid #f2f3f3;
pointer-events: none;
opacity: 0.9;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bootstrap-select .dropdown-menu .notify.fadeOut {
-webkit-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
-o-animation: 300ms linear 750ms forwards bs-notify-fadeOut;
animation: 300ms linear 750ms forwards bs-notify-fadeOut;
}
.bootstrap-select .no-results {
padding: 3px;
background: #f5f5f5;
margin: 0 5px;
white-space: nowrap;
}
.bootstrap-select.fit-width .dropdown-toggle .filter-option {
position: static;
display: inline;
padding: 0;
}
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner,
.bootstrap-select.fit-width .dropdown-toggle .filter-option-inner-inner {
display: inline;
}
.bootstrap-select.fit-width .dropdown-toggle .bs-caret:before {
content: '\00a0';
}
.bootstrap-select.fit-width .dropdown-toggle .caret {
position: static;
top: auto;
margin-top: -1px;
}
.bootstrap-select.show-tick .dropdown-menu .selected span.check-mark {
position: absolute;
display: inline-block;
right: 15px;
top: 10px;
}
.bootstrap-select.show-tick .dropdown-menu li a span.text {
margin-right: 34px;
}
.bootstrap-select .bs-ok-default:after {
content: '';
display: block;
width: 0.5em;
height: 1em;
border-style: solid;
border-width: 0 0.13em 0.13em 0;
border-color: #4d5259;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: rotate(45deg);
-ms-transform: rotate(45deg);
-o-transform: rotate(45deg);
transform: rotate(45deg);
}
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle,
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle {
z-index: 1061;
}
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:before {
content: '';
border-left: 7px solid transparent;
border-right: 7px solid transparent;
border-bottom: 7px solid rgba(204, 204, 204, 0.2);
position: absolute;
bottom: -4px;
left: 9px;
display: none;
}
.bootstrap-select.show-menu-arrow .dropdown-toggle .filter-option:after {
content: '';
border-left: 6px solid transparent;
border-right: 6px solid transparent;
border-bottom: 6px solid white;
position: absolute;
bottom: -4px;
left: 10px;
display: none;
}
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:before {
bottom: auto;
top: -4px;
border-top: 7px solid rgba(204, 204, 204, 0.2);
border-bottom: 0;
}
.bootstrap-select.show-menu-arrow.dropup .dropdown-toggle .filter-option:after {
bottom: auto;
top: -4px;
border-top: 6px solid white;
border-bottom: 0;
}
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:before {
right: 12px;
left: auto;
}
.bootstrap-select.show-menu-arrow.pull-right .dropdown-toggle .filter-option:after {
right: 13px;
left: auto;
}
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:before,
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:before,
.bootstrap-select.show-menu-arrow.open > .dropdown-toggle .filter-option:after,
.bootstrap-select.show-menu-arrow.show > .dropdown-toggle .filter-option:after {
display: block;
}
.bs-searchbox,
.bs-actionsbox,
.bs-donebutton {
padding: 4px 8px;
}
.bs-actionsbox {
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bs-actionsbox .btn-group button {
width: 50%;
}
.bs-donebutton {
float: left;
width: 100%;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
}
.bs-donebutton .btn-group button {
width: 100%;
}
.bs-searchbox + .bs-actionsbox {
padding: 0 8px 4px;
}
.bs-searchbox .form-control {
margin-bottom: 0;
width: 100%;
float: none;
}
/*# sourceMappingURL=bootstrap-select.css.map */
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,8 @@
/*!
* Bootstrap-select v1.13.17 (https://developer.snapappointments.com/bootstrap-select)
*
* Copyright 2012-2020 SnapAppointments, LLC
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
*/
!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"\u6ca1\u6709\u9009\u4e2d\u4efb\u4f55\u9879",noneResultsText:"\u6ca1\u6709\u627e\u5230\u5339\u914d\u9879",countSelectedText:"\u9009\u4e2d{1}\u4e2d\u7684{0}\u9879",maxOptionsText:["\u8d85\u51fa\u9650\u5236 (\u6700\u591a\u9009\u62e9{n}\u9879)","\u7ec4\u9009\u62e9\u8d85\u51fa\u9650\u5236(\u6700\u591a\u9009\u62e9{n}\u7ec4)"],multipleSeparator:", ",selectAllText:"\u5168\u9009",deselectAllText:"\u53d6\u6d88\u5168\u9009"}});
@@ -0,0 +1,8 @@
/*!
* Bootstrap-select v1.13.17 (https://developer.snapappointments.com/bootstrap-select)
*
* Copyright 2012-2020 SnapAppointments, LLC
* Licensed under MIT (https://github.com/snapappointments/bootstrap-select/blob/master/LICENSE)
*/
!function(e,t){void 0===e&&void 0!==window&&(e=window),"function"==typeof define&&define.amd?define(["jquery"],function(e){return t(e)}):"object"==typeof module&&module.exports?module.exports=t(require("jquery")):t(e.jQuery)}(this,function(e){e.fn.selectpicker.defaults={noneSelectedText:"\u6c92\u6709\u9078\u53d6\u4efb\u4f55\u9805\u76ee",noneResultsText:"\u6c92\u6709\u627e\u5230\u7b26\u5408\u7684\u7d50\u679c",countSelectedText:"\u5df2\u7d93\u9078\u53d6{0}\u500b\u9805\u76ee",maxOptionsText:["\u8d85\u904e\u9650\u5236 (\u6700\u591a\u9078\u64c7{n}\u9805)","\u8d85\u904e\u9650\u5236(\u6700\u591a\u9078\u64c7{n}\u7d44)"],selectAllText:"\u9078\u53d6\u5168\u90e8",deselectAllText:"\u5168\u90e8\u53d6\u6d88",multipleSeparator:", "}});
+361
View File
@@ -0,0 +1,361 @@
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
* version: 1.16.0
* https://github.com/wenzhixin/bootstrap-table/
*/
.bootstrap-table .fixed-table-toolbar::after {
content: "";
display: block;
clear: both;
}
.bootstrap-table .fixed-table-toolbar .bs-bars,
.bootstrap-table .fixed-table-toolbar .search,
.bootstrap-table .fixed-table-toolbar .columns {
position: relative;
margin-top: 10px;
margin-bottom: 10px;
}
.bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group {
display: inline-block;
margin-left: -1px !important;
}
.bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group > .btn {
border-radius: 0;
}
.bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group:first-child > .btn {
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
}
.bootstrap-table .fixed-table-toolbar .columns .btn-group > .btn-group:last-child > .btn {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
.bootstrap-table .fixed-table-toolbar .columns .dropdown-menu {
text-align: left;
max-height: 300px;
overflow: auto;
-ms-overflow-style: scrollbar;
z-index: 1001;
}
.bootstrap-table .fixed-table-toolbar .columns label {
display: block;
padding: 3px 20px;
clear: both;
font-weight: normal;
line-height: 1.428571429;
}
.bootstrap-table .fixed-table-toolbar .columns-left {
margin-right: 5px;
}
.bootstrap-table .fixed-table-toolbar .columns-right {
margin-left: 5px;
}
.bootstrap-table .fixed-table-toolbar .pull-right .dropdown-menu {
right: 0;
left: auto;
}
.bootstrap-table .fixed-table-container {
position: relative;
clear: both;
}
.bootstrap-table .fixed-table-container .table {
width: 100%;
margin-bottom: 0 !important;
}
.bootstrap-table .fixed-table-container .table th,
.bootstrap-table .fixed-table-container .table td {
vertical-align: middle;
box-sizing: border-box;
}
.bootstrap-table .fixed-table-container .table thead th {
vertical-align: bottom;
padding: 0;
margin: 0;
}
.bootstrap-table .fixed-table-container .table thead th:focus {
outline: 0 solid transparent;
}
.bootstrap-table .fixed-table-container .table thead th.detail {
width: 30px;
}
.bootstrap-table .fixed-table-container .table thead th .th-inner {
padding: 0.75rem;
vertical-align: bottom;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.bootstrap-table .fixed-table-container .table thead th .sortable {
cursor: pointer;
background-position: right;
background-repeat: no-repeat;
padding-right: 30px !important;
}
.bootstrap-table .fixed-table-container .table thead th .both {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAQAAADYWf5HAAAAkElEQVQoz7X QMQ5AQBCF4dWQSJxC5wwax1Cq1e7BAdxD5SL+Tq/QCM1oNiJidwox0355mXnG/DrEtIQ6azioNZQxI0ykPhTQIwhCR+BmBYtlK7kLJYwWCcJA9M4qdrZrd8pPjZWPtOqdRQy320YSV17OatFC4euts6z39GYMKRPCTKY9UnPQ6P+GtMRfGtPnBCiqhAeJPmkqAAAAAElFTkSuQmCC");
}
.bootstrap-table .fixed-table-container .table thead th .asc {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZ0lEQVQ4y2NgGLKgquEuFxBPAGI2ahhWCsS/gDibUoO0gPgxEP8H4ttArEyuQYxAPBdqEAxPBImTY5gjEL9DM+wTENuQahAvEO9DMwiGdwAxOymGJQLxTyD+jgWDxCMZRsEoGAVoAADeemwtPcZI2wAAAABJRU5ErkJggg==");
}
.bootstrap-table .fixed-table-container .table thead th .desc {
background-image: url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABMAAAATCAYAAAByUDbMAAAAZUlEQVQ4y2NgGAWjYBSggaqGu5FA/BOIv2PBIPFEUgxjB+IdQPwfC94HxLykus4GiD+hGfQOiB3J8SojEE9EM2wuSJzcsFMG4ttQgx4DsRalkZENxL+AuJQaMcsGxBOAmGvopk8AVz1sLZgg0bsAAAAASUVORK5CYII= ");
}
.bootstrap-table .fixed-table-container .table tbody tr.selected td {
background-color: rgba(0, 0, 0, 0.035);
}
.bootstrap-table .fixed-table-container .table tbody tr.no-records-found td {
text-align: center;
}
.bootstrap-table .fixed-table-container .table tbody tr .card-view {
display: flex;
}
.bootstrap-table .fixed-table-container .table tbody tr .card-view .card-view-title {
font-weight: bold;
display: inline-block;
min-width: 30%;
text-align: left !important;
}
.bootstrap-table .fixed-table-container .table .bs-checkbox {
text-align: center;
}
.bootstrap-table .fixed-table-container .table .bs-checkbox label {
margin-bottom: 0;
}
.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type="radio"],
.bootstrap-table .fixed-table-container .table .bs-checkbox label input[type="checkbox"] {
margin: 0 auto !important;
}
.bootstrap-table .fixed-table-container .table.table-sm .th-inner {
padding: 0.3rem;
}
.bootstrap-table .fixed-table-container.fixed-height:not(.has-footer) {
border-bottom: 1px solid #dee2e6;
}
.bootstrap-table .fixed-table-container.fixed-height.has-card-view {
border-top: 1px solid #dee2e6;
border-bottom: 1px solid #dee2e6;
}
.bootstrap-table .fixed-table-container.fixed-height .fixed-table-border {
border-left: 1px solid #dee2e6;
border-right: 1px solid #dee2e6;
}
.bootstrap-table .fixed-table-container.fixed-height .table thead th {
border-bottom: 1px solid #dee2e6;
}
.bootstrap-table .fixed-table-container.fixed-height .table-dark thead th {
border-bottom: 1px solid #32383e;
}
.bootstrap-table .fixed-table-container .fixed-table-header {
overflow: hidden;
}
.bootstrap-table .fixed-table-container .fixed-table-body {
overflow-x: auto;
overflow-y: auto;
height: 100%;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading {
align-items: center;
background: #fff;
display: none;
justify-content: center;
position: absolute;
bottom: 0;
width: 100%;
z-index: 1000;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap {
align-items: baseline;
display: flex;
justify-content: center;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .loading-text {
font-size: 2rem;
margin-right: 6px;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap {
align-items: center;
display: flex;
justify-content: center;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot,
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after,
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::before {
content: "";
animation-duration: 1.5s;
animation-iteration-count: infinite;
animation-name: LOADING;
background: #212529;
border-radius: 50%;
display: block;
height: 5px;
margin: 0 4px;
opacity: 0;
width: 5px;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-dot {
animation-delay: 0.3s;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading .loading-wrap .animation-wrap::after {
animation-delay: 0.6s;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark {
background: #212529;
}
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-dot,
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::after,
.bootstrap-table .fixed-table-container .fixed-table-body .fixed-table-loading.table-dark .animation-wrap::before {
background: #fff;
}
.bootstrap-table .fixed-table-container .fixed-table-footer {
overflow: hidden;
}
.bootstrap-table .fixed-table-pagination::after {
content: "";
display: block;
clear: both;
}
.bootstrap-table .fixed-table-pagination > .pagination-detail,
.bootstrap-table .fixed-table-pagination > .pagination {
margin-top: 10px;
margin-bottom: 10px;
}
.bootstrap-table .fixed-table-pagination > .pagination-detail .pagination-info {
line-height: 34px;
margin-right: 5px;
}
.bootstrap-table .fixed-table-pagination > .pagination-detail .page-list {
display: inline-block;
}
.bootstrap-table .fixed-table-pagination > .pagination-detail .page-list .btn-group {
position: relative;
display: inline-block;
vertical-align: middle;
}
.bootstrap-table .fixed-table-pagination > .pagination-detail .page-list .btn-group .dropdown-menu {
margin-bottom: 0;
}
.bootstrap-table .fixed-table-pagination > .pagination ul.pagination {
margin: 0;
}
.bootstrap-table .fixed-table-pagination > .pagination ul.pagination a {
/*padding: 6px 12px;
line-height: 1.428571429;*/
}
.bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.page-intermediate a {
color: #c8c8c8;
}
.bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.page-intermediate a::before {
content: '\2B05';
}
.bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.page-intermediate a::after {
content: '\27A1';
}
.bootstrap-table .fixed-table-pagination > .pagination ul.pagination li.disabled a {
pointer-events: none;
cursor: default;
}
.bootstrap-table.fullscreen {
position: fixed;
top: 0;
left: 0;
z-index: 1050;
width: 100% !important;
background: #fff;
height: calc(100vh);
overflow-y: scroll;
}
.dropdown-item.dropdown-item-marker {
padding: .25rem 1.5rem;
}
.dropdown-item.dropdown-item-marker:focus,
.dropdown-item.dropdown-item:active {
background-color: #fff;
color: #4d5259;
}
/* calculate scrollbar width */
div.fixed-table-scroll-inner {
width: 100%;
height: 200px;
}
div.fixed-table-scroll-outer {
top: 0;
left: 0;
visibility: hidden;
width: 200px;
height: 150px;
overflow: hidden;
}
@keyframes LOADING {
0% {
opacity: 0;
}
50% {
opacity: 1;
}
to {
opacity: 0;
}
}
File diff suppressed because it is too large Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
/**
* bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation)
*
* @version v1.16.0
* @homepage https://bootstrap-table.com
* @author wenzhixin <wenzhixin2010@gmail.com> (http://wenzhixin.net.cn/)
* @license MIT
*/
.table-cell-input{display:block!important;padding:5px!important;margin:0!important;border:0!important;width:100%!important;box-sizing:border-box!important;-moz-box-sizing:border-box!important;border-radius:0!important;line-height:1!important;white-space:nowrap}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,10 @@
/**
* bootstrap-table - An extended table to integration with some of the most widely used CSS frameworks. (Supports Bootstrap, Semantic UI, Bulma, Material Design, Foundation)
*
* @version v1.16.0
* @homepage https://bootstrap-table.com
* @author wenzhixin <wenzhixin2010@gmail.com> (http://wenzhixin.net.cn/)
* @license MIT
*/
@charset "UTF-8";.no-filter-control{height:34px}.filter-control{margin:0 2px 2px 2px}
File diff suppressed because one or more lines are too long
@@ -0,0 +1,395 @@
/**
* @author zhixin wen <wenzhixin2010@gmail.com>
*/
const Utils = $.fn.bootstrapTable.utils
// Reasonable defaults
const PIXEL_STEP = 10
const LINE_HEIGHT = 40
const PAGE_HEIGHT = 800
function normalizeWheel (event) {
let sX = 0 // spinX
let sY = 0 // spinY
let pX = 0 // pixelX
let pY = 0 // pixelY
// Legacy
if ('detail' in event) { sY = event.detail }
if ('wheelDelta' in event) { sY = -event.wheelDelta / 120 }
if ('wheelDeltaY' in event) { sY = -event.wheelDeltaY / 120 }
if ('wheelDeltaX' in event) { sX = -event.wheelDeltaX / 120 }
// side scrolling on FF with DOMMouseScroll
if ( 'axis' in event && event.axis === event.HORIZONTAL_AXIS ) {
sX = sY
sY = 0
}
pX = sX * PIXEL_STEP
pY = sY * PIXEL_STEP
if ('deltaY' in event) { pY = event.deltaY }
if ('deltaX' in event) { pX = event.deltaX }
if ((pX || pY) && event.deltaMode) {
if (event.deltaMode === 1) { // delta in LINE units
pX *= LINE_HEIGHT
pY *= LINE_HEIGHT
} else { // delta in PAGE units
pX *= PAGE_HEIGHT
pY *= PAGE_HEIGHT
}
}
// Fall-back if spin cannot be determined
if (pX && !sX) { sX = (pX < 1) ? -1 : 1 }
if (pY && !sY) { sY = (pY < 1) ? -1 : 1 }
return {
spinX: sX,
spinY: sY,
pixelX: pX,
pixelY: pY
}
}
$.extend($.fn.bootstrapTable.defaults, {
fixedColumns: false,
fixedNumber: 0,
fixedRightNumber: 0
})
$.BootstrapTable = class extends $.BootstrapTable {
fixedColumnsSupported () {
return this.options.fixedColumns &&
!this.options.detailView &&
!this.options.cardView
}
initContainer () {
super.initContainer()
if (!this.fixedColumnsSupported()) {
return
}
if (this.options.fixedNumber) {
this.$tableContainer.append('<div class="fixed-columns"></div>')
this.$fixedColumns = this.$tableContainer.find('.fixed-columns')
}
if (this.options.fixedRightNumber) {
this.$tableContainer.append('<div class="fixed-columns-right"></div>')
this.$fixedColumnsRight = this.$tableContainer.find('.fixed-columns-right')
}
}
initBody (...args) {
super.initBody(...args)
if (!this.fixedColumnsSupported()) {
return
}
if (this.options.showHeader && this.options.height) {
return
}
this.initFixedColumnsBody()
this.initFixedColumnsEvents()
}
trigger (...args) {
super.trigger(...args)
if (!this.fixedColumnsSupported()) {
return
}
if (args[0] === 'post-header') {
this.initFixedColumnsHeader()
} else if (args[0] === 'scroll-body') {
if (this.needFixedColumns && this.options.fixedNumber) {
this.$fixedBody.scrollTop(this.$tableBody.scrollTop())
}
if (this.needFixedColumns && this.options.fixedRightNumber) {
this.$fixedBodyRight.scrollTop(this.$tableBody.scrollTop())
}
}
}
updateSelected () {
super.updateSelected()
if (!this.fixedColumnsSupported()) {
return
}
this.$tableBody.find('tr').each((i, el) => {
const $el = $(el)
const index = $el.data('index')
const classes = $el.attr('class')
const inputSelector = `[name="${this.options.selectItemName}"]`
const $input = $el.find(inputSelector)
if (typeof index === undefined) {
return
}
const updateFixedBody = ($fixedHeader, $fixedBody) => {
const $tr = $fixedBody.find(`tr[data-index="${index}"]`)
$tr.attr('class', classes)
if ($input.length) {
$tr.find(inputSelector).prop('checked', $input.prop('checked'))
}
if (this.$selectAll.length) {
$fixedHeader.add($fixedBody)
.find('[name="btSelectAll"]')
.prop('checked', this.$selectAll.prop('checked'))
}
}
if (this.$fixedBody && this.options.fixedNumber) {
updateFixedBody(this.$fixedHeader, this.$fixedBody)
}
if (this.$fixedBodyRight && this.options.fixedRightNumber) {
updateFixedBody(this.$fixedHeaderRight, this.$fixedBodyRight)
}
})
}
hideLoading () {
super.hideLoading()
if (this.needFixedColumns && this.options.fixedNumber) {
this.$fixedColumns.find('.fixed-table-loading').hide()
}
if (this.needFixedColumns && this.options.fixedRightNumber) {
this.$fixedColumnsRight.find('.fixed-table-loading').hide()
}
}
initFixedColumnsHeader () {
if (this.options.height) {
this.needFixedColumns = this.$tableHeader.outerWidth(true) < this.$tableHeader.find('table').outerWidth(true)
} else {
this.needFixedColumns = this.$tableBody.outerWidth(true) < this.$tableBody.find('table').outerWidth(true)
}
const initFixedHeader = ($fixedColumns, isRight) => {
$fixedColumns.find('.fixed-table-header').remove()
$fixedColumns.append(this.$tableHeader.clone(true))
$fixedColumns.css({
width: this.getFixedColumnsWidth(isRight)
})
return $fixedColumns.find('.fixed-table-header')
}
if (this.needFixedColumns && this.options.fixedNumber) {
this.$fixedHeader = initFixedHeader(this.$fixedColumns)
this.$fixedHeader.css('margin-right', '')
} else if (this.$fixedColumns) {
this.$fixedColumns.html('').css('width', '')
}
if (this.needFixedColumns && this.options.fixedRightNumber) {
this.$fixedHeaderRight = initFixedHeader(this.$fixedColumnsRight, true)
this.$fixedHeaderRight.scrollLeft(this.$fixedHeaderRight.find('table').width())
} else if (this.$fixedColumnsRight) {
this.$fixedColumnsRight.html('').css('width', '')
}
this.initFixedColumnsBody()
this.initFixedColumnsEvents()
}
initFixedColumnsBody () {
const initFixedBody = ($fixedColumns, $fixedHeader) => {
$fixedColumns.find('.fixed-table-body').remove()
$fixedColumns.append(this.$tableBody.clone(true))
const $fixedBody = $fixedColumns.find('.fixed-table-body')
const tableBody = this.$tableBody.get(0)
const scrollHeight = tableBody.scrollWidth > tableBody.clientWidth
? Utils.getScrollBarWidth() : 0
const height = this.$tableContainer.outerHeight(true) - scrollHeight - 1
$fixedColumns.css({
height
})
$fixedBody.css({
height: height - $fixedHeader.height()
})
return $fixedBody
}
if (this.needFixedColumns && this.options.fixedNumber) {
this.$fixedBody = initFixedBody(this.$fixedColumns, this.$fixedHeader)
}
if (this.needFixedColumns && this.options.fixedRightNumber) {
this.$fixedBodyRight = initFixedBody(this.$fixedColumnsRight, this.$fixedHeaderRight)
this.$fixedBodyRight.scrollLeft(this.$fixedBodyRight.find('table').width())
this.$fixedBodyRight.css('overflow-y', this.options.height ? 'auto' : 'hidden')
}
}
getFixedColumnsWidth (isRight) {
let visibleFields = this.getVisibleFields()
let width = 0
let fixedNumber = this.options.fixedNumber
let marginRight = 0
if (isRight) {
visibleFields = visibleFields.reverse()
fixedNumber = this.options.fixedRightNumber
marginRight = parseInt(this.$tableHeader.css('margin-right'), 10)
}
for (let i = 0; i < fixedNumber; i++) {
width += this.$header.find(`th[data-field="${visibleFields[i]}"]`).outerWidth(true)
}
return width + marginRight + 1
}
initFixedColumnsEvents () {
const toggleHover = (e, toggle) => {
const tr = `tr[data-index="${$(e.currentTarget).data('index')}"]`
let $trs = this.$tableBody.find(tr)
if (this.$fixedBody) {
$trs = $trs.add(this.$fixedBody.find(tr))
}
if (this.$fixedBodyRight) {
$trs = $trs.add(this.$fixedBodyRight.find(tr))
}
$trs.css('background-color', toggle ? $(e.currentTarget).css('background-color') : '')
}
this.$tableBody.find('tr').hover(e => {
toggleHover(e, true)
}, e => {
toggleHover(e, false)
})
const isFirefox = typeof navigator !== 'undefined' &&
navigator.userAgent.toLowerCase().indexOf('firefox') > -1
const mousewheel = isFirefox ? 'DOMMouseScroll' : 'mousewheel'
const updateScroll = (e, fixedBody) => {
const normalized = normalizeWheel(e)
const deltaY = Math.ceil(normalized.pixelY)
const top = this.$tableBody.scrollTop() + deltaY
if (
deltaY < 0 && top > 0 ||
deltaY > 0 && top < fixedBody.scrollHeight - fixedBody.clientHeight
) {
e.preventDefault()
}
this.$tableBody.scrollTop(top)
if (this.$fixedBody) {
this.$fixedBody.scrollTop(top)
}
if (this.$fixedBodyRight) {
this.$fixedBodyRight.scrollTop(top)
}
}
if (this.needFixedColumns && this.options.fixedNumber) {
this.$fixedBody.find('tr').hover(e => {
toggleHover(e, true)
}, e => {
toggleHover(e, false)
})
this.$fixedBody[0].addEventListener(mousewheel, e => {
updateScroll(e, this.$fixedBody[0])
})
}
if (this.needFixedColumns && this.options.fixedRightNumber) {
this.$fixedBodyRight.find('tr').hover(e => {
toggleHover(e, true)
}, e => {
toggleHover(e, false)
})
this.$fixedBodyRight.off('scroll').on('scroll', () => {
const top = this.$fixedBodyRight.scrollTop()
this.$tableBody.scrollTop(top)
if (this.$fixedBody) {
this.$fixedBody.scrollTop(top)
}
})
}
if (this.options.filterControl) {
$(this.$fixedColumns).off('keyup change').on('keyup change', e => {
const $target = $(e.target)
const value = $target.val()
const field = $target.parents('th').data('field')
const $coreTh = this.$header.find(`th[data-field="${field}"]`)
if ($target.is('input')) {
$coreTh.find('input').val(value)
} else if ($target.is('select')) {
const $select = $coreTh.find('select')
$select.find('option[selected]').removeAttr('selected')
$select.find(`option[value="${value}"]`).attr('selected', true)
}
this.triggerSearch()
})
}
}
renderStickyHeader () {
if (!this.options.stickyHeader) {
return
}
this.$stickyContainer = this.$container.find('.sticky-header-container')
super.renderStickyHeader()
if (this.needFixedColumns && this.options.fixedNumber) {
this.$fixedColumns.css('z-index', 101)
.find('.sticky-header-container')
.css('right', '')
.width(this.$fixedColumns.outerWidth())
}
if (this.needFixedColumns && this.options.fixedRightNumber) {
const $stickyHeaderContainerRight = this.$fixedColumnsRight.find('.sticky-header-container')
this.$fixedColumnsRight.css('z-index', 101)
$stickyHeaderContainerRight.css('left', '')
.scrollLeft($stickyHeaderContainerRight.find('.table').outerWidth())
.width(this.$fixedColumnsRight.outerWidth())
}
}
matchPositionX () {
if (!this.options.stickyHeader) {
return
}
this.$stickyContainer.eq(0).scrollLeft(this.$tableBody.scrollLeft())
}
}
@@ -0,0 +1,25 @@
.fixed-columns,
.fixed-columns-right {
position: absolute;
top: 0;
height: 100%;
background-color: #fff;
box-sizing: border-box;
z-index: 1;
}
.fixed-columns {
left: 0;
.fixed-table-body {
overflow: hidden!important;
}
}
.fixed-columns-right {
right: 0;
.fixed-table-body {
overflow-x: hidden!important;
}
}
@@ -0,0 +1,277 @@
/**
* @author: Yura Knoxville
* @version: v1.1.0
*/
let initBodyCaller
// it only does '%s', and return '' when arguments are undefined
const sprintf = function (str) {
const args = arguments
let flag = true
let i = 1
str = str.replace(/%s/g, () => {
const arg = args[i++]
if (typeof arg === 'undefined') {
flag = false
return ''
}
return arg
})
return flag ? str : ''
}
const groupBy = (array, f) => {
const tmpGroups = {}
array.forEach(o => {
const groups = f(o)
tmpGroups[groups] = tmpGroups[groups] || []
tmpGroups[groups].push(o)
})
return tmpGroups
}
$.extend($.fn.bootstrapTable.defaults, {
groupBy: false,
groupByField: '',
groupByFormatter: undefined
})
const Utils = $.fn.bootstrapTable.utils
const BootstrapTable = $.fn.bootstrapTable.Constructor
const _initSort = BootstrapTable.prototype.initSort
const _initBody = BootstrapTable.prototype.initBody
const _updateSelected = BootstrapTable.prototype.updateSelected
BootstrapTable.prototype.initSort = function (...args) {
_initSort.apply(this, Array.prototype.slice.apply(args))
const that = this
this.tableGroups = []
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
if ((this.options.sortName !== this.options.groupByField)) {
if (this.options.customSort) {
Utils.calculateObjectValue(this.options, this.options.customSort, [
this.options.sortName,
this.options.sortOrder,
this.data
])
} else {
this.data.sort((a, b) => {
const groupByFields = this.getGroupByFields()
const fieldValuesA = []
const fieldValuesB = []
$.each(groupByFields, (i, field) => {
fieldValuesA.push(a[field])
fieldValuesB.push(b[field])
})
a = fieldValuesA.join()
b = fieldValuesB.join()
return a.localeCompare(b, undefined, {numeric: true})
})
}
}
const groups = groupBy(that.data, (item) => {
const groupByFields = this.getGroupByFields()
const groupValues = []
$.each(groupByFields, (i, field) => {
groupValues.push(item[field])
})
return groupValues.join(', ')
})
let index = 0
$.each(groups, (key, value) => {
this.tableGroups.push({
id: index,
name: key,
data: value
})
value.forEach(item => {
if (!item._data) {
item._data = {}
}
item._data['parent-index'] = index
})
index++
})
}
}
BootstrapTable.prototype.initBody = function (...args) {
initBodyCaller = true
_initBody.apply(this, Array.prototype.slice.apply(args))
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
const that = this
let checkBox = false
let visibleColumns = 0
this.columns.forEach(column => {
if (column.checkbox) {
checkBox = true
} else {
if (column.visible) {
visibleColumns += 1
}
}
})
if (this.options.detailView && !this.options.cardView) {
visibleColumns += 1
}
this.tableGroups.forEach(item => {
const html = []
html.push(sprintf('<tr class="info groupBy expanded" data-group-index="%s">', item.id))
if (that.options.detailView && !that.options.cardView) {
html.push('<td class="detail"></td>')
}
if (checkBox) {
html.push('<td class="bs-checkbox">',
'<input name="btSelectGroup" type="checkbox" />',
'</td>'
)
}
let formattedValue = item.name
if (typeof (that.options.groupByFormatter) === 'function') {
formattedValue = that.options.groupByFormatter(item.name, item.id, item.data)
}
html.push('<td',
sprintf(' colspan="%s"', visibleColumns),
'>', formattedValue, '</td>'
)
html.push('</tr>')
that.$body.find(`tr[data-parent-index=${item.id}]:first`).before($(html.join('')))
})
this.$selectGroup = []
this.$body.find('[name="btSelectGroup"]').each(function () {
const self = $(this)
that.$selectGroup.push({
group: self,
item: that.$selectItem.filter(function () {
return ($(this).closest('tr').data('parent-index') ===
self.closest('tr').data('group-index'))
})
})
})
this.$container.off('click', '.groupBy')
.on('click', '.groupBy', function () {
$(this).toggleClass('expanded')
that.$body.find(`tr[data-parent-index=${$(this).closest('tr').data('group-index')}]`).toggleClass('hidden')
})
this.$container.off('click', '[name="btSelectGroup"]')
.on('click', '[name="btSelectGroup"]', function (event) {
event.stopImmediatePropagation()
const self = $(this)
const checked = self.prop('checked')
that[checked ? 'checkGroup' : 'uncheckGroup']($(this).closest('tr').data('group-index'))
})
}
initBodyCaller = false
this.updateSelected()
}
BootstrapTable.prototype.updateSelected = function (...args) {
if (!initBodyCaller) {
_updateSelected.apply(this, Array.prototype.slice.apply(args))
if ((this.options.groupBy) && (this.options.groupByField !== '')) {
this.$selectGroup.forEach(item => {
const checkGroup = item.item.filter(':enabled').length ===
item.item.filter(':enabled').filter(':checked').length
item.group.prop('checked', checkGroup)
})
}
}
}
BootstrapTable.prototype.checkGroup = function (index) {
this.checkGroup_(index, true)
}
BootstrapTable.prototype.uncheckGroup = function (index) {
this.checkGroup_(index, false)
}
BootstrapTable.prototype.checkGroup_ = function (index, checked) {
const rowsBefore = this.getSelections()
let rows
const filter = function () {
return ($(this).closest('tr').data('parent-index') === index)
}
this.$selectItem.filter(filter).prop('checked', checked)
this.updateRows()
this.updateSelected()
const rowsAfter = this.getSelections()
if (checked) {
this.trigger('check-all', rowsAfter, rowsBefore)
return
}
this.trigger('uncheck-all', rowsAfter, rowsBefore)
}
BootstrapTable.prototype.getGroupByFields = function () {
let groupByFields = this.options.groupByField
if (!$.isArray(this.options.groupByField)) {
groupByFields = [this.options.groupByField]
}
return groupByFields
}
$.BootstrapTable = class extends $.BootstrapTable {
scrollTo (params) {
if (this.options.groupBy) {
let options = {unit: 'px', value: 0}
if (typeof params === 'object') {
options = Object.assign(options, params)
}
if (options.unit === 'rows') {
let scrollTo = 0
this.$body.find(`> tr:lt(${options.value})`).each((i, el) => {
scrollTo += $(el).outerHeight(true)
})
const $targetColumn = this.$body.find(`> tr:not(.groupBy):eq(${options.value})`)
$targetColumn.prevAll('.groupBy').each((i, el) => {
scrollTo += $(el).outerHeight(true)
})
this.$tableBody.scrollTop(scrollTo)
return
}
}
super.scrollTo(params)
}
}
@@ -0,0 +1,7 @@
.bootstrap-table .table > tbody > tr.groupBy {
cursor: pointer;
}
.bootstrap-table .table > tbody > tr.hidden + tr.detail-view {
display: none;
}
@@ -0,0 +1,12 @@
{
"name": "Group By V2",
"version": "1.0.0",
"description": "Group the data by field",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/group-by-v2",
"example": "",
"plugins": [],
"author": {
"name": "Knoxvillekm",
"image": "https://avatars3.githubusercontent.com/u/11072464"
}
}
@@ -0,0 +1,31 @@
/**
* @author: Jewway
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
$.fn.bootstrapTable.methods.push('changeTitle')
$.fn.bootstrapTable.methods.push('changeLocale')
$.BootstrapTable = class extends $.BootstrapTable {
changeTitle (locale) {
$.each(this.options.columns, (idx, columnList) => {
$.each(columnList, (idx, column) => {
if (column.field) {
column.title = locale[column.field]
}
})
})
this.initHeader()
this.initBody()
this.initToolbar()
}
changeLocale (localeId) {
this.options.locale = localeId
this.initLocale()
this.initPagination()
this.initBody()
this.initToolbar()
}
}
@@ -0,0 +1,17 @@
{
"name": "i18n Enhance",
"version": "1.0.0",
"description": "Plugin to add i18n API in order to change column's title and table locale.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/i18n-enhance",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/i18n-enhance.html",
"plugins": [{
"name": "bootstrap-table-i18n-enhance",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/i18n-enhance"
}],
"author": {
"name": "Jewway",
"image": "https://avatars0.githubusercontent.com/u/3501899"
}
}
@@ -0,0 +1,74 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
$.extend($.fn.bootstrapTable.defaults, {
keyEvents: false
})
$.BootstrapTable = class extends $.BootstrapTable {
init (...args) {
super.init(...args)
if (this.options.keyEvents) {
this.initKeyEvents()
}
}
initKeyEvents () {
$(document).off('keydown').on('keydown', e => {
const $search = this.$toolbar.find('.search input')
const $refresh = this.$toolbar.find('button[name="refresh"]')
const $toggle = this.$toolbar.find('button[name="toggle"]')
const $paginationSwitch = this.$toolbar.find('button[name="paginationSwitch"]')
if (document.activeElement === $search.get(0) || !$.contains(document.activeElement ,this.$toolbar.get(0))) {
return true
}
switch (e.keyCode) {
case 83: // s
if (!this.options.search) {
return
}
$search.focus()
return false
case 82: // r
if (!this.options.showRefresh) {
return
}
$refresh.click()
return false
case 84: // t
if (!this.options.showToggle) {
return
}
$toggle.click()
return false
case 80: // p
if (!this.options.showPaginationSwitch) {
return
}
$paginationSwitch.click()
return false
case 37: // left
if (!this.options.pagination) {
return
}
this.prevPage()
return false
case 39: // right
if (!this.options.pagination) {
return
}
this.nextPage()
return
default:
break
}
})
}
}
@@ -0,0 +1,17 @@
{
"name": "Key Events",
"version": "1.0.0",
"description": "Plugin to support the key events in the bootstrap table.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/key-events",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/key-events.html",
"plugins": [{
"name": "bootstrap-table-key-events",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/key-events"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}
@@ -0,0 +1,123 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
const debounce = (func, wait) => {
let timeout = 0
return (...args) => {
const later = () => {
timeout = 0
func(...args)
}
clearTimeout(timeout)
timeout = setTimeout(later, wait)
}
}
$.extend($.fn.bootstrapTable.defaults, {
mobileResponsive: false,
minWidth: 562,
minHeight: undefined,
heightThreshold: 100, // just slightly larger than mobile chrome's auto-hiding toolbar
checkOnInit: true,
columnsHidden: []
})
$.BootstrapTable = class extends $.BootstrapTable {
init (...args) {
super.init(...args)
if (!this.options.mobileResponsive || !this.options.minWidth) {
return
}
if (this.options.minWidth < 100 && this.options.resizable) {
console.info('The minWidth when the resizable extension is active should be greater or equal than 100')
this.options.minWidth = 100
}
let old = {
width: $(window).width(),
height: $(window).height()
}
$(window).on('resize orientationchange', debounce(() => {
// reset view if height has only changed by at least the threshold.
const width = $(window).width()
const height = $(window).height()
const $activeElement = $(document.activeElement)
if ($activeElement.length && ['INPUT', 'SELECT', 'TEXTAREA'].includes($activeElement.prop('nodeName'))) {
return
}
if (
Math.abs(old.height - height) > this.options.heightThreshold ||
old.width !== width
) {
this.changeView(width, height)
old = {
width,
height
}
}
}, 200))
if (this.options.checkOnInit) {
const width = $(window).width()
const height = $(window).height()
this.changeView(width, height)
old = {
width,
height
}
}
}
conditionCardView () {
this.changeTableView(false)
this.showHideColumns(false)
}
conditionFullView () {
this.changeTableView(true)
this.showHideColumns(true)
}
changeTableView (cardViewState) {
this.options.cardView = cardViewState
this.toggleView()
}
showHideColumns (checked) {
if (this.options.columnsHidden.length > 0) {
this.columns.forEach(column => {
if (this.options.columnsHidden.includes(column.field)) {
if (column.visible !== checked) {
this._toggleColumn(this.fieldsColumnsIndex[column.field], checked, true)
}
}
})
}
}
changeView (width, height) {
if (this.options.minHeight) {
if ((width <= this.options.minWidth) && (height <= this.options.minHeight)) {
this.conditionCardView()
} else if ((width > this.options.minWidth) && (height > this.options.minHeight)) {
this.conditionFullView()
}
} else {
if (width <= this.options.minWidth) {
this.conditionCardView()
} else if (width > this.options.minWidth) {
this.conditionFullView()
}
}
this.resetView()
}
}
@@ -0,0 +1,17 @@
{
"name": "Mobile",
"version": "1.1.0",
"description": "Plugin to support the responsive feature.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/mobile",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/mobile.html",
"plugins": [{
"name": "bootstrap-table-mobile",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/mobile"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}
@@ -0,0 +1,728 @@
/**
* @author Nadim Basalamah <dimbslmh@gmail.com>
* @version: v1.1.0
* https://github.com/dimbslmh/bootstrap-table/tree/master/src/extensions/multiple-sort/bootstrap-table-multiple-sort.js
* Modification: ErwannNevou <https://github.com/ErwannNevou>
*/
let isSingleSort = false
const Utils = $.fn.bootstrapTable.utils
const bootstrap = {
bootstrap3: {
icons: {
plus: 'glyphicon-plus',
minus: 'glyphicon-minus',
sort: 'glyphicon-sort'
},
html: {
multipleSortModal: `
<div class="modal fade" id="%s" tabindex="-1" role="dialog" aria-labelledby="%sLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="%sLabel">%s</h4>
</div>
<div class="modal-body">
<div class="bootstrap-table">
<div class="fixed-table-toolbar">
<div class="bars">
<div id="toolbar">
<button id="add" type="button" class="btn btn-default">%s %s</button>
<button id="delete" type="button" class="btn btn-default" disabled>%s %s</button>
</div>
</div>
</div>
<div class="fixed-table-container">
<table id="multi-sort" class="table">
<thead>
<tr>
<th></th>
<th><div class="th-inner">%s</div></th>
<th><div class="th-inner">%s</div></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">%s</button>
<button type="button" class="btn btn-primary multi-sort-order-button">%s</button>
</div>
</div>
</div>
</div>
`,
multipleSortButton: '<button class="multi-sort btn btn-default" type="button" data-toggle="modal" data-target="#%s" title="%s">%s</button>',
multipleSortSelect: '<select class="%s %s form-control">'
}
},
bootstrap4: {
icons: {
'plus': 'fa-plus',
'minus': 'fa-minus',
'sort': 'fa-sort'
},
html: {
multipleSortModal: `
<div class="modal fade" id="%s" tabindex="-1" role="dialog" aria-labelledby="%sLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="%sLabel">%s</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="bootstrap-table">
<div class="fixed-table-toolbar">
<div class="bars">
<div id="toolbar" class="pb-3">
<button id="add" type="button" class="btn btn-secondary">%s %s</button>
<button id="delete" type="button" class="btn btn-secondary" disabled>%s %s</button>
</div>
</div>
</div>
<div class="fixed-table-container">
<table id="multi-sort" class="table">
<thead>
<tr>
<th></th>
<th><div class="th-inner">%s</div></th>
<th><div class="th-inner">%s</div></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">%s</button>
<button type="button" class="btn btn-primary multi-sort-order-button">%s</button>
</div>
</div>
</div>
</div>
`,
multipleSortButton: '<button class="multi-sort btn btn-secondary" type="button" data-toggle="modal" data-target="#%s" title="%s">%s</button>',
multipleSortSelect: '<select class="%s %s form-control">'
}
},
semantic: {
icons: {
'plus': 'fa-plus',
'minus': 'fa-minus',
'sort': 'fa-sort'
},
html: {
multipleSortModal: `
<div class="ui modal tiny" id="%s" aria-labelledby="%sLabel" aria-hidden="true">
<i class="close icon"></i>
<div class="header" id="%sLabel">
%s
</div>
<div class="image content">
<div class="bootstrap-table">
<div class="fixed-table-toolbar">
<div class="bars">
<div id="toolbar" class="pb-3">
<button id="add" type="button" class="ui button">%s %s</button>
<button id="delete" type="button" class="ui button" disabled>%s %s</button>
</div>
</div>
</div>
<div class="fixed-table-container">
<table id="multi-sort" class="table">
<thead>
<tr>
<th></th>
<th><div class="th-inner">%s</div></th>
<th><div class="th-inner">%s</div></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
</div>
<div class="actions">
<div class="ui button deny">%s</div>
<div class="ui button approve multi-sort-order-button">%s</div>
</div>
</div>
`,
multipleSortButton: '<button class="multi-sort ui button" type="button" data-toggle="modal" data-target="#%s" title="%s">%s</button>',
multipleSortSelect: '<select class="%s %s">'
}
},
materialize: {
icons: {
'plus': 'plus',
'minus': 'minus',
'sort': 'sort'
},
html: {
multipleSortModal: `
<div id="%s" class="modal" aria-labelledby="%sLabel" aria-hidden="true">
<div class="modal-content" id="%sLabel">
<h4>%s</h4>
<div class="bootstrap-table">
<div class="fixed-table-toolbar">
<div class="bars">
<div id="toolbar" class="pb-3">
<button id="add" type="button" class="waves-effect waves-light btn">%s %s</button>
<button id="delete" type="button" class="waves-effect waves-light btn" disabled>%s %s</button>
</div>
</div>
</div>
<div class="fixed-table-container">
<table id="multi-sort" class="table">
<thead>
<tr>
<th></th>
<th><div class="th-inner">%s</div></th>
<th><div class="th-inner">%s</div></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<div class="modal-footer">
<a href="javascript:void(0)" class="modal-close waves-effect waves-light btn">%s</a>
<a href="javascript:void(0)" class="modal-close waves-effect waves-light btn multi-sort-order-button">%s</a>
</div>
</div>
</div>
`,
multipleSortButton: '<a href="#%s" class="multi-sort waves-effect waves-light btn modal-trigger" type="button" data-toggle="modal" title="%s">%s</a>',
multipleSortSelect: '<select class="%s %s browser-default">'
}
},
foundation: {
icons: {
'plus': 'fa-plus',
'minus': 'fa-minus',
'sort': 'fa-sort'
},
html: {
multipleSortModal: `
<div class="reveal" id="%s" data-reveal aria-labelledby="%sLabel" aria-hidden="true">
<div id="%sLabel">
<h1>%s</h1>
<div class="bootstrap-table">
<div class="fixed-table-toolbar">
<div class="bars">
<div id="toolbar" class="padding-bottom-2">
<button id="add" type="button" class="waves-effect waves-light button">%s %s</button>
<button id="delete" type="button" class="waves-effect waves-light button" disabled>%s %s</button>
</div>
</div>
</div>
<div class="fixed-table-container">
<table id="multi-sort" class="table">
<thead>
<tr>
<th></th>
<th><div class="th-inner">%s</div></th>
<th><div class="th-inner">%s</div></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<button class="waves-effect waves-light button" data-close aria-label="Close modal" type="button">
<span aria-hidden="true">%s</span>
</button>
<button class="waves-effect waves-light button multi-sort-order-button" data-close aria-label="Order" type="button">
<span aria-hidden="true">%s</span>
</button>
</div>
</div>
`,
multipleSortButton: '<button class="button multi-sort" data-open="%s" title="%s">%s</button>',
multipleSortSelect: '<select class="%s %s browser-default">'
}
},
bulma: {
icons: {
'plus': 'fa-plus',
'minus': 'fa-minus',
'sort': 'fa-sort'
},
html: {
multipleSortModal: `
<div class="modal" id="%s" aria-labelledby="%sLabel" aria-hidden="true">
<div class="modal-background"></div>
<div class="modal-content" id="%sLabel">
<div class="box">
<h2>%s</h2>
<div class="bootstrap-table">
<div class="fixed-table-toolbar">
<div class="bars">
<div id="toolbar" class="padding-bottom-2">
<button id="add" type="button" class="waves-effect waves-light button">%s %s</button>
<button id="delete" type="button" class="waves-effect waves-light button" disabled>%s %s</button>
</div>
</div>
</div>
<div class="fixed-table-container">
<table id="multi-sort" class="table">
<thead>
<tr>
<th></th>
<th><div class="th-inner">%s</div></th>
<th><div class="th-inner">%s</div></th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
</div>
<button type="button" class="waves-effect waves-light button" data-close>%s</button>
<button type="button" class="waves-effect waves-light button multi-sort-order-button" data-close>%s</button>
</div>
</div>
</div>
`,
multipleSortButton: '<button class="button multi-sort" data-target="%s" title="%s">%s</button>',
multipleSortSelect: '<select class="%s %s browser-default">'
}
}
}[$.fn.bootstrapTable.theme]
$.extend($.fn.bootstrapTable.defaults.icons, bootstrap.icons)
$.extend($.fn.bootstrapTable.defaults.html, bootstrap.html)
const showSortModal = that => {
const _selector = that.sortModalSelector
const _id = `#${_selector}`
const o = that.options
if (!$(_id).hasClass('modal')) {
const sModal = Utils.sprintf(
that.constants.html.multipleSortModal,
_selector, _selector, _selector,
that.options.formatMultipleSort(),
Utils.sprintf(that.constants.html.icon, o.iconsPrefix, that.constants.icons.plus),
that.options.formatAddLevel(),
Utils.sprintf(that.constants.html.icon, o.iconsPrefix, that.constants.icons.minus),
that.options.formatDeleteLevel(),
that.options.formatColumn(),
that.options.formatOrder(),
that.options.formatCancel(),
that.options.formatSort()
)
$('body').append($(sModal))
that.$sortModal = $(_id)
const $rows = that.$sortModal.find('tbody > tr')
that.$sortModal.off('click', '#add').on('click', '#add', () => {
const total = that.$sortModal.find('.multi-sort-name:first option').length
let current = that.$sortModal.find('tbody tr').length
if (current < total) {
current++
that.addLevel()
that.setButtonStates()
}
})
that.$sortModal.off('click', '#delete').on('click', '#delete', () => {
const total = that.$sortModal.find('.multi-sort-name:first option').length
let current = that.$sortModal.find('tbody tr').length
if (current > 1 && current <= total) {
current--
that.$sortModal.find('tbody tr:last').remove()
that.setButtonStates()
}
})
that.$sortModal.off('click', '.multi-sort-order-button').on('click', '.multi-sort-order-button', () => {
const $rows = that.$sortModal.find('tbody > tr')
let $alert = that.$sortModal.find('div.alert')
const fields = []
const results = []
const sortPriority = $.map($rows, row => {
const $row = $(row)
const name = $row.find('.multi-sort-name').val()
const order = $row.find('.multi-sort-order').val()
fields.push(name)
return {
sortName: name,
sortOrder: order
}
})
const sorted_fields = fields.sort()
for (let i = 0; i < fields.length - 1; i++) {
if (sorted_fields[i + 1] === sorted_fields[i]) {
results.push(sorted_fields[i])
}
}
if (results.length > 0) {
if ($alert.length === 0) {
$alert = `<div class="alert alert-danger" role="alert"><strong>${that.options.formatDuplicateAlertTitle()}</strong> ${that.options.formatDuplicateAlertDescription()}</div>`
$($alert).insertBefore(that.$sortModal.find('.bars'))
}
} else {
if ($alert.length === 1) {
$($alert).remove()
}
if ($.inArray($.fn.bootstrapTable.theme, ['bootstrap3', 'bootstrap4']) !== -1) {
that.$sortModal.modal('hide')
}
that.multiSort(sortPriority)
}
})
if (that.options.sortPriority === null || that.options.sortPriority.length === 0) {
if (that.options.sortName) {
that.options.sortPriority = [{
sortName: that.options.sortName,
sortOrder: that.options.sortOrder
}]
}
}
if (that.options.sortPriority !== null && that.options.sortPriority.length > 0) {
if ($rows.length < that.options.sortPriority.length && typeof that.options.sortPriority === 'object') {
for (let i = 0; i < that.options.sortPriority.length; i++) {
that.addLevel(i, that.options.sortPriority[i])
}
}
} else {
that.addLevel(0)
}
that.setButtonStates()
}
}
$.fn.bootstrapTable.methods.push('multipleSort')
$.fn.bootstrapTable.methods.push('multiSort')
$.extend($.fn.bootstrapTable.defaults, {
showMultiSort: false,
showMultiSortButton: true,
multiSortStrictSort: false,
sortPriority: null,
onMultipleSort () {
return false
}
})
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'multiple-sort.bs.table': 'onMultipleSort'
})
$.extend($.fn.bootstrapTable.locales, {
formatMultipleSort () {
return 'Multiple Sort'
},
formatAddLevel () {
return 'Add Level'
},
formatDeleteLevel () {
return 'Delete Level'
},
formatColumn () {
return 'Column'
},
formatOrder () {
return 'Order'
},
formatSortBy () {
return 'Sort by'
},
formatThenBy () {
return 'Then by'
},
formatSort () {
return 'Sort'
},
formatCancel () {
return 'Cancel'
},
formatDuplicateAlertTitle () {
return 'Duplicate(s) detected!'
},
formatDuplicateAlertDescription () {
return 'Please remove or change any duplicate column.'
},
formatSortOrders () {
return {
asc: 'Ascending',
desc: 'Descending'
}
}
})
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
const BootstrapTable = $.fn.bootstrapTable.Constructor
const _initToolbar = BootstrapTable.prototype.initToolbar
const _destroy = BootstrapTable.prototype.destroy
BootstrapTable.prototype.initToolbar = function (...args) {
this.showToolbar = this.showToolbar || this.options.showMultiSort
const that = this
const sortModalSelector = `sortModal_${this.$el.attr('id')}`
const sortModalId = `#${sortModalSelector}`
this.$sortModal = $(sortModalId)
this.sortModalSelector = sortModalSelector
if (that.options.sortPriority !== null) {
that.onMultipleSort()
}
_initToolbar.apply(this, Array.prototype.slice.apply(args))
if (that.options.sidePagination === 'server' && !isSingleSort && that.options.sortPriority !== null) {
const t = that.options.queryParams
that.options.queryParams = params => {
params.multiSort = that.options.sortPriority
return t(params)
}
}
if (this.options.showMultiSort) {
const $btnGroup = this.$toolbar.find('>.' + that.constants.classes.buttonsGroup.split(' ').join('.')).first()
let $multiSortBtn = this.$toolbar.find('div.multi-sort')
const o = that.options
if (!$multiSortBtn.length && this.options.showMultiSortButton) {
$multiSortBtn = Utils.sprintf(that.constants.html.multipleSortButton, that.sortModalSelector, this.options.formatMultipleSort(), Utils.sprintf(that.constants.html.icon, o.iconsPrefix, o.icons.sort))
$btnGroup.append($multiSortBtn)
if ($.fn.bootstrapTable.theme === 'semantic') {
this.$toolbar.find('.multi-sort').on('click', () => {
$(sortModalId).modal('show')
})
} else if ($.fn.bootstrapTable.theme === 'materialize') {
this.$toolbar.find('.multi-sort').on('click', () => {
$(sortModalId).modal()
})
} else if ($.fn.bootstrapTable.theme === 'foundation') {
this.$toolbar.find('.multi-sort').on('click', () => {
if (!this.foundationModal) {
// eslint-disable-next-line no-undef
this.foundationModal = new Foundation.Reveal($(sortModalId))
}
this.foundationModal.open()
})
} else if ($.fn.bootstrapTable.theme === 'bulma') {
this.$toolbar.find('.multi-sort').on('click', () => {
$('html').toggleClass('is-clipped')
$(sortModalId).toggleClass('is-active')
$('button[data-close]').one('click', () => {
$('html').toggleClass('is-clipped')
$(sortModalId).toggleClass('is-active')
})
})
}
showSortModal(that)
}
this.$el.on('sort.bs.table', () => {
isSingleSort = true
})
this.$el.on('multiple-sort.bs.table', () => {
isSingleSort = false
})
this.$el.on('load-success.bs.table', () => {
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object' && that.options.sidePagination !== 'server') {
that.onMultipleSort()
}
})
this.$el.on('column-switch.bs.table', (field, checked) => {
for (let i = 0; i < that.options.sortPriority.length; i++) {
if (that.options.sortPriority[i].sortName === checked) {
that.options.sortPriority.splice(i, 1)
}
}
that.assignSortableArrows()
that.$sortModal.remove()
showSortModal(that)
})
this.$el.on('reset-view.bs.table', () => {
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object') {
that.assignSortableArrows()
}
})
}
}
BootstrapTable.prototype.destroy = function (...args) {
_destroy.apply(this, Array.prototype.slice.apply(args))
if (this.options.showMultiSort) {
this.$sortModal.remove()
}
}
BootstrapTable.prototype.multipleSort = function () {
const that = this
if (!isSingleSort && that.options.sortPriority !== null && typeof that.options.sortPriority === 'object' && that.options.sidePagination !== 'server') {
that.onMultipleSort()
}
}
BootstrapTable.prototype.onMultipleSort = function () {
const that = this
const cmp = (x, y) => x > y ? 1 : x < y ? -1 : 0
const arrayCmp = (a, b) => {
const arr1 = []
const arr2 = []
for (let i = 0; i < that.options.sortPriority.length; i++) {
let fieldName = that.options.sortPriority[i].sortName
const fieldIndex = that.header.fields.indexOf(fieldName)
const sorterName = that.header.sorters[that.header.fields.indexOf(fieldName)]
if (that.header.sortNames[fieldIndex]) {
fieldName = that.header.sortNames[fieldIndex]
}
const order = that.options.sortPriority[i].sortOrder === 'desc' ? -1 : 1
let aa = Utils.getItemField(a, fieldName)
let bb = Utils.getItemField(b, fieldName)
const value1 = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, sorterName, [aa, bb])
const value2 = $.fn.bootstrapTable.utils.calculateObjectValue(that.header, sorterName, [bb, aa])
if (value1 !== undefined && value2 !== undefined) {
arr1.push(order * value1)
arr2.push(order * value2)
continue
}
if (aa === undefined || aa === null) aa = ''
if (bb === undefined || bb === null) bb = ''
if ($.isNumeric(aa) && $.isNumeric(bb)) {
aa = parseFloat(aa)
bb = parseFloat(bb)
} else {
aa = aa.toString()
bb = bb.toString()
if (that.options.multiSortStrictSort) {
aa = aa.toLowerCase()
bb = bb.toLowerCase()
}
}
arr1.push(order * cmp(aa, bb))
arr2.push(order * cmp(bb, aa))
}
return cmp(arr1, arr2)
}
this.data.sort((a, b) => arrayCmp(a, b))
this.initBody()
this.assignSortableArrows()
this.trigger('multiple-sort')
}
BootstrapTable.prototype.addLevel = function (index, sortPriority) {
const text = index === 0 ? this.options.formatSortBy() : this.options.formatThenBy()
this.$sortModal.find('tbody')
.append($('<tr>')
.append($('<td>').text(text))
.append($('<td>').append($(Utils.sprintf(this.constants.html.multipleSortSelect, this.constants.classes.paginationDropdown, 'multi-sort-name'))))
.append($('<td>').append($(Utils.sprintf(this.constants.html.multipleSortSelect, this.constants.classes.paginationDropdown, 'multi-sort-order'))))
)
const $multiSortName = this.$sortModal.find('.multi-sort-name').last()
const $multiSortOrder = this.$sortModal.find('.multi-sort-order').last()
$.each(this.columns, (i, column) => {
if (column.sortable === false || column.visible === false) {
return true
}
$multiSortName.append(`<option value="${column.field}">${column.title}</option>`)
})
$.each(this.options.formatSortOrders(), (value, order) => {
$multiSortOrder.append(`<option value="${value}">${order}</option>`)
})
if (sortPriority !== undefined) {
$multiSortName.find(`option[value="${sortPriority.sortName}"]`).attr('selected', true)
$multiSortOrder.find(`option[value="${sortPriority.sortOrder}"]`).attr('selected', true)
}
}
BootstrapTable.prototype.assignSortableArrows = function () {
const that = this
const headers = that.$header.find('th')
for (let i = 0; i < headers.length; i++) {
for (let c = 0; c < that.options.sortPriority.length; c++) {
if ($(headers[i]).data('field') === that.options.sortPriority[c].sortName) {
$(headers[i]).find('.sortable').removeClass('desc asc').addClass(that.options.sortPriority[c].sortOrder)
}
}
}
}
BootstrapTable.prototype.setButtonStates = function () {
const total = this.$sortModal.find('.multi-sort-name:first option').length
const current = this.$sortModal.find('tbody tr').length
if (current === total) {
this.$sortModal.find('#add').attr('disabled', 'disabled')
}
if (current > 1) {
this.$sortModal.find('#delete').removeAttr('disabled')
}
if (current < total) {
this.$sortModal.find('#add').removeAttr('disabled')
}
if (current === 1) {
this.$sortModal.find('#delete').attr('disabled', 'disabled')
}
}
BootstrapTable.prototype.multiSort = function (sortPriority) {
this.options.sortPriority = sortPriority
this.options.sortName = ''
if (this.options.sidePagination === 'server') {
this.options.queryParams = params => {
params.multiSort = this.options.sortPriority
return $.fn.bootstrapTable.utils.calculateObjectValue(this.options, this.options.queryParams, [params])
}
isSingleSort = false
this.initServer(this.options.silentSort)
return
}
this.onMultipleSort()
}
@@ -0,0 +1,17 @@
{
"name": "Multiple Sort",
"version": "1.1.0",
"description": "Plugin to support the multiple sort.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-sort",
"example": "#",
"plugins": [{
"name": "bootstrap-table-multiple-sort",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/multiple-sort"
}],
"author": {
"name": "dimbslmh",
"image": "https://avatars1.githubusercontent.com/u/745635"
}
}
@@ -0,0 +1,43 @@
/**
* @author Jay <jwang@dizsoft.com>
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
const Utils = $.fn.bootstrapTable.utils
$.extend($.fn.bootstrapTable.defaults, {
showJumpTo: false
})
$.extend($.fn.bootstrapTable.locales, {
formatJumpTo () {
return 'GO'
}
})
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
$.BootstrapTable = class extends $.BootstrapTable {
initPagination (...args) {
super.initPagination(...args)
if (this.options.showJumpTo) {
const $pageGroup = this.$pagination.find('> .pagination')
let $jumpTo = $pageGroup.find('.page-jump-to')
if (!$jumpTo.length) {
$jumpTo = $(`
<div class="page-jump-to ${this.constants.classes.inputGroup}">
<input type="number" class="${this.constants.classes.input}${Utils.sprintf(' input-%s', this.options.iconSize)}" value="${this.options.pageNumber}">
<button class="${this.constants.buttonsClass}" type="button">
${this.options.formatJumpTo()}
</button>
</div>
`).appendTo($pageGroup)
$jumpTo.on('click', 'button', (e) => {
this.selectPage(+$(e.target).parent('.page-jump-to').find('input').val())
})
}
}
}
}
@@ -0,0 +1,11 @@
.bootstrap-table.bootstrap3 .fixed-table-pagination > .pagination ul.pagination,
.bootstrap-table.bootstrap3 .fixed-table-pagination > .pagination .page-jump-to {
display: inline;
}
.bootstrap-table .fixed-table-pagination > .pagination .page-jump-to input {
width: 70px;
margin-left: 5px;
text-align: center;
float: left;
}
@@ -0,0 +1,21 @@
(The MIT License)
Copyright (c) 2019 doug-the-guy <badlydrawnsun@yahoo.com>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
@@ -0,0 +1,92 @@
# Bootstrap Table Pipelining
Use Plugin: [bootstrap-table-pipeline]
This plugin enables client side data caching for server side requests which will
eliminate the need to issue a new request every page change. This will allow
for a performance balance for a large data set between returning all data at once
(client side paging) and a new server side request (server side paging).
There are two new options:
- usePipeline: enables this feature
- pipelineSize: the size of each cache window
The size of the pipeline must be evenly divisible by the current page size. This is
assured by rounding up to the nearest evenly divisible value. For example, if
the pipeline size is 4990 and the current page size is 25, then pipeline size will
be dynamically set to 5000.
The cache windows are computed based on the pipeline size and the total number of rows
returned by the server side query. For example, with pipeline size 500 and total rows
1300, the cache windows will be:
[{'lower': 0, 'upper': 499}, {'lower': 500, 'upper': 999}, {'lower': 1000, 'upper': 1499}]
Using the limit (i.e. the pipelineSize) and offset parameters, the server side request
**MUST** return only the data in the requested cache window **AND** the total number of rows.
To wit, the server side code must use the offset and limit parameters to prepare the response
data.
On a page change, the new offset is checked if it is within the current cache window. If so,
the requested page data is returned from the cached data set. Otherwise, a new server side
request will be issued for the new cache window.
The current cached data is only invalidated on these events:
- sorting
- searching
- page size change
- page change moves into a new cache window
There are two new events:
- cached-data-hit.bs.table: issued when cached data is used on a page change
- cached-data-reset.bs.table: issued when the cached data is invalidated and new server side request is issued
## Features
* Created with Bootstrap 4
## Usage
```
# assumed import of bootstrap and bootstrap-table assets
<script src="/path/to/bootstrap-table-pipeline.js"></script>
...
<table id="pipeline_table"
class="table table-striped"
data-method='post'
data-use-pipeline="true"
data-pipeline-size="5000"
data-pagination="true"
data-side-pagination="server"
data-page-size="50">
<thead><tr>
<th data-field="type" data-sortable="true">Type</th>
<th data-field="value" data-sortable="true">Value</th>
<th data-field="date" data-sortable="true">Date</th>
</tr></thead>
</table>
```
## Options
### usePipeline
* type: Boolean
* description: Set true to enable pipelining
* default: `false`
## pipelineSize
* type: Integer
* description: Size of each cache window. Must be greater than 0
* default: `1000`
## Events
### onCachedDataHit(cached-data-hit.bs.table)
* Fires when paging was able to use the locally cached data.
### onCachedDataReset(cached-data-reset.bs.table)
* Fires when the locally cached data needed to be reset (i.e. on sorting, searching, page size change or paged out of current cache window)
@@ -0,0 +1,320 @@
/**
* @author doug-the-guy
* @version v1.0.0
*
* Bootstrap Table Pipeline
* -----------------------
*
* This plugin enables client side data caching for server side requests which will
* eliminate the need to issue a new request every page change. This will allow
* for a performance balance for a large data set between returning all data at once
* (client side paging) and a new server side request (server side paging).
*
* There are two new options:
* - usePipeline: enables this feature
* - pipelineSize: the size of each cache window
*
* The size of the pipeline must be evenly divisible by the current page size. This is
* assured by rounding up to the nearest evenly divisible value. For example, if
* the pipeline size is 4990 and the current page size is 25, then pipeline size will
* be dynamically set to 5000.
*
* The cache windows are computed based on the pipeline size and the total number of rows
* returned by the server side query. For example, with pipeline size 500 and total rows
* 1300, the cache windows will be:
*
* [{'lower': 0, 'upper': 499}, {'lower': 500, 'upper': 999}, {'lower': 1000, 'upper': 1499}]
*
* Using the limit (i.e. the pipelineSize) and offset parameters, the server side request
* **MUST** return only the data in the requested cache window **AND** the total number of rows.
* To wit, the server side code must use the offset and limit parameters to prepare the response
* data.
*
* On a page change, the new offset is checked if it is within the current cache window. If so,
* the requested page data is returned from the cached data set. Otherwise, a new server side
* request will be issued for the new cache window.
*
* The current cached data is only invalidated on these events:
* * sorting
* * searching
* * page size change
* * page change moves into a new cache window
*
* There are two new events:
* - cached-data-hit.bs.table: issued when cached data is used on a page change
* - cached-data-reset.bs.table: issued when the cached data is invalidated and a
* new server side request is issued
*
**/
const Utils = $.fn.bootstrapTable.utils
$.extend($.fn.bootstrapTable.defaults, {
usePipeline: false,
pipelineSize: 1000,
onCachedDataHit (data) {
return false
},
onCachedDataReset (data) {
return false
}
})
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'cached-data-hit.bs.table': 'onCachedDataHit',
'cached-data-reset.bs.table': 'onCachedDataReset'
})
const BootstrapTable = $.fn.bootstrapTable.Constructor
const _init = BootstrapTable.prototype.init
const _initServer = BootstrapTable.prototype.initServer
const _onSearch = BootstrapTable.prototype.onSearch
const _onSort = BootstrapTable.prototype.onSort
const _onPageListChange = BootstrapTable.prototype.onPageListChange
BootstrapTable.prototype.init = function (...args) {
// needs to be called before initServer()
this.initPipeline()
_init.apply(this, Array.prototype.slice.apply(args))
}
BootstrapTable.prototype.initPipeline = function () {
this.cacheRequestJSON = {}
this.cacheWindows = []
this.currWindow = 0
this.resetCache = true
}
BootstrapTable.prototype.onSearch = function (event) {
/* force a cache reset on search */
if (this.options.usePipeline) {
this.resetCache = true
}
_onSearch.apply(this, Array.prototype.slice.apply(arguments))
}
BootstrapTable.prototype.onSort = function (event) {
/* force a cache reset on sort */
if (this.options.usePipeline) {
this.resetCache = true
}
_onSort.apply(this, Array.prototype.slice.apply(arguments))
}
BootstrapTable.prototype.onPageListChange = function (event) {
/* rebuild cache window on page size change */
const target = $(event.currentTarget)
const newPageSize = parseInt(target.text())
this.options.pipelineSize = this.calculatePipelineSize(this.options.pipelineSize, newPageSize)
this.resetCache = true
_onPageListChange.apply(this, Array.prototype.slice.apply(arguments))
}
BootstrapTable.prototype.calculatePipelineSize = (pipelineSize, pageSize) => {
/* calculate pipeline size by rounding up to the nearest value evenly divisible
* by the pageSize */
if (pageSize === 0) return 0
return Math.ceil(pipelineSize / pageSize) * pageSize
}
BootstrapTable.prototype.setCacheWindows = function () {
/* set cache windows based on the total number of rows returned by server side
* request and the pipelineSize */
this.cacheWindows = []
const numWindows = this.options.totalRows / this.options.pipelineSize
for (let i = 0; i <= numWindows; i++) {
const b = i * this.options.pipelineSize
this.cacheWindows[i] = {'lower': b, 'upper': b + this.options.pipelineSize - 1}
}
}
BootstrapTable.prototype.setCurrWindow = function (offset) {
/* set the current cache window index, based on where the current offset falls */
this.currWindow = 0
for (let i = 0; i < this.cacheWindows.length; i++) {
if (this.cacheWindows[i].lower <= offset && offset <= this.cacheWindows[i].upper) {
this.currWindow = i
break
}
}
}
BootstrapTable.prototype.drawFromCache = function (offset, limit) {
/* draw rows from the cache using offset and limit */
const res = $.extend(true, {}, this.cacheRequestJSON)
const drawStart = offset - this.cacheWindows[this.currWindow].lower
const drawEnd = drawStart + limit
res.rows = res.rows.slice(drawStart, drawEnd)
return res
}
BootstrapTable.prototype.initServer = function (silent, query, url) {
/* determine if requested data is in cache (on paging) or if
* a new ajax request needs to be issued (sorting, searching, paging
* moving outside of cached data, page size change)
* initial version of this extension will entirely override base initServer
**/
let data = {}
const index = this.header.fields.indexOf(this.options.sortName)
let params = {
searchText: this.searchText,
sortName: this.options.sortName,
sortOrder: this.options.sortOrder
}
let request = null
if (this.header.sortNames[index]) {
params.sortName = this.header.sortNames[index]
}
if (this.options.pagination && this.options.sidePagination === 'server') {
params.pageSize = this.options.pageSize === this.options.formatAllRows()
? this.options.totalRows : this.options.pageSize
params.pageNumber = this.options.pageNumber
}
if (!(url || this.options.url) && !this.options.ajax) {
return
}
let useAjax = true
if (this.options.queryParamsType === 'limit') {
params = {
searchText: params.searchText,
sortName: params.sortName,
sortOrder: params.sortOrder
}
if (this.options.pagination && this.options.sidePagination === 'server') {
params.limit = this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize
params.offset = (this.options.pageSize === this.options.formatAllRows() ? this.options.totalRows : this.options.pageSize) * (this.options.pageNumber - 1)
if (this.options.usePipeline) {
// if cacheWindows is empty, this is the initial request
if (!this.cacheWindows.length) {
useAjax = true
params.drawOffset = params.offset
// cache exists: determine if the page request is entirely within the current cached window
} else {
const w = this.cacheWindows[this.currWindow]
// case 1: reset cache but stay within current window (e.g. column sort)
// case 2: move outside of the current window (e.g. search or paging)
// since each cache window is aligned with the current page size
// checking if params.offset is outside the current window is sufficient.
// need to requery for preceding or succeeding cache window
// also handle case
if (this.resetCache || (params.offset < w.lower || params.offset > w.upper)) {
useAjax = true
this.setCurrWindow(params.offset)
// store the relative offset for drawing the page data afterwards
params.drawOffset = params.offset
// now set params.offset to the lower bound of the new cache window
// the server will return that whole cache window
params.offset = this.cacheWindows[this.currWindow].lower
// within current cache window
} else {
useAjax = false
}
}
} else {
if (params.limit === 0) {
delete params.limit
}
}
}
}
// force an ajax call - this is on search, sort or page size change
if (this.resetCache) {
useAjax = true
this.resetCache = false
}
if (this.options.usePipeline && useAjax) {
/* in this scenario limit is used on the server to get the cache window
* and drawLimit is used to get the page data afterwards */
params.drawLimit = params.limit
params.limit = this.options.pipelineSize
}
// cached results can be used
if (!useAjax) {
const res = this.drawFromCache(params.offset, params.limit)
this.load(res)
this.trigger('load-success', res)
this.trigger('cached-data-hit', res)
return
}
// cached results can't be used
// continue base initServer code
if (!($.isEmptyObject(this.filterColumnsPartial))) {
params.filter = JSON.stringify(this.filterColumnsPartial, null)
}
data = Utils.calculateObjectValue(this.options, this.options.queryParams, [params], data)
$.extend(data, query || {})
// false to stop request
if (data === false) {
return
}
if (!silent) {
this.$tableLoading.show()
}
const self = this
request = $.extend({}, Utils.calculateObjectValue(null, this.options.ajaxOptions), {
type: this.options.method,
url: url || this.options.url,
data: this.options.contentType === 'application/json' && this.options.method === 'post'
? JSON.stringify(data) : data,
cache: this.options.cache,
contentType: this.options.contentType,
dataType: this.options.dataType,
success (res) {
res = Utils.calculateObjectValue(self.options, self.options.responseHandler, [res], res)
// cache results if using pipelining
if (self.options.usePipeline) {
// store entire request in cache
self.cacheRequestJSON = $.extend(true, {}, res)
// this gets set in load() also but needs to be set before
// setting cacheWindows
self.options.totalRows = res[self.options.totalField]
// if this is a search, potentially less results will be returned
// so cache windows need to be rebuilt. Otherwise it
// will come out the same
self.setCacheWindows()
self.setCurrWindow(params.drawOffset)
// just load data for the page
res = self.drawFromCache(params.drawOffset, params.drawLimit)
self.trigger('cached-data-reset', res)
}
self.load(res)
self.trigger('load-success', res)
if (!silent) self.$tableLoading.hide()
},
error (res) {
let data = []
if (self.options.sidePagination === 'server') {
data = {}
data[self.options.totalField] = 0
data[self.options.dataField] = []
}
self.load(data)
self.trigger('load-error', res.status, res)
if (!silent) self.$tableLoading.hide()
}
})
if (this.options.ajax) {
Utils.calculateObjectValue(this, this.options.ajax, [request], null)
} else {
if (this._xhr && this._xhr.readyState !== 4) {
this._xhr.abort()
}
this._xhr = $.ajax(request)
}
}
@@ -0,0 +1,18 @@
{
"name": "Pipeline",
"version": "1.0.0",
"description": "Plugin to support a hybrid approach to server/client side paging.",
"url": "",
"example": "#",
"plugins": [{
"name": "bootstrap-table-pipeline",
"url": ""
}],
"author": {
"name": "doug-the-guy",
"image": ""
}
}
@@ -0,0 +1,181 @@
/**
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
const Utils = $.fn.bootstrapTable.utils
function printPageBuilderDefault (table) {
return `
<html>
<head>
<style type="text/css" media="print">
@page {
size: auto;
margin: 25px 0 25px 0;
}
</style>
<style type="text/css" media="all">
table {
border-collapse: collapse;
font-size: 12px;
}
table, th, td {
border: 1px solid grey;
}
th, td {
text-align: center;
vertical-align: middle;
}
p {
font-weight: bold;
margin-left:20px;
}
table {
width:94%;
margin-left:3%;
margin-right:3%;
}
div.bs-table-print {
text-align:center;
}
</style>
</head>
<title>Print Table</title>
<body>
<p>Printed on: ${new Date} </p>
<div class="bs-table-print">${table}</div>
</body>
</html>`
}
$.extend($.fn.bootstrapTable.defaults, {
showPrint: false,
printAsFilteredAndSortedOnUI: true,
printSortColumn: undefined,
printSortOrder: 'asc',
printPageBuilder (table) {
return printPageBuilderDefault(table)
}
})
$.extend($.fn.bootstrapTable.COLUMN_DEFAULTS, {
printFilter: undefined,
printIgnore: false,
printFormatter: undefined
})
$.extend($.fn.bootstrapTable.defaults.icons, {
print: {
bootstrap3: 'glyphicon-print icon-share'
}[$.fn.bootstrapTable.theme] || 'fa-print'
})
$.BootstrapTable = class extends $.BootstrapTable {
initToolbar (...args) {
this.showToolbar = this.showToolbar || this.options.showPrint
super.initToolbar(...args)
if (!this.options.showPrint) {
return
}
const $btnGroup = this.$toolbar.find('>.columns')
let $print = $btnGroup.find('button.bs-print')
if (!$print.length) {
$print = $(`
<button class="${this.constants.buttonsClass} bs-print" type="button">
<i class="${this.options.iconsPrefix} ${this.options.icons.print}"></i>
</button>`
).appendTo($btnGroup)
}
$print.off('click').on('click', () => {
this.doPrint(this.options.printAsFilteredAndSortedOnUI ?
this.getData() : this.options.data.slice(0))
})
}
doPrint (data) {
const formatValue = (row, i, column ) => {
const value = Utils.calculateObjectValue(column, column.printFormatter,
[row[column.field], row, i], row[column.field])
return typeof value === 'undefined' || value === null
? this.options.undefinedText : value
}
const buildTable = (data, columnsArray) => {
const dir = this.$el.attr('dir') || 'ltr'
const html = [`<table dir="${dir}"><thead>`]
for (const columns of columnsArray) {
html.push('<tr>')
for (let h = 0; h < columns.length; h++) {
if (!columns[h].printIgnore) {
html.push(
`<th
${Utils.sprintf(' rowspan="%s"', columns[h].rowspan)}
${Utils.sprintf(' colspan="%s"', columns[h].colspan)}
>${columns[h].title}</th>`)
}
}
html.push('</tr>')
}
html.push('</thead><tbody>')
for (let i = 0; i < data.length; i++) {
html.push('<tr>')
for (const columns of columnsArray) {
for (let j = 0; j < columns.length; j++) {
if (!columns[j].printIgnore && columns[j].field) {
html.push('<td>', formatValue(data[i], i, columns[j]), '</td>')
}
}
}
html.push('</tr>')
}
html.push('</tbody></table>')
return html.join('')
}
const sortRows = (data, colName, sortOrder) => {
if (!colName) {
return data
}
let reverse = sortOrder !== 'asc'
reverse = -((+reverse) || -1)
return data.sort((a, b) => reverse * (a[colName].localeCompare(b[colName])))
}
const filterRow = (row, filters) => {
for (let index = 0; index < filters.length; ++index) {
if (row[filters[index].colName] !== filters[index].value) {
return false
}
}
return true
}
const filterRows = (data, filters) => data.filter(row => filterRow(row,filters))
const getColumnFilters = columns => !columns || !columns[0] ? [] : columns[0].filter(col => col.printFilter).map(col => ({
colName: col.field,
value: col.printFilter
}))
data = filterRows(data,getColumnFilters(this.options.columns))
data = sortRows(data, this.options.printSortColumn, this.options.printSortOrder)
const table = buildTable(data, this.options.columns)
const newWin = window.open('')
newWin.document.write(this.options.printPageBuilder.call(this, table))
newWin.document.close()
newWin.focus()
newWin.print()
newWin.close()
}
}
@@ -0,0 +1,199 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @update: https://github.com/wenzhixin
* @version: v1.2.0
*/
$.akottr.dragtable.prototype._restoreState = function (persistObj) {
for (const [field, value] of Object.entries(persistObj)) {
var $th = this.originalTable.el.find(`th[data-field="${field}"]`)
this.originalTable.startIndex = $th.prevAll().length + 1
this.originalTable.endIndex = parseInt(value, 10) + 1
this._bubbleCols()
}
}
// From MDN site, https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
const filterFn = () => {
if (!Array.prototype.filter) {
Array.prototype.filter = function (fun/* , thisArg*/) {
if (this === undefined || this === null) {
throw new TypeError()
}
const t = Object(this)
const len = t.length >>> 0
if (typeof fun !== 'function') {
throw new TypeError()
}
const res = []
const thisArg = arguments.length >= 2 ? arguments[1] : undefined
for (let i = 0; i < len; i++) {
if (i in t) {
const val = t[i]
// NOTE: Technically this should Object.defineProperty at
// the next index, as push can be affected by
// properties on Object.prototype and Array.prototype.
// But this method's new, and collisions should be
// rare, so use the more-compatible alternative.
if (fun.call(thisArg, val, i, t)) {
res.push(val)
}
}
}
return res
}
}
}
$.extend($.fn.bootstrapTable.defaults, {
reorderableColumns: false,
maxMovingRows: 10,
onReorderColumn (headerFields) {
return false
},
dragaccept: null
})
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'reorder-column.bs.table': 'onReorderColumn'
})
$.fn.bootstrapTable.methods.push('orderColumns')
$.BootstrapTable = class extends $.BootstrapTable {
initHeader (...args) {
super.initHeader(...args)
if (!this.options.reorderableColumns) {
return
}
this.makeRowsReorderable()
}
_toggleColumn (...args) {
super._toggleColumn(...args)
if (!this.options.reorderableColumns) {
return
}
this.makeRowsReorderable()
}
toggleView (...args) {
super.toggleView(...args)
if (!this.options.reorderableColumns) {
return
}
if (this.options.cardView) {
return
}
this.makeRowsReorderable()
}
resetView (...args) {
super.resetView(...args)
if (!this.options.reorderableColumns) {
return
}
this.makeRowsReorderable()
}
makeRowsReorderable (order = null) {
try {
$(this.$el).dragtable('destroy')
} catch (e) {
// do nothing
}
$(this.$el).dragtable({
maxMovingRows: this.options.maxMovingRows,
dragaccept: this.options.dragaccept,
clickDelay: 200,
dragHandle: '.th-inner',
restoreState: order ? order : this.columnsSortOrder,
beforeStop: (table) => {
const sortOrder = {}
table.el.find('th').each((i, el) => {
sortOrder[$(el).data('field')] = i
})
this.columnsSortOrder = sortOrder
if (this.options.cookie) {
this.persistReorderColumnsState(this)
}
const ths = []
const formatters = []
const columns = []
let columnsHidden = []
let columnIndex = -1
const optionsColumns = []
this.$header.find('th:not(.detail)').each(function (i) {
ths.push($(this).data('field'))
formatters.push($(this).data('formatter'))
})
// Exist columns not shown
if (ths.length < this.columns.length) {
columnsHidden = this.columns.filter(column => !column.visible)
for (var i = 0; i < columnsHidden.length; i++) {
ths.push(columnsHidden[i].field)
formatters.push(columnsHidden[i].formatter)
}
}
for (let i = 0; i < ths.length; i++) {
columnIndex = this.fieldsColumnsIndex[ths[i]]
if (columnIndex !== -1) {
this.fieldsColumnsIndex[ths[i]] = i
this.columns[columnIndex].fieldIndex = i
columns.push(this.columns[columnIndex])
}
}
this.columns = columns
filterFn() // Support <IE9
$.each(this.columns, (i, column) => {
let found = false
const field = column.field
this.options.columns[0].filter(item => {
if (!found && item['field'] === field) {
optionsColumns.push(item)
found = true
return false
}
return true
})
})
this.options.columns[0] = optionsColumns
this.header.fields = ths
this.header.formatters = formatters
this.initHeader()
this.initToolbar()
this.initSearchText()
this.initBody()
this.resetView()
this.trigger('reorder-column', ths)
}
})
}
orderColumns (order) {
this.columnsSortOrder = order
this.makeRowsReorderable()
}
}
@@ -0,0 +1,17 @@
{
"name": "Reorder Columns",
"version": "1.1.0",
"description": "Plugin to support the reordering columns feature.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-columns",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/reorder-columns.html",
"plugins": [{
"name": "bootstrap-table-reorder-columns",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-columns"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}
@@ -0,0 +1,95 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
const rowAttr = (row, index) => ({
id: `customId_${index}`
})
$.extend($.fn.bootstrapTable.defaults, {
reorderableRows: false,
onDragStyle: null,
onDropStyle: null,
onDragClass: 'reorder_rows_onDragClass',
dragHandle: '>tbody>tr>td',
useRowAttrFunc: false,
onReorderRowsDrag (row) {
return false
},
onReorderRowsDrop (row) {
return false
},
onReorderRow (newData) {
return false
}
})
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'reorder-row.bs.table': 'onReorderRow'
})
$.BootstrapTable = class extends $.BootstrapTable {
init (...args) {
if (!this.options.reorderableRows) {
super.init(...args)
return
}
if (this.options.useRowAttrFunc) {
this.options.rowAttributes = rowAttr
}
const onPostBody = this.options.onPostBody
this.options.onPostBody = () => {
setTimeout(() => {
this.makeRowsReorderable()
onPostBody.call(this.options, this.options.data)
}, 1)
}
super.init(...args)
}
makeRowsReorderable () {
this.$el.tableDnD({
onDragStyle: this.options.onDragStyle,
onDropStyle: this.options.onDropStyle,
onDragClass: this.options.onDragClass,
onDragStart: (table, droppedRow) => this.onDropStart(table, droppedRow),
onDrop: (table, droppedRow) => this.onDrop(table, droppedRow),
dragHandle: this.options.dragHandle
})
}
onDropStart (table, draggingTd) {
this.$draggingTd = $(draggingTd).css('cursor', 'move')
this.draggingIndex = $(this.$draggingTd.parent()).data('index')
// Call the user defined function
this.options.onReorderRowsDrag(this.data[this.draggingIndex])
}
onDrop (table) {
this.$draggingTd.css('cursor', '')
const newData = []
for (let i = 0; i < table.tBodies[0].rows.length; i++) {
const $tr = $(table.tBodies[0].rows[i])
newData.push(this.data[$tr.data('index')])
$tr.data('index', i)
}
const draggingRow = this.data[this.draggingIndex]
const droppedIndex = newData.indexOf(this.data[this.draggingIndex])
const droppedRow = this.data[droppedIndex]
const index = this.options.data.indexOf(this.data[droppedIndex])
this.options.data.splice(this.options.data.indexOf(draggingRow), 1)
this.options.data.splice(index, 0, draggingRow)
// Call the user defined function
this.options.onReorderRowsDrop(droppedRow)
// Call the event reorder-row
this.trigger('reorder-row', newData)
}
}
@@ -0,0 +1,14 @@
.reorder_rows_onDragClass td {
background-color: #eee;
-webkit-box-shadow: 11px 5px 12px 2px #333, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-webkit-box-shadow: 6px 3px 5px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-moz-box-shadow: 6px 4px 5px 1px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-box-shadow: 6px 4px 5px 1px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
}
.reorder_rows_onDragClass td:last-child {
-webkit-box-shadow: 8px 7px 12px 0 #333, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-webkit-box-shadow: 1px 8px 6px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset;
-moz-box-shadow: 0 9px 4px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset, -1px 0 0 #ccc inset;
-box-shadow: 0 9px 4px -4px #555, 0 1px 0 #ccc inset, 0 -1px 0 #ccc inset, -1px 0 0 #ccc inset;
}
@@ -0,0 +1,17 @@
{
"name": "Reorder Rows",
"version": "1.0.0",
"description": "Plugin to support the reordering rows feature.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-rows",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/reorder-rows.html",
"plugins": [{
"name": "bootstrap-table-reorder-rows",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/reorder-rows"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}
@@ -0,0 +1,68 @@
/**
* @author: Dennis Hernández
* @webSite: http://djhvscf.github.io/Blog
* @version: v2.0.0
*/
const isInit = that => that.$el.data('resizableColumns') !== undefined
const initResizable = that => {
if (that.options.resizable && !that.options.cardView && !isInit(that)) {
that.$el.resizableColumns({
store: window.store
})
}
}
const destroy = that => {
if (isInit(that)) {
that.$el.data('resizableColumns').destroy()
}
}
const reInitResizable = that => {
destroy(that)
initResizable(that)
}
$.extend($.fn.bootstrapTable.defaults, {
resizable: false
})
const BootstrapTable = $.fn.bootstrapTable.Constructor
const _initBody = BootstrapTable.prototype.initBody
const _toggleView = BootstrapTable.prototype.toggleView
const _resetView = BootstrapTable.prototype.resetView
BootstrapTable.prototype.initBody = function (...args) {
const that = this
_initBody.apply(this, Array.prototype.slice.apply(args))
that.$el
.off('column-switch.bs.table page-change.bs.table')
.on('column-switch.bs.table page-change.bs.table', () => {
reInitResizable(that)
})
}
BootstrapTable.prototype.toggleView = function (...args) {
_toggleView.apply(this, Array.prototype.slice.apply(args))
if (this.options.resizable && this.options.cardView) {
// Destroy the plugin
destroy(this)
}
}
BootstrapTable.prototype.resetView = function (...args) {
const that = this
_resetView.apply(this, Array.prototype.slice.apply(args))
if (this.options.resizable) {
// because in fitHeader function, we use setTimeout(func, 100);
setTimeout(() => {
initResizable(that)
}, 100)
}
}
@@ -0,0 +1,17 @@
{
"name": "Resizable",
"version": "1.1.0",
"description": "Plugin to support the resizable feature.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/resizable",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/resizable.html",
"plugins": [{
"name": "bootstrap-table-resizable",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/resizable"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}
@@ -0,0 +1,119 @@
/**
* @author vincent loh <vincent.ml@gmail.com>
* @update J Manuel Corona <jmcg92@gmail.com>
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
const Utils = $.fn.bootstrapTable.utils
$.extend($.fn.bootstrapTable.defaults, {
stickyHeader: false,
stickyHeaderOffsetY: 0,
stickyHeaderOffsetLeft: 0,
stickyHeaderOffsetRight: 0
})
$.BootstrapTable = class extends $.BootstrapTable {
initHeader (...args) {
super.initHeader(...args)
if (!this.options.stickyHeader) {
return
}
this.$tableBody.find('.sticky-header-container,.sticky_anchor_begin,.sticky_anchor_end').remove()
this.$el.before('<div class="sticky-header-container"></div>')
this.$el.before('<div class="sticky_anchor_begin"></div>')
this.$el.after('<div class="sticky_anchor_end"></div>')
this.$header.addClass('sticky-header')
// clone header just once, to be used as sticky header
// deep clone header, using source header affects tbody>td width
this.$stickyContainer = this.$tableBody.find('.sticky-header-container')
this.$stickyBegin = this.$tableBody.find('.sticky_anchor_begin')
this.$stickyEnd = this.$tableBody.find('.sticky_anchor_end')
this.$stickyHeader = this.$header.clone(true, true)
// render sticky on window scroll or resize
$(window).off('resize.sticky-header-table')
.on('resize.sticky-header-table', () => this.renderStickyHeader())
$(window).off('scroll.sticky-header-table')
.on('scroll.sticky-header-table', () => this.renderStickyHeader())
this.$tableBody.off('scroll').on('scroll', () => this.matchPositionX())
}
onColumnSearch ({currentTarget, keyCode}) {
super.onColumnSearch({currentTarget, keyCode})
this.renderStickyHeader()
}
resetView (...args) {
super.resetView(...args)
$('.bootstrap-table.fullscreen').off('scroll')
.on('scroll', () => this.renderStickyHeader())
}
renderStickyHeader () {
const that = this
this.$stickyHeader = this.$header.clone(true, true)
if (this.options.filterControl) {
$(this.$stickyHeader).off('keyup change mouseup').on('keyup change mouse', function (e) {
const $target = $(e.target)
const value = $target.val()
const field = $target.parents('th').data('field')
const $coreTh = that.$header.find('th[data-field="' + field + '"]')
if ($target.is('input')) {
$coreTh.find('input').val(value)
} else if ($target.is('select')) {
const $select = $coreTh.find('select')
$select.find('option[selected]').removeAttr('selected')
$select.find('option[value="' + value + '"]').attr('selected', true)
}
that.triggerSearch()
})
}
const top = $(window).scrollTop()
// top anchor scroll position, minus header height
const start = this.$stickyBegin.offset().top - this.options.stickyHeaderOffsetY
// bottom anchor scroll position, minus header height, minus sticky height
const end = this.$stickyEnd.offset().top - this.options.stickyHeaderOffsetY - this.$header.height()
// show sticky when top anchor touches header, and when bottom anchor not exceeded
if (top > start && top <= end) {
// ensure clone and source column widths are the same
this.$stickyHeader.find('tr:eq(0)').find('th').each((index, el) => {
$(el).css('min-width', this.$header.find('tr:eq(0)').find('th').eq(index).css('width'))
})
// match bootstrap table style
this.$stickyContainer.show().addClass('fix-sticky fixed-table-container')
// stick it in position
let stickyHeaderOffsetLeft = this.options.stickyHeaderOffsetLeft
let stickyHeaderOffsetRight = this.options.stickyHeaderOffsetRight
if (this.$el.closest('.bootstrap-table').hasClass('fullscreen')) {
stickyHeaderOffsetLeft = 0
stickyHeaderOffsetRight = 0
}
this.$stickyContainer.css('top', `${this.options.stickyHeaderOffsetY}`)
this.$stickyContainer.css('left', `${stickyHeaderOffsetLeft}`)
this.$stickyContainer.css('right', `${stickyHeaderOffsetRight}`)
// create scrollable container for header
this.$stickyTable = $('<table/>')
this.$stickyTable.addClass(this.options.classes)
// append cloned header to dom
this.$stickyContainer.html(this.$stickyTable.append(this.$stickyHeader))
// match clone and source header positions when left-right scroll
this.matchPositionX()
} else {
this.$stickyContainer.removeClass('fix-sticky').hide()
}
}
matchPositionX () {
this.$stickyContainer.scrollLeft(this.$tableBody.scrollLeft())
}
}
@@ -0,0 +1,22 @@
/**
* @author vincent loh <vincent.ml@gmail.com>
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
.fix-sticky {
position: fixed !important;
overflow: hidden;
z-index: 100;
}
.fix-sticky table thead {
background: #fff;
}
.fix-sticky table thead.thead-light {
background: #e9ecef;
}
.fix-sticky table thead.thead-dark {
background: #212529;
}
@@ -0,0 +1,17 @@
{
"name": "Sticky Header",
"version": "1.0.0",
"description": "An extension which provides a sticky header for table columns when scrolling on a long page and / or table. Works for tables with many columns and narrow width with horizontal scrollbars too.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/sticky-header",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/sticky-header.html",
"plugins": [{
"name": "bootstrap-table-sticky-header",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/sticky-header"
}],
"author": {
"name": "vinzloh",
"image": "https://avatars0.githubusercontent.com/u/5501845"
}
}
@@ -0,0 +1,360 @@
/**
* @author: aperez <aperez@datadec.es>
* @version: v2.0.0
*
* @update Dennis Hernández <http://djhvscf.github.io/Blog>
* @update zhixin wen <wenzhixin2010@gmail.com>
*/
const Utils = $.fn.bootstrapTable.utils
const bootstrap = {
bootstrap3: {
icons: {
advancedSearchIcon: 'glyphicon-chevron-down'
},
html: {
modal: `
<div id="avdSearchModal_%s" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xs">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">%s</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body modal-body-custom">
<div class="container-fluid" id="avdSearchModalContent_%s"
style="padding-right: 0px; padding-left: 0px;" >
</div>
</div>
<div class="modal-footer">
<button type="button" id="btnCloseAvd_%s" class="btn btn-%s">%s</button>
</div>
</div>
</div>
</div>
`
}
},
bootstrap4: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
html: {
modal: `
<div id="avdSearchModal_%s" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xs">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">%s</h4>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body modal-body-custom">
<div class="container-fluid" id="avdSearchModalContent_%s"
style="padding-right: 0px; padding-left: 0px;" >
</div>
</div>
<div class="modal-footer">
<button type="button" id="btnCloseAvd_%s" class="btn btn-%s">%s</button>
</div>
</div>
</div>
</div>
`
}
},
bulma: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
html: {
modal: `
<div class="modal" id="avdSearchModal_%s">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">%s</p>
<button class="delete" aria-label="close"></button>
</header>
<section class="modal-card-body" id="avdSearchModalContent_%s"></section>
<footer class="modal-card-foot">
<button class="button" id="btnCloseAvd_%s" data-close="btn btn-%s">%s</button>
</footer>
</div>
</div>
`
}
},
foundation: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
html: {
modal: `
<div class="reveal" id="avdSearchModal_%s" data-reveal>
<h1>%s</h1>
<div id="avdSearchModalContent_%s">
</div>
<button class="close-button" data-close aria-label="Close modal" type="button">
<span aria-hidden="true">&times;</span>
</button>
<button id="btnCloseAvd_%s" class="%s" type="button">%s</button>
</div>
`
}
},
materialize: {
icons: {
advancedSearchIcon: 'expand_more'
},
html: {
modal: `
<div id="avdSearchModal_%s" class="modal">
<div class="modal-content">
<h4>%s</h4>
<div id="avdSearchModalContent_%s">
</div>
</div>
<div class="modal-footer">
<a href="javascript:void(0)"" id="btnCloseAvd_%s" class="modal-close waves-effect waves-green btn-flat %s">%s</a>
</div>
</div>
`
}
},
semantic: {
icons: {
advancedSearchIcon: 'fa-chevron-down'
},
html: {
modal: `
<div class="ui modal" id="avdSearchModal_%s">
<i class="close icon"></i>
<div class="header">
%s
</div>
<div class="image content ui form" id="avdSearchModalContent_%s"></div>
<div class="actions">
<div id="btnCloseAvd_%s" class="ui black deny button %s">%s</div>
</div>
</div>
`
}
}
}[$.fn.bootstrapTable.theme]
$.extend($.fn.bootstrapTable.defaults, {
advancedSearch: false,
idForm: 'advancedSearch',
actionForm: '',
idTable: undefined,
onColumnAdvancedSearch (field, text) {
return false
}
})
$.extend($.fn.bootstrapTable.defaults.icons, {
advancedSearchIcon: bootstrap.icons.advancedSearchIcon
})
$.extend($.fn.bootstrapTable.Constructor.EVENTS, {
'column-advanced-search.bs.table': 'onColumnAdvancedSearch'
})
$.extend($.fn.bootstrapTable.locales, {
formatAdvancedSearch () {
return 'Advanced search'
},
formatAdvancedCloseButton () {
return 'Close'
}
})
$.extend($.fn.bootstrapTable.defaults, $.fn.bootstrapTable.locales)
$.BootstrapTable = class extends $.BootstrapTable {
initToolbar () {
const o = this.options
this.showToolbar = this.showToolbar ||
(o.search &&
o.advancedSearch &&
o.idTable)
super.initToolbar()
if (!o.search || !o.advancedSearch || !o.idTable) {
return
}
this.$toolbar.find('>.columns').append(`
<button class="${this.constants.buttonsClass} "
type="button"
name="advancedSearch"
aria-label="advanced search"
title="${o.formatAdvancedSearch()}">
${ this.options.showButtonIcons ? Utils.sprintf(this.constants.html.icon, o.iconsPrefix, o.icons.advancedSearchIcon) : ''}
${ this.options.showButtonText ? this.options.formatAdvancedSearch() : ''}
</button>
`)
this.$toolbar.find('button[name="advancedSearch"]').off('click').on('click', () => this.showAvdSearch())
}
showAvdSearch () {
const o = this.options
const modalSelector = '#avdSearchModal_' + o.idTable
if ($(modalSelector).length <= 0) {
$('body').append(Utils.sprintf(bootstrap.html.modal, o.idTable, o.formatAdvancedSearch(), o.idTable, o.idTable, o.buttonsClass, o.formatAdvancedCloseButton()))
let timeoutId = 0
$(`#avdSearchModalContent_${o.idTable}`).append(this.createFormAvd().join(''))
$(`#${o.idForm}`).off('keyup blur', 'input').on('keyup blur', 'input', e => {
if (o.sidePagination === 'server') {
this.onColumnAdvancedSearch(e)
} else {
clearTimeout(timeoutId)
timeoutId = setTimeout(() => {
this.onColumnAdvancedSearch(e)
}, o.searchTimeOut)
}
})
$(`#btnCloseAvd_${o.idTable}`).click(() => this.hideModal())
if ($.fn.bootstrapTable.theme === 'bulma') {
$(modalSelector).find('.delete').off('click').on('click', () => this.hideModal())
}
this.showModal()
} else {
this.showModal()
}
}
showModal () {
const modalSelector = '#avdSearchModal_' + this.options.idTable
if ($.inArray($.fn.bootstrapTable.theme, ['bootstrap3', 'bootstrap4']) !== -1) {
$(modalSelector).modal()
} else if ($.fn.bootstrapTable.theme === 'bulma') {
$(modalSelector).toggleClass('is-active')
} else if ($.fn.bootstrapTable.theme === 'foundation') {
if (!this.toolbarModal) {
// eslint-disable-next-line no-undef
this.toolbarModal = new Foundation.Reveal($(modalSelector))
}
this.toolbarModal.open()
} else if ($.fn.bootstrapTable.theme === 'materialize') {
$(modalSelector).modal()
$(modalSelector).modal('open')
} else if ($.fn.bootstrapTable.theme === 'semantic') {
$(modalSelector).modal('show')
}
}
hideModal () {
const $closeModalButton = $(`#avdSearchModal_${this.options.idTable}`)
const modalSelector = '#avdSearchModal_' + this.options.idTable
if ($.inArray($.fn.bootstrapTable.theme, ['bootstrap3', 'bootstrap4']) !== -1) {
$closeModalButton.modal('hide')
} else if ($.fn.bootstrapTable.theme === 'bulma') {
$('html').toggleClass('is-clipped')
$(modalSelector).toggleClass('is-active')
} else if ($.fn.bootstrapTable.theme === 'foundation') {
this.toolbarModal.close()
} else if ($.fn.bootstrapTable.theme === 'materialize') {
$(modalSelector).modal('open')
} else if ($.fn.bootstrapTable.theme === 'semantic') {
$(modalSelector).modal('close')
}
if (this.options.sidePagination === 'server') {
this.options.pageNumber = 1
this.updatePagination()
this.trigger('column-advanced-search', this.filterColumnsPartial)
}
}
createFormAvd () {
const o = this.options
const html = [`<form class="form-horizontal" id="${o.idForm}" action="${o.actionForm}">`]
for (const column of this.columns) {
if (!column.checkbox && column.visible && column.searchable) {
html.push(`
<div class="form-group row">
<label class="col-sm-4 control-label">${column.title}</label>
<div class="col-sm-6">
<input type="text" class="form-control ${this.constants.classes.input}" name="${column.field}" placeholder="${column.title}" id="${column.field}">
</div>
</div>
`)
}
}
html.push('</form>')
return html
}
initSearch () {
super.initSearch()
if (!this.options.advancedSearch || this.options.sidePagination === 'server') {
return
}
const fp = $.isEmptyObject(this.filterColumnsPartial) ? null : this.filterColumnsPartial
this.data = fp ? this.data.filter((item, i) => {
for (const [key, v] of Object.entries(fp)) {
const fval = v.toLowerCase()
let value = item[key]
const index = this.header.fields.indexOf(key)
value = Utils.calculateObjectValue(this.header,
this.header.formatters[index], [value, item, i], value)
if (
!(index !== -1 &&
(typeof value === 'string' || typeof value === 'number') &&
(`${value}`).toLowerCase().includes(fval))
) {
return false
}
}
return true
}) : this.data
}
onColumnAdvancedSearch (e) {
const text = $.trim($(e.currentTarget).val())
const $field = $(e.currentTarget)[0].id
if ($.isEmptyObject(this.filterColumnsPartial)) {
this.filterColumnsPartial = {}
}
if (text) {
this.filterColumnsPartial[$field] = text
} else {
delete this.filterColumnsPartial[$field]
}
if (this.options.sidePagination !== 'server') {
this.options.pageNumber = 1
this.onSearch(e)
this.updatePagination()
this.trigger('column-advanced-search', $field, text)
}
}
}
@@ -0,0 +1,17 @@
{
"name": "Toolbar",
"version": "2.0.0",
"description": "Plugin to support the advanced search.",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar",
"example": "http://issues.wenzhixin.net.cn/bootstrap-table/#extensions/toolbar.html",
"plugins": [{
"name": "bootstrap-table-toolbar",
"url": "https://github.com/wenzhixin/bootstrap-table/tree/master/src/extensions/toolbar"
}],
"author": {
"name": "djhvscf",
"image": "https://avatars1.githubusercontent.com/u/4496763"
}
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1,127 @@
document.write('<script type="text/javascript" src="/assets/bootstrap/js/authorization/ksort.js"></script>');
document.write('<script type="text/javascript" src="/assets/bootstrap/js/authorization/crypto-js.min.js"></script>');
document.write('<script type="text/javascript" src="/assets/bootstrap/js/authorization/hmac-sha256.js"></script>');
document.write('<script type="text/javascript" src="/assets/bootstrap/js/authorization/enc-base64.min.js"></script>');
document.write('<script type="text/javascript" src="/assets/bootstrap/js/jquery.cookie.min.js"></script>');
document.write('<div style="display:none"><script type="text/javascript">document.write(unescape("%3Cspan id=\'cnzz_stat_icon_1279911342\'%3E%3C/span%3E%3Cscript src=\'https://v1.cnzz.com/z_stat.php%3Fid%3D1279911342%26\' type=\'text/javascript\'%3E%3C/script%3E"));</script></div>');
function GenerateAuthorization(path, method, params) {
let key = "admin";
let secret = "12878dd962115106db6d";
let date = new Date();
let datetime = date.getFullYear() + "-" // "年"
+ ((date.getMonth() + 1) >= 10 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1)) + "-" // "月"
+ (date.getDate() < 10 ? "0" + date.getDate() : date.getDate()) + " " // "日"
+ (date.getHours() < 10 ? "0" + date.getHours() : date.getHours()) + ":" // "小时"
+ (date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes()) + ":" // "分钟"
+ (date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds()); // "秒"
let sortParamsEncode = decodeURIComponent(jQuery.param(ksort(params)));
let encryptStr = path + "|" + method.toUpperCase() + "|" + sortParamsEncode + "|" + datetime;
let digest = CryptoJS.enc.Base64.stringify(CryptoJS.HmacSHA256(encryptStr, secret));
return {authorization: key + " " + digest, date: datetime};
}
function IsJson(str) {
if (typeof str == 'string') {
try {
let obj = JSON.parse(str);
if (typeof obj == 'object' && obj) {
return true;
} else {
return false;
}
} catch (e) {
console.log('error' + str + '!!!' + e);
return false;
}
}
console.log('It is not a string!')
}
function AjaxError(response) {
let errCode = response.status;
let errMsg = response.responseText;
if (errCode === 401) {
// 跳转到登录页
if (window.frames.length !== parent.frames.length) {
parent.window.open("/login",'_self');
}else{
window.open("/login",'_self');
}
return;
}
if (IsJson(response.responseText)) {
const errInfo = JSON.parse(response.responseText);
errCode = errInfo.code;
errMsg = errInfo.message;
}
$.alert({
title: '错误提示',
icon: 'mdi mdi-alert',
type: 'red',
content: '错误码:' + errCode + '<br/>' + '错误信息:' + errMsg,
});
}
function AjaxForm(method, url, params, beforeSendFunction, successFunction, errorFunction) {
let authorizationData = GenerateAuthorization(url, method, params);
$.ajax({
url: url,
type: method,
data: params,
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
'Authorization': authorizationData.authorization,
'Authorization-Date': authorizationData.date,
'Token': $.cookie("_login_token_"),
},
beforeSend: beforeSendFunction,
success: successFunction,
error: errorFunction,
});
}
function AjaxFormNoAsync(method, url, params, beforeSendFunction, successFunction, errorFunction) {
let authorizationData = GenerateAuthorization(url, method, params);
$.ajax({
url: url,
type: method,
data: params,
async: false,
headers: {
'Content-Type': 'application/x-www-form-urlencoded; charset=utf-8',
'Authorization': authorizationData.authorization,
'Authorization-Date': authorizationData.date,
'Token': $.cookie("_login_token_"),
},
beforeSend: beforeSendFunction,
success: successFunction,
error: errorFunction,
});
}
function AjaxPostJson(url, params, beforeSendFunction, successFunction, errorFunction) {
let authorizationData = GenerateAuthorization(url, "POST", params);
$.ajax({
url: url,
type: "POST",
data: JSON.stringify(params),
headers: {
'Content-Type': 'application/json; charset=utf-8',
'Authorization': authorizationData.authorization,
'Authorization-Date': authorizationData.date,
'Token': $.cookie("_login_token_"),
},
beforeSend: beforeSendFunction,
success: successFunction,
error: errorFunction,
});
}
+139
View File
@@ -0,0 +1,139 @@
;jQuery( function() {
// 停止
$("body").on('click','[data-stopPropagation]',function (e) {
e.stopPropagation();
});
// 滚动条
if($('.lyear-scroll')[0]) {
$('.lyear-scroll').each(function(){
new PerfectScrollbar(this, {
swipeEasing: false,
suppressScrollX: true
});
});
}
// 侧边栏
$(document).on('click', '.lyear-aside-toggler', function() {
$('.lyear-layout-sidebar').toggleClass('lyear-aside-open');
$("body").toggleClass('lyear-layout-sidebar-close');
if ($('.lyear-mask-modal').length == 0) {
$('<div class="lyear-mask-modal"></div>').prependTo('body');
} else {
$( '.lyear-mask-modal' ).remove();
}
});
// 遮罩层
$(document).on('click', '.lyear-mask-modal', function() {
$( this ).remove();
$('.lyear-layout-sidebar').toggleClass('lyear-aside-open');
$('body').toggleClass('lyear-layout-sidebar-close');
});
// 侧边栏导航
$(document).on('click', '.nav-item-has-subnav > a', function() {
$subnavToggle = jQuery( this );
$navHasSubnav = $subnavToggle.parent();
$topHasSubNav = $subnavToggle.parents('.nav-item-has-subnav').last();
$subnav = $navHasSubnav.find('.nav-subnav').first();
$viSubHeight = $navHasSubnav.siblings().find('.nav-subnav:visible').outerHeight();
$scrollBox = $('.lyear-layout-sidebar-info');
$navHasSubnav.siblings().find('.nav-subnav:visible').slideUp(500).parent().removeClass('open');
$subnav.slideToggle( 300, function() {
$navHasSubnav.toggleClass( 'open' );
// 新增滚动条处理
var scrollHeight = 0;
pervTotal = $topHasSubNav.prevAll().length,
boxHeight = $scrollBox.outerHeight(),
innerHeight = $('.sidebar-main').outerHeight(),
thisScroll = $scrollBox.scrollTop(),
thisSubHeight = $(this).outerHeight(),
footHeight = 121;
if (footHeight + innerHeight - boxHeight >= (pervTotal * 48)) {
scrollHeight = pervTotal * 48;
}
if ($subnavToggle.parents('.nav-item-has-subnav').length == 1) {
$scrollBox.animate({scrollTop: scrollHeight}, 300);
} else {
// 子菜单操作
if (typeof($viSubHeight) != 'undefined' && $viSubHeight != null) {
scrollHeight = thisScroll + thisSubHeight - $viSubHeight;
$scrollBox.animate({scrollTop: scrollHeight}, 300);
} else {
if ((thisScroll + boxHeight - $scrollBox[0].scrollHeight) == 0) {
scrollHeight = thisScroll - thisSubHeight;
$scrollBox.animate({scrollTop: scrollHeight}, 300);
}
}
}
});
});
// 读取cookie中的主题设置
var the_logo_bg = $.cookie('the_logo_bg'),
the_header_bg = $.cookie('the_header_bg'),
the_sidebar_bg = $.cookie('the_sidebar_bg');
if (the_logo_bg) $('body').attr('data-logobg', the_logo_bg);
if (the_header_bg) $('body').attr('data-headerbg', the_header_bg);
if (the_sidebar_bg) $('body').attr('data-sidebarbg', the_sidebar_bg);
// 处理主题配色下拉选中
$(".dropdown-skin :radio").each(function(){
var $this = $(this),
radioName = $this.attr('name');
switch (radioName) {
case 'logo_bg':
$this.val() == the_logo_bg && $this.prop("checked", true);
break;
case 'header_bg':
$this.val() == the_header_bg && $this.prop("checked", true);
break;
case 'sidebar_bg':
$this.val() == the_sidebar_bg && $this.prop("checked", true);
}
});
// 设置主题配色
setTheme = function(input_name, data_name) {
$("input[name='"+input_name+"']").click(function(){
$('body').attr(data_name, $(this).val());
$.cookie('the_'+input_name, $(this).val());
});
}
setTheme('sidebar_bg', 'data-sidebarbg');
setTheme('logo_bg', 'data-logobg');
setTheme('header_bg', 'data-headerbg');
// 选项卡
$('#iframe-content').multitabs({
iframe : true,
refresh : 'nav', // iframe中页面是否刷新,'no''从不刷新''nav''点击菜单刷新''all''菜单和tab点击都刷新'
nav: {
backgroundColor: '#ffffff',
maxTabs : 35, // 选项卡最大值
},
init : [{
type : 'main',
title : $.cookie('_nav_title_') ? $.cookie('_nav_title_') : '仪表盘',
url : $.cookie('_nav_url_') ? $.cookie('_nav_url_') : '/dashboard',
}]
});
$(document).on('click', '.nav-item .multitabs', function() {
$('.nav-item').removeClass('active');
$('.nav-subnav li').removeClass('active');
$(this).parent('li').addClass('active');
$(this).parents('.nav-item-has-subnav').addClass('open').first().addClass('active');
var date = new Date();
date.setTime(date.getTime() + 24 * 60 * 60 * 1000); // 24 * 60 * 60 * 1000 表示 24 小时
$.cookie('_nav_url_', $(this).attr('href'), {expires: date});
$.cookie('_nav_title_', $(this).text(), {expires: date});
});
});
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
.treegrid-indent{width:16px;height:16px;display:inline-block;position:relative}.treegrid-expander{width:16px;height:16px;display:inline-block;position:relative;cursor:pointer}
File diff suppressed because one or more lines are too long
+24
View File
@@ -0,0 +1,24 @@
/*
jQuery twitter bootstrap wizard plugin
Examples and documentation at: http://github.com/VinceG/twitter-bootstrap-wizard
version 1.4.2
Requires jQuery v1.3.2 or later
Supports Bootstrap 2.2.x, 2.3.x, 3.0
Dual licensed under the MIT and GPL licenses:
http://www.opensource.org/licenses/mit-license.php
http://www.gnu.org/licenses/gpl.html
Authors: Vadim Vincent Gabriel (http://vadimg.com), Jason Gill (www.gilluminate.com)
*/
(function(c){var n=function(d,k){d=c(d);var a=this,h=[],b=c.extend({},c.fn.bootstrapWizard.defaults,k),f=null,e=null;this.rebindClick=function(b,a){b.unbind("click",a).bind("click",a)};this.fixNavigationButtons=function(){f.length||(e.find("a:first").tab("show"),f=e.find('li:has([data-toggle="tab"]):first'));c(b.previousSelector,d).toggleClass("disabled",a.firstIndex()>=a.currentIndex());c(b.nextSelector,d).toggleClass("disabled",a.currentIndex()>=a.navigationLength());c(b.nextSelector,d).toggleClass("d-none",
a.currentIndex()>=a.navigationLength()&&0<c(b.finishSelector,d).length);c(b.lastSelector,d).toggleClass("d-none",a.currentIndex()>=a.navigationLength()&&0<c(b.finishSelector,d).length);c(b.finishSelector,d).toggleClass("d-none",a.currentIndex()<a.navigationLength());c(b.backSelector,d).toggleClass("disabled",0==h.length);c(b.backSelector,d).toggleClass("d-none",a.currentIndex()>=a.navigationLength()&&0<c(b.finishSelector,d).length);a.rebindClick(c(b.nextSelector,d),a.next);a.rebindClick(c(b.previousSelector,
d),a.previous);a.rebindClick(c(b.lastSelector,d),a.last);a.rebindClick(c(b.firstSelector,d),a.first);a.rebindClick(c(b.finishSelector,d),a.finish);a.rebindClick(c(b.backSelector,d),a.back);if(b.onTabShow&&"function"===typeof b.onTabShow&&!1===b.onTabShow(f,e,a.currentIndex()))return!1};this.next=function(g){if(d.hasClass("last")||b.onNext&&"function"===typeof b.onNext&&!1===b.onNext(f,e,a.nextIndex()))return!1;g=a.currentIndex();var c=a.nextIndex();c>a.navigationLength()||(h.push(g),e.find('li:has([data-toggle="tab"])'+
(b.withVisible?":visible":"")+":eq("+c+") a").tab("show"))};this.previous=function(g){if(d.hasClass("first")||b.onPrevious&&"function"===typeof b.onPrevious&&!1===b.onPrevious(f,e,a.previousIndex()))return!1;g=a.currentIndex();var c=a.previousIndex();0>c||(h.push(g),e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")+":eq("+c+") a").tab("show"))};this.first=function(g){if(b.onFirst&&"function"===typeof b.onFirst&&!1===b.onFirst(f,e,a.firstIndex())||d.hasClass("disabled"))return!1;h.push(a.currentIndex());
e.find('li:has([data-toggle="tab"]):eq(0) a').tab("show")};this.last=function(g){if(b.onLast&&"function"===typeof b.onLast&&!1===b.onLast(f,e,a.lastIndex())||d.hasClass("disabled"))return!1;h.push(a.currentIndex());e.find('li:has([data-toggle="tab"]):eq('+a.navigationLength()+") a").tab("show")};this.finish=function(g){if(b.onFinish&&"function"===typeof b.onFinish)b.onFinish(f,e,a.lastIndex())};this.back=function(){if(0==h.length)return null;var a=h.pop();if(b.onBack&&"function"===typeof b.onBack&&
!1===b.onBack(f,e,a))return h.push(a),!1;d.find('li:has([data-toggle="tab"]):eq('+a+") a").tab("show")};this.currentIndex=function(){return e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")).index(f)};this.firstIndex=function(){return 0};this.lastIndex=function(){return a.navigationLength()};this.getIndex=function(a){return e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")).index(a)};this.nextIndex=function(){var a=this.currentIndex(),c;do a++,c=e.find('li:has([data-toggle="tab"])'+
(b.withVisible?":visible":"")+":eq("+a+")");while(c&&c.hasClass("disabled"));return a};this.previousIndex=function(){var a=this.currentIndex(),c;do a--,c=e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")+":eq("+a+")");while(c&&c.hasClass("disabled"));return a};this.navigationLength=function(){return e.find('li:has([data-toggle="tab"])'+(b.withVisible?":visible":"")).length-1};this.activeTab=function(){return f};this.nextTab=function(){return e.find('li:has([data-toggle="tab"]):eq('+
(a.currentIndex()+1)+")").length?e.find('li:has([data-toggle="tab"]):eq('+(a.currentIndex()+1)+")"):null};this.previousTab=function(){return 0>=a.currentIndex()?null:e.find('li:has([data-toggle="tab"]):eq('+parseInt(a.currentIndex()-1)+")")};this.show=function(b){b=isNaN(b)?d.find('li:has([data-toggle="tab"]) a[href="#'+b+'"]'):d.find('li:has([data-toggle="tab"]):eq('+b+") a");0<b.length&&(h.push(a.currentIndex()),b.tab("show"))};this.disable=function(a){e.find('li:has([data-toggle="tab"]):eq('+a+
")").addClass("disabled")};this.enable=function(a){e.find('li:has([data-toggle="tab"]):eq('+a+")").removeClass("disabled")};this.hide=function(a){e.find('li:has([data-toggle="tab"]):eq('+a+")").hide()};this.display=function(a){e.find('li:has([data-toggle="tab"]):eq('+a+")").show()};this.remove=function(a){var b="undefined"!=typeof a[1]?a[1]:!1;a=e.find('li:has([data-toggle="tab"]):eq('+a[0]+")");b&&(b=a.find("a").attr("href"),c(b).remove());a.remove()};var l=function(d){var g=e.find('li:has([data-toggle="tab"])');
d=g.index(c(d.currentTarget).parent('li:has([data-toggle="tab"])'));g=c(g[d]);if(b.onTabClick&&"function"===typeof b.onTabClick&&!1===b.onTabClick(f,e,a.currentIndex(),d,g))return!1},m=function(d){d=c(d.target).parent();var g=e.find('li:has([data-toggle="tab"])').index(d);if(d.hasClass("disabled")||b.onTabChange&&"function"===typeof b.onTabChange&&!1===b.onTabChange(f,e,a.currentIndex(),g))return!1;f=d;a.fixNavigationButtons()};this.resetWizard=function(){c('a[data-toggle="tab"]',e).off("click",l);
c('a[data-toggle="tab"]',e).off("show show.bs.tab",m);e=d.find("ul:first",d);f=e.find('li:has([data-toggle="tab"]).active',d);c('a[data-toggle="tab"]',e).on("click",l);c('a[data-toggle="tab"]',e).on("show show.bs.tab",m);a.fixNavigationButtons()};e=d.find("ul:first",d);f=e.find('li:has([data-toggle="tab"]).active',d);e.hasClass(b.tabClass)||e.addClass(b.tabClass);if(b.onInit&&"function"===typeof b.onInit)b.onInit(f,e,0);if(b.onShow&&"function"===typeof b.onShow)b.onShow(f,e,a.nextIndex());c('a[data-toggle="tab"]',
e).on("click",l);c('a[data-toggle="tab"]',e).on("show show.bs.tab",m)};c.fn.bootstrapWizard=function(d){if("string"==typeof d){var k=Array.prototype.slice.call(arguments,1);1===k.length&&k.toString();return this.data("bootstrapWizard")[d](k)}return this.each(function(a){a=c(this);if(!a.data("bootstrapWizard")){var h=new n(a,d);a.data("bootstrapWizard",h);h.fixNavigationButtons()}})};c.fn.bootstrapWizard.defaults={withVisible:!0,tabClass:"nav nav-pills",nextSelector:".wizard li.next",previousSelector:".wizard li.previous",
firstSelector:".wizard li.first",lastSelector:".wizard li.last",finishSelector:".wizard li.finish",backSelector:".wizard li.back",onShow:null,onInit:null,onNext:null,onPrevious:null,onLast:null,onFirst:null,onFinish:null,onBack:null,onTabChange:null,onTabClick:null,onTabShow:null}})(jQuery);
+2
View File
@@ -0,0 +1,2 @@
/*! jquery.cookie v1.4.1 | MIT */
!function(a){"function"==typeof define&&define.amd?define(["jquery"],a):"object"==typeof exports?a(require("jquery")):a(jQuery)}(function(a){function b(a){return h.raw?a:encodeURIComponent(a)}function c(a){return h.raw?a:decodeURIComponent(a)}function d(a){return b(h.json?JSON.stringify(a):String(a))}function e(a){0===a.indexOf('"')&&(a=a.slice(1,-1).replace(/\\"/g,'"').replace(/\\\\/g,"\\"));try{return a=decodeURIComponent(a.replace(g," ")),h.json?JSON.parse(a):a}catch(b){}}function f(b,c){var d=h.raw?b:e(b);return a.isFunction(c)?c(d):d}var g=/\+/g,h=a.cookie=function(e,g,i){if(void 0!==g&&!a.isFunction(g)){if(i=a.extend({},h.defaults,i),"number"==typeof i.expires){var j=i.expires,k=i.expires=new Date;k.setTime(+k+864e5*j)}return document.cookie=[b(e),"=",d(g),i.expires?"; expires="+i.expires.toUTCString():"",i.path?"; path="+i.path:"",i.domain?"; domain="+i.domain:"",i.secure?"; secure":""].join("")}for(var l=e?void 0:{},m=document.cookie?document.cookie.split("; "):[],n=0,o=m.length;o>n;n++){var p=m[n].split("="),q=c(p.shift()),r=p.join("=");if(e&&e===q){l=f(r,g);break}e||void 0===(r=f(r))||(l[q]=r)}return l};h.defaults={},a.removeCookie=function(b,c){return void 0===a.cookie(b)?!1:(a.cookie(b,"",a.extend({},c,{expires:-1})),!a.cookie(b))}});
File diff suppressed because one or more lines are too long
+292
View File
@@ -0,0 +1,292 @@
/**
* pagination.js 1.5.1
* A jQuery plugin to provide simple yet fully customisable pagination.
* @version 1.5.1
* @author mss
* @url https://github.com/Maxiaoxiang/jQuery-plugins
*
* @调用方法
* $(selector).pagination(option, callback);
* -此处callback是初始化调用option里的callback是点击页码后调用
*
* -- example --
* $(selector).pagination({
* ... // 配置参数
* callback: function(api) {
* console.log('点击页码调用该回调'); //切换页码时执行一次回调
* }
* }, function(){
* console.log('初始化'); //插件初始化时调用该方法,比如请求第一次接口来初始化分页配置
* });
*/
;
(function (factory) {
if (typeof define === "function" && (define.amd || define.cmd) && !jQuery) {
// AMD或CMD
define(["jquery"], factory);
} else if (typeof module === 'object' && module.exports) {
// Node/CommonJS
module.exports = function (root, jQuery) {
if (jQuery === undefined) {
if (typeof window !== 'undefined') {
jQuery = require('jquery');
} else {
jQuery = require('jquery')(root);
}
}
factory(jQuery);
return jQuery;
};
} else {
//Browser globals
factory(jQuery);
}
}(function ($) {
//配置参数
var defaults = {
totalData: 0, //数据总条数
showData: 0, //每页显示的条数
pageCount: 9, //总页数,默认为9
current: 1, //当前第几页
prevCls: 'prev', //上一页class
nextCls: 'next', //下一页class
prevContent: '<', //上一页内容
nextContent: '>', //下一页内容
activeCls: 'active', //当前页选中状态
coping: false, //首页和尾页
isHide: false, //当前页数为0页或者1页时不显示分页
homePage: '', //首页节点内容
endPage: '', //尾页节点内容
keepShowPN: false, //是否一直显示上一页下一页
mode: 'unfixed', //分页模式,unfixed:不固定页码数量,fixed:固定页码数量
count: 4, //mode为unfixed时显示当前选中页前后页数,mode为fixed显示页码总数
jump: false, //跳转到指定页数
jumpIptCls: 'jump-ipt', //文本框内容
jumpBtnCls: 'jump-btn', //跳转按钮
jumpBtn: '跳转', //跳转按钮文本
callback: function () {} //回调
};
var Pagination = function (element, options) {
//全局变量
var opts = options, //配置
current, //当前页
$document = $(document),
$obj = $(element); //容器
/**
* 设置总页数
* @param {int} page 页码
* @return opts.pageCount 总页数配置
*/
this.setPageCount = function (page) {
return opts.pageCount = page;
};
/**
* 获取总页数
* 如果配置了总条数和每页显示条数将会自动计算总页数并略过总页数配置反之
* @return {int} 总页数
*/
this.getPageCount = function () {
return opts.totalData && opts.showData ? Math.ceil(parseInt(opts.totalData) / opts.showData) : opts.pageCount;
};
/**
* 获取当前页
* @return {int} 当前页码
*/
this.getCurrent = function () {
return current;
};
/**
* 填充数据
* @param {int} 页码
*/
this.filling = function (index) {
var html = '';
current = parseInt(index) || parseInt(opts.current); //当前页码
var pageCount = this.getPageCount(); //获取的总页数
switch (opts.mode) { //配置模式
case 'fixed': //固定按钮模式
html += '<li class="page-item"><a href="javascript:;" class="page-link ' + opts.prevCls + '">' + opts.prevContent + '</a></li>';
if (opts.coping) {
var home = opts.coping && opts.homePage ? opts.homePage : '1';
html += '<li class="page-item"><a class="page-link" href="javascript:;" data-page="1">' + home + '</a></li>';
}
var start = current > opts.count - 1 ? current + opts.count - 1 > pageCount ? current - (opts.count - (pageCount - current)) : current - 2 : 1;
var end = current + opts.count - 1 > pageCount ? pageCount : start + opts.count;
for (; start <= end; start++) {
if (start != current) {
html += '<li class="page-item"><a class="page-link" href="javascript:;" data-page="' + start + '">' + start + '</a></li>';
} else {
html += '<li class="page-item active"><span class="page-link ' + opts.activeCls + '">' + start + '</span></li>';
}
}
if (opts.coping) {
var _end = opts.coping && opts.endPage ? opts.endPage : pageCount;
html += '<li class="page-item"><a class="page-link" href="javascript:;" data-page="' + pageCount + '">' + _end + '</a></li>';
}
html += '<li class="page-item"><a href="javascript:;" class="page-link ' + opts.nextCls + '">' + opts.nextContent + '</a></li>';
break;
// if (opts.keepShowPN || current > 1) { //上一页
// html += '<a href="javascript:;" class="' + opts.prevCls + '">' + opts.prevContent + '</a>';
// } else {
// if (opts.keepShowPN == false) {
// $obj.find('.' + opts.prevCls) && $obj.find('.' + opts.prevCls).remove();
// }
// }
// if (current >= opts.count + 2 && current != 1 && pageCount != opts.count) {
// var home = opts.coping && opts.homePage ? opts.homePage : '1';
// html += opts.coping ? '<a href="javascript:;" data-page="1">' + home + '</a><span>...</span>' : '';
// }
// var start = (current - opts.count) <= 1 ? 1 : (current - opts.count);
// var end = (current + opts.count) >= pageCount ? pageCount : (current + opts.count);
// for (; start <= end; start++) {
// if (start <= pageCount && start >= 1) {
// if (start != current) {
// html += '<a href="javascript:;" data-page="' + start + '">' + start + '</a>';
// } else {
// html += '<span class="' + opts.activeCls + '">' + start + '</span>';
// }
// }
// }
// if (current + opts.count < pageCount && current >= 1 && pageCount > opts.count) {
// var end = opts.coping && opts.endPage ? opts.endPage : pageCount;
// html += opts.coping ? '<span>...</span><a href="javascript:;" data-page="' + pageCount + '">' + end + '</a>' : '';
// }
// if (opts.keepShowPN || current < pageCount) { //下一页
// html += '<a href="javascript:;" class="' + opts.nextCls + '">' + opts.nextContent + '</a>';
// } else {
// if (opts.keepShowPN == false) {
// $obj.find('.' + opts.nextCls) && $obj.find('.' + opts.nextCls).remove();
// }
// }
// break;
case 'unfixed': //不固定按钮模式
if (opts.keepShowPN || current > 1) { //上一页
html += '<a href="javascript:;" class="' + opts.prevCls + '">' + opts.prevContent + '</a>';
} else {
if (opts.keepShowPN == false) {
$obj.find('.' + opts.prevCls) && $obj.find('.' + opts.prevCls).remove();
}
}
if (current >= opts.count + 2 && current != 1 && pageCount != opts.count) {
var home = opts.coping && opts.homePage ? opts.homePage : '1';
html += opts.coping ? '<a href="javascript:;" data-page="1">' + home + '</a><span>...</span>' : '';
}
var start = (current - opts.count) <= 1 ? 1 : (current - opts.count);
var end = (current + opts.count) >= pageCount ? pageCount : (current + opts.count);
for (; start <= end; start++) {
if (start <= pageCount && start >= 1) {
if (start != current) {
html += '<a href="javascript:;" data-page="' + start + '">' + start + '</a>';
} else {
html += '<span class="' + opts.activeCls + '">' + start + '</span>';
}
}
}
if (current + opts.count < pageCount && current >= 1 && pageCount > opts.count) {
var end = opts.coping && opts.endPage ? opts.endPage : pageCount;
html += opts.coping ? '<span>...</span><a href="javascript:;" data-page="' + pageCount + '">' + end + '</a>' : '';
}
if (opts.keepShowPN || current < pageCount) { //下一页
html += '<a href="javascript:;" class="' + opts.nextCls + '">' + opts.nextContent + '</a>';
} else {
if (opts.keepShowPN == false) {
$obj.find('.' + opts.nextCls) && $obj.find('.' + opts.nextCls).remove();
}
}
break;
case 'easy': //简单模式
break;
default:
}
html += opts.jump ? '<input type="text" class="' + opts.jumpIptCls + '"><a href="javascript:;" class="' + opts.jumpBtnCls + '">' + opts.jumpBtn + '</a>' : '';
$obj.empty().html(html);
};
//绑定事件
this.eventBind = function () {
var that = this;
var pageCount = that.getPageCount(); //总页数
var index = 1;
$obj.off().on('click', 'a', function () {
if ($(this).hasClass(opts.nextCls)) {
if (parseInt($obj.find('.' + opts.activeCls).text()) >= pageCount) {
$(this).addClass('disabled');
return false;
} else {
index = parseInt($obj.find('.' + opts.activeCls).text()) + 1;
}
} else if ($(this).hasClass(opts.prevCls)) {
if (parseInt($obj.find('.' + opts.activeCls).text()) <= 1) {
$(this).addClass('disabled');
return false;
} else {
index = parseInt($obj.find('.' + opts.activeCls).text()) - 1;
}
} else if ($(this).hasClass(opts.jumpBtnCls)) {
if ($obj.find('.' + opts.jumpIptCls).val() !== '') {
index = parseInt($obj.find('.' + opts.jumpIptCls).val());
} else {
return;
}
} else {
index = parseInt($(this).data('page'));
}
that.filling(index);
typeof opts.callback === 'function' && opts.callback(that);
});
//输入跳转的页码
$obj.on('input propertychange', '.' + opts.jumpIptCls, function () {
var $this = $(this);
var val = $this.val();
var reg = /[^\d]/g;
if (reg.test(val)) $this.val(val.replace(reg, ''));
(parseInt(val) > pageCount) && $this.val(pageCount);
if (parseInt(val) === 0) $this.val(1); //最小值为1
});
//回车跳转指定页码
$document.keydown(function (e) {
if (e.keyCode == 13 && $obj.find('.' + opts.jumpIptCls).val()) {
var index = parseInt($obj.find('.' + opts.jumpIptCls).val());
that.filling(index);
typeof opts.callback === 'function' && opts.callback(that);
}
});
};
//初始化
this.init = function () {
this.filling(opts.current);
this.eventBind();
if (opts.isHide && this.getPageCount() == '1' || this.getPageCount() == '0') {
$obj.hide();
} else {
$obj.show();
}
};
this.init();
};
$.fn.pagination = function (parameter, callback) {
if (typeof parameter == 'function') { //重载
callback = parameter;
parameter = {};
} else {
parameter = parameter || {};
callback = callback || function () {};
}
var options = $.extend({}, defaults, parameter);
return this.each(function () {
var pagination = new Pagination(this, options);
callback(pagination);
});
};
}));
+141
View File
@@ -0,0 +1,141 @@
;jQuery( function() {
// 工具提示
if($('[data-toggle="tooltip"]')[0]) {
$('[data-toggle="tooltip"]').tooltip({
"container" : 'body',
});
}
// POP弹出框
if($('[data-toggle="popover"]')[0]) {
$('[data-toggle="popover"]').popover();
}
// 关闭卡片
$(document).on('click', '.card-btn-close', function() {
$(this).closest('.card').fadeOut(150, function() {
if ($(this).parent().children().length == 1) {
$(this).parent().remove();
} else {
$(this).remove();
}
});
});
// 卡片收缩与打开
$(document).on('click', '.card-btn-slide', function(){
$(this).toggleClass('rotate-180').closest('.card').find('.card-body').slideToggle();
});
/**
* 如果页面中需要用到滚动条请先导入perfect-scrollbar.min.js
*/
if($('.lyear-scroll')[0]) {
$('.lyear-scroll').each(function(){
new PerfectScrollbar(this, {
swipeEasing: false,
suppressScrollX: true
});
});
}
// 颜色选取
jQuery('.js-colorpicker').each(function() {
var $colorpicker = jQuery(this);
var $colorpickerMode = $colorpicker.data('colorpicker-mode') ? $colorpicker.data('colorpicker-mode') : 'auto';
$colorpicker.colorpicker({
'format': $colorpickerMode,
});
});
// 日期选择器
jQuery("[data-provide = 'datepicker']").each(function() {
var options = {
language: 'zh-CN', // 默认简体中文
multidateSeparator: ', ' // 默认多个日期用,分隔
}
options = $.extend( options, getDataOptions( $(this) ));
if ( $(this).prop("tagName") != 'INPUT' ) {
options.inputs = [$(this).find('input:first'), $(this).find('input:last')];
}
$(this).datepicker(options);
});
// 时间选择器
jQuery("[data-provide = 'clockpicker']").each(function() {
$(this).clockpicker({
donetext: 'Done'
});
});
// 时间日期选择器
jQuery("[data-provide = 'datetimepicker']").each(function() {
var options = {
locale: moment.locale(),
}
options = $.extend( options, getDataOptions( $(this) ));
if ( $(this).prop("tagName") != 'INPUT' ) {
options.inputs = [$(this).find('input:first'), $(this).find('input:last')];
}
console.log(options);
$(this).datetimepicker(options);
});
// 标签
$('.js-tags-input').each(function() {
var $this = $(this);
$this.tagsInput({
height: $this.data('height') ? $this.data('height') : '36px',
width: '100%',
defaultText: $this.attr("placeholder"),
removeWithBackspace: true,
delimiter: [',']
});
});
// 复选框全选
$("#check-all").change(function () {
if ($boxname = $(this).data('name')) {
$(this).closest('table').find("input[name='" + $boxname + "']").prop('checked', $(this).prop("checked"));
} else {
$(this).closest('table').find(".custom-checkbox input[type='checkbox']").prop('checked', $(this).prop("checked"));
}
});
// iframe打开tab
$(document).on('click', '.js-create-tab', function(){
parent.$(parent.document).data('multitabs').create({
iframe : true,
title : $(this).data('title') ? $(this).data('title') : '标题',
url : $(this).data('url') ? $(this).data('url') : '/dashboard'
}, true);
});
});
// 参考国外模板的写法,获取当前的配置,以data-*(*指插件原有的配置名)
getDataOptions = function(el, castList) {
var options = {};
$.each( $(el).data(), function(key, value){
key = dataToOption(key);
if ( key == 'provide' ) {
return;
}
options[key] = value;
});
return options;
}
dataToOption = function(name) {
return name.replace(/-([a-z])/g, function(x){return x[1].toUpperCase();});
}
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+357
View File
@@ -0,0 +1,357 @@
/**
* vkBeautify - javascript plugin to pretty-print or minify text in XML, JSON, CSS and SQL formats.
*
* Version - 0.99.00.beta
* Copyright (c) 2012 Vadim Kiryukhin
* vkiryukhin @ gmail.com
* http://www.eslinstructor.net/vkbeautify/
*
* MIT license:
* http://www.opensource.org/licenses/mit-license.php
*
* Pretty print
*
* vkbeautify.xml(text [,indent_pattern]);
* vkbeautify.json(text [,indent_pattern]);
* vkbeautify.css(text [,indent_pattern]);
* vkbeautify.sql(text [,indent_pattern]);
*
* @text - String; text to beatufy;
* @indent_pattern - Integer | String;
* Integer: number of white spaces;
* String: character string to visualize indentation ( can also be a set of white spaces )
* Minify
*
* vkbeautify.xmlmin(text [,preserve_comments]);
* vkbeautify.jsonmin(text);
* vkbeautify.cssmin(text [,preserve_comments]);
* vkbeautify.sqlmin(text);
*
* @text - String; text to minify;
* @preserve_comments - Bool; [optional];
* Set this flag to true to prevent removing comments from @text ( minxml and mincss functions only. )
*
* Examples:
* vkbeautify.xml(text); // pretty print XML
* vkbeautify.json(text, 4 ); // pretty print JSON
* vkbeautify.css(text, '. . . .'); // pretty print CSS
* vkbeautify.sql(text, '----'); // pretty print SQL
*
* vkbeautify.xmlmin(text, true);// minify XML, preserve comments
* vkbeautify.jsonmin(text);// minify JSON
* vkbeautify.cssmin(text);// minify CSS, remove comments ( default )
* vkbeautify.sqlmin(text);// minify SQL
*
*/
(function() {
function createShiftArr(step) {
var space = ' ';
if ( isNaN(parseInt(step)) ) { // argument is string
space = step;
} else { // argument is integer
switch(step) {
case 1: space = ' '; break;
case 2: space = ' '; break;
case 3: space = ' '; break;
case 4: space = ' '; break;
case 5: space = ' '; break;
case 6: space = ' '; break;
case 7: space = ' '; break;
case 8: space = ' '; break;
case 9: space = ' '; break;
case 10: space = ' '; break;
case 11: space = ' '; break;
case 12: space = ' '; break;
}
}
var shift = ['\n']; // array of shifts
for(ix=0;ix<100;ix++){
shift.push(shift[ix]+space);
}
return shift;
}
function vkbeautify(){
this.step = '\t'; // 4 spaces
this.shift = createShiftArr(this.step);
};
vkbeautify.prototype.xml = function(text,step) {
var ar = text.replace(/>\s{0,}</g,"><")
.replace(/</g,"~::~<")
.replace(/\s*xmlns\:/g,"~::~xmlns:")
.replace(/\s*xmlns\=/g,"~::~xmlns=")
.split('~::~'),
len = ar.length,
inComment = false,
deep = 0,
str = '',
ix = 0,
shift = step ? createShiftArr(step) : this.shift;
for(ix=0;ix<len;ix++) {
// start comment or <![CDATA[...]]> or <!DOCTYPE //
if(ar[ix].search(/<!/) > -1) {
str += shift[deep]+ar[ix];
inComment = true;
// end comment or <![CDATA[...]]> //
if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1 || ar[ix].search(/!DOCTYPE/) > -1 ) {
inComment = false;
}
} else
// end comment or <![CDATA[...]]> //
if(ar[ix].search(/-->/) > -1 || ar[ix].search(/\]>/) > -1) {
str += ar[ix];
inComment = false;
} else
// <elm></elm> //
if( /^<\w/.exec(ar[ix-1]) && /^<\/\w/.exec(ar[ix]) &&
/^<[\w:\-\.\,]+/.exec(ar[ix-1]) == /^<\/[\w:\-\.\,]+/.exec(ar[ix])[0].replace('/','')) {
str += ar[ix];
if(!inComment) deep--;
} else
// <elm> //
if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) == -1 && ar[ix].search(/\/>/) == -1 ) {
str = !inComment ? str += shift[deep++]+ar[ix] : str += ar[ix];
} else
// <elm>...</elm> //
if(ar[ix].search(/<\w/) > -1 && ar[ix].search(/<\//) > -1) {
str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
} else
// </elm> //
if(ar[ix].search(/<\//) > -1) {
str = !inComment ? str += shift[--deep]+ar[ix] : str += ar[ix];
} else
// <elm/> //
if(ar[ix].search(/\/>/) > -1 ) {
str = !inComment ? str += shift[deep]+ar[ix] : str += ar[ix];
} else
// <? xml ... ?> //
if(ar[ix].search(/<\?/) > -1) {
str += shift[deep]+ar[ix];
} else
// xmlns //
if( ar[ix].search(/xmlns\:/) > -1 || ar[ix].search(/xmlns\=/) > -1) {
str += shift[deep]+ar[ix];
}
else {
str += ar[ix];
}
}
return (str[0] == '\n') ? str.slice(1) : str;
}
vkbeautify.prototype.json = function(text,step) {
var step = step ? step : this.step;
if (typeof JSON === 'undefined' ) return text;
if ( typeof text === "string" ) return JSON.stringify(JSON.parse(text), null, step);
if ( typeof text === "object" ) return JSON.stringify(text, null, step);
return text; // text is not string nor object
}
vkbeautify.prototype.css = function(text, step) {
var ar = text.replace(/\s{1,}/g,' ')
.replace(/\{/g,"{~::~")
.replace(/\}/g,"~::~}~::~")
.replace(/\;/g,";~::~")
.replace(/\/\*/g,"~::~/*")
.replace(/\*\//g,"*/~::~")
.replace(/~::~\s{0,}~::~/g,"~::~")
.split('~::~'),
len = ar.length,
deep = 0,
str = '',
ix = 0,
shift = step ? createShiftArr(step) : this.shift;
for(ix=0;ix<len;ix++) {
if( /\{/.exec(ar[ix])) {
str += shift[deep++]+ar[ix];
} else
if( /\}/.exec(ar[ix])) {
str += shift[--deep]+ar[ix];
} else
if( /\*\\/.exec(ar[ix])) {
str += shift[deep]+ar[ix];
}
else {
str += shift[deep]+ar[ix];
}
}
return str.replace(/^\n{1,}/,'');
}
//----------------------------------------------------------------------------
function isSubquery(str, parenthesisLevel) {
return parenthesisLevel - (str.replace(/\(/g,'').length - str.replace(/\)/g,'').length )
}
function split_sql(str, tab) {
return str.replace(/\s{1,}/g," ")
.replace(/ AND /ig,"~::~"+tab+tab+"AND ")
.replace(/ BETWEEN /ig,"~::~"+tab+"BETWEEN ")
.replace(/ CASE /ig,"~::~"+tab+"CASE ")
.replace(/ ELSE /ig,"~::~"+tab+"ELSE ")
.replace(/ END /ig,"~::~"+tab+"END ")
.replace(/ FROM /ig,"~::~FROM ")
.replace(/ GROUP\s{1,}BY/ig,"~::~GROUP BY ")
.replace(/ HAVING /ig,"~::~HAVING ")
//.replace(/ SET /ig," SET~::~")
.replace(/ IN /ig," IN ")
.replace(/ JOIN /ig,"~::~JOIN ")
.replace(/ CROSS~::~{1,}JOIN /ig,"~::~CROSS JOIN ")
.replace(/ INNER~::~{1,}JOIN /ig,"~::~INNER JOIN ")
.replace(/ LEFT~::~{1,}JOIN /ig,"~::~LEFT JOIN ")
.replace(/ RIGHT~::~{1,}JOIN /ig,"~::~RIGHT JOIN ")
.replace(/ ON /ig,"~::~"+tab+"ON ")
.replace(/ OR /ig,"~::~"+tab+tab+"OR ")
.replace(/ ORDER\s{1,}BY/ig,"~::~ORDER BY ")
.replace(/ OVER /ig,"~::~"+tab+"OVER ")
.replace(/\(\s{0,}SELECT /ig,"~::~(SELECT ")
.replace(/\)\s{0,}SELECT /ig,")~::~SELECT ")
.replace(/ THEN /ig," THEN~::~"+tab+"")
.replace(/ UNION /ig,"~::~UNION~::~")
.replace(/ USING /ig,"~::~USING ")
.replace(/ WHEN /ig,"~::~"+tab+"WHEN ")
.replace(/ WHERE /ig,"~::~WHERE ")
.replace(/ WITH /ig,"~::~WITH ")
//.replace(/\,\s{0,}\(/ig,",~::~( ")
//.replace(/\,/ig,",~::~"+tab+tab+"")
.replace(/ ALL /ig," ALL ")
.replace(/ AS /ig," AS ")
.replace(/ ASC /ig," ASC ")
.replace(/ DESC /ig," DESC ")
.replace(/ DISTINCT /ig," DISTINCT ")
.replace(/ EXISTS /ig," EXISTS ")
.replace(/ NOT /ig," NOT ")
.replace(/ NULL /ig," NULL ")
.replace(/ LIKE /ig," LIKE ")
.replace(/\s{0,}SELECT /ig,"SELECT ")
.replace(/\s{0,}UPDATE /ig,"UPDATE ")
.replace(/ SET /ig," SET ")
.replace(/~::~{1,}/g,"~::~")
.split('~::~');
}
vkbeautify.prototype.sql = function(text,step) {
var ar_by_quote = text.replace(/\s{1,}/g," ")
.replace(/\'/ig,"~::~\'")
.split('~::~'),
len = ar_by_quote.length,
ar = [],
deep = 0,
tab = this.step,//+this.step,
inComment = true,
inQuote = false,
parenthesisLevel = 0,
str = '',
ix = 0,
shift = step ? createShiftArr(step) : this.shift;;
for(ix=0;ix<len;ix++) {
if(ix%2) {
ar = ar.concat(ar_by_quote[ix]);
} else {
ar = ar.concat(split_sql(ar_by_quote[ix], tab) );
}
}
len = ar.length;
for(ix=0;ix<len;ix++) {
parenthesisLevel = isSubquery(ar[ix], parenthesisLevel);
if( /\s{0,}\s{0,}SELECT\s{0,}/.exec(ar[ix])) {
ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
}
if( /\s{0,}\s{0,}SET\s{0,}/.exec(ar[ix])) {
ar[ix] = ar[ix].replace(/\,/g,",\n"+tab+tab+"")
}
if( /\s{0,}\(\s{0,}SELECT\s{0,}/.exec(ar[ix])) {
deep++;
str += shift[deep]+ar[ix];
} else
if( /\'/.exec(ar[ix]) ) {
if(parenthesisLevel<1 && deep) {
deep--;
}
str += ar[ix];
}
else {
str += shift[deep]+ar[ix];
if(parenthesisLevel<1 && deep) {
deep--;
}
}
var junk = 0;
}
str = str.replace(/^\n{1,}/,'').replace(/\n{1,}/g,"\n");
return str;
}
vkbeautify.prototype.xmlmin = function(text, preserveComments) {
var str = preserveComments ? text
: text.replace(/\<![ \r\n\t]*(--([^\-]|[\r\n]|-[^\-])*--[ \r\n\t]*)\>/g,"")
.replace(/[ \r\n\t]{1,}xmlns/g, ' xmlns');
return str.replace(/>\s{0,}</g,"><");
}
vkbeautify.prototype.jsonmin = function(text) {
if (typeof JSON === 'undefined' ) return text;
return JSON.stringify(JSON.parse(text), null, 0);
}
vkbeautify.prototype.cssmin = function(text, preserveComments) {
var str = preserveComments ? text
: text.replace(/\/\*([^*]|[\r\n]|(\*+([^*/]|[\r\n])))*\*+\//g,"") ;
return str.replace(/\s{1,}/g,' ')
.replace(/\{\s{1,}/g,"{")
.replace(/\}\s{1,}/g,"}")
.replace(/\;\s{1,}/g,";")
.replace(/\/\*\s{1,}/g,"/*")
.replace(/\*\/\s{1,}/g,"*/");
}
vkbeautify.prototype.sqlmin = function(text) {
return text.replace(/\s{1,}/g," ").replace(/\s{1,}\(/,"(").replace(/\s{1,}\)/,")");
}
window.vkbeautify = new vkbeautify();
})();
+164
View File
@@ -0,0 +1,164 @@
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"/>
<link href="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.css" rel="stylesheet">
<link href="/assets/bootstrap/css/bootstrap.min.css" rel="stylesheet">
<link href="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.css" rel="stylesheet" type="text/css">
<link href="/assets/bootstrap/css/materialdesignicons.min.css" rel="stylesheet">
<link href="/assets/bootstrap/css/style.min.css" rel="stylesheet">
</head>
<body>
<div class="container-fluid p-t-15">
<div class="row">
<div class="col-lg-12">
<div class="card">
<div class="card-header">
<div class="card-title">新增管理员</div>
</div>
<div class="card-body">
<form>
<div class="form-group">
<label>用户名</label>
<input type="text" class="form-control" maxlength="10" id="username"
placeholder="请输入用户名">
</div>
<div class="form-group">
<label>昵称</label>
<input type="text" class="form-control" maxlength="10" id="nickname"
placeholder="请输入昵称">
</div>
<div class="form-group">
<label>手机号</label>
<input type="text" class="form-control" maxlength="11" id="mobile"
placeholder="请输入手机号">
</div>
<div class="form-group">
<label>密码</label>
<input type="password" class="form-control" maxlength="20" id="password"
placeholder="请输入密码">
</div>
<button type="button" id="btnOk" class="btn btn-primary">确认</button>
<button type="button" id="btnLoading" class="btn btn-primary" disabled style="display: none">
<span class="spinner-grow spinner-grow-sm" role="status" aria-hidden="true"></span>
执行中...
</button>
</form>
</div>
</div>
</div>
</div>
</div>
<script type="text/javascript" src="/assets/bootstrap/js/jquery.min.js"></script>
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap.min.js"></script>
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-maxlength/bootstrap-maxlength.min.js"></script>
<script type="text/javascript" src="/assets/bootstrap/js/jquery-confirm/jquery-confirm.min.js"></script>
<script type="text/javascript" src="/assets/bootstrap/js/bootstrap-multitabs/multitabs.min.js"></script>
<script type="text/javascript" src="/assets/bootstrap/js/httpclient/httpclient.js"></script>
<script type="text/javascript" src="/assets/bootstrap/js/authorization/md5.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
$("input#username").maxlength({
warningClass: "badge badge-info",
limitReachedClass: "badge badge-warning"
});
$("input#nickname").maxlength({
warningClass: "badge badge-info",
limitReachedClass: "badge badge-warning"
});
$("input#mobile").maxlength({
warningClass: "badge badge-info",
limitReachedClass: "badge badge-warning"
});
$("input#password").maxlength({
warningClass: "badge badge-info",
limitReachedClass: "badge badge-warning"
});
$('#btnOk').on('click', function () {
const username = $("#username").val();
if (username === "") {
$.alert({
title: '温馨提示',
icon: 'mdi mdi-alert',
type: 'orange',
content: '请输入用户名。',
});
return false;
}
const nickname = $("#nickname").val();
if (nickname === "") {
$.alert({
title: '温馨提示',
icon: 'mdi mdi-alert',
type: 'orange',
content: '请输入昵称。',
});
return false;
}
const password = $("#password").val();
if (password === "") {
$.alert({
title: '温馨提示',
icon: 'mdi mdi-alert',
type: 'orange',
content: '请输入密码。',
});
return false;
}
const postData = {
username: username,
nickname: nickname,
mobile: $("#mobile").val(),
password: md5(password),
};
AjaxForm(
"POST",
"/api/admin",
postData,
function () {
$(this).hide();
$("#btnLoading").show();
},
function (data) {
$("#btnLoading").hide();
$("#btnOk").show();
$.alert({
title: '操作成功',
icon: 'mdi mdi-check-decagram',
type: 'green',
content: '编号:' + data.id + ' 创建完成。',
buttons: {
okay: {
text: '关闭',
action: function () {
location.href = "/admin/list";
}
}
}
});
},
function (response) {
$("#btnLoading").hide();
$("#btnOk").show();
AjaxError(response);
}
);
});
})
</script>
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More