├── app
├── model
│ ├── menu_meta.go
│ ├── role_menu.go
│ ├── role_menu_auto_create.go
│ ├── role_name_auto_create.go
│ ├── menu_meta_auto_create.go
│ ├── policy_name_auto_create.go
│ ├── menu_auto_create.go
│ ├── user_auto_create.go
│ ├── model.go
│ ├── user.go
│ ├── policy.go
│ ├── role.go
│ ├── casbin_adapter.go
│ └── menu.go
├── service
│ └── baseService.go
└── api
│ ├── baseController.go
│ ├── policyController.go
│ ├── roleController.go
│ ├── menuController.go
│ ├── userController.go
│ └── auth.go
├── static
├── robots.txt
├── img
│ ├── 401.089007e7.gif
│ ├── 404.a57b6f31.png
│ └── 404_cloud.0f4bc32b.png
├── fonts
│ ├── element-icons.6f0a7632.ttf
│ └── element-icons.2fad952a.woff
├── css
│ ├── chunk-296d0504.a19c2bc2.css
│ ├── chunk-2e555135.76ea626a.css
│ ├── chunk-3296490b.9d63d053.css
│ ├── chunk-7670121b.9d63d053.css
│ ├── chunk-6a4eb3ee.50ac9a65.css
│ ├── chunk-cbf46a0a.c19e23ad.css
│ ├── chunk-libs.3dfb7769.css
│ ├── chunk-2a330e22.d5adff47.css
│ ├── chunk-015d6b7a.0a66699f.css
│ └── chunk-508832c0.fed07099.css
└── js
│ ├── chunk-2d230fe7.9bb0c7e2.js
│ ├── chunk-2d2105d3.ce6e26e5.js
│ ├── chunk-508832c0.eea072a2.js
│ ├── chunk-2e555135.9e9541fc.js
│ ├── chunk-cbf46a0a.daf42114.js
│ ├── chunk-2a330e22.9d637d72.js
│ ├── chunk-296d0504.61c10fec.js
│ ├── chunk-015d6b7a.3faa4a94.js
│ ├── chunk-3296490b.44372469.js
│ ├── chunk-7670121b.23245917.js
│ └── chunk-6a4eb3ee.9b859229.js
├── docfile
├── showApiWithSwagger.bat
├── gadmin.png
├── tools
│ └── codeCreater
│ │ └── xorm
│ │ ├── templates
│ │ ├── extend
│ │ │ ├── extend.go.tpl
│ │ │ └── config
│ │ └── struct
│ │ │ ├── config
│ │ │ └── structs.go.tpl
│ │ ├── create_extend.bat
│ │ ├── create_struct.bat
│ │ └── readme.txt
├── sql
│ ├── role_menu.sql
│ ├── role_name.sql
│ ├── policy_name.sql
│ ├── menu_meta.sql
│ ├── casbin_rule.sql
│ ├── menu.sql
│ ├── user.sql
│ └── all.sql
└── swagger.yaml
├── favicon.ico
├── vendor.bat
├── library
├── code
│ └── code.go
├── timer
│ └── timer.go
├── logger
│ └── logger.go
└── common
│ ├── common.go
│ └── rsa.go
├── go.mod
├── .gitignore
├── config
├── rbac.conf
└── config.default.toml
├── main.go
├── readme.md
├── index.html
├── router
└── router.go
└── go.sum
/app/model/menu_meta.go:
--------------------------------------------------------------------------------
1 | package model
2 |
--------------------------------------------------------------------------------
/app/service/baseService.go:
--------------------------------------------------------------------------------
1 | package service
2 |
--------------------------------------------------------------------------------
/static/robots.txt:
--------------------------------------------------------------------------------
1 | User-agent: *
2 | Disallow: /
--------------------------------------------------------------------------------
/docfile/showApiWithSwagger.bat:
--------------------------------------------------------------------------------
1 | swagger serve -F=swagger swagger.yaml
--------------------------------------------------------------------------------
/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hailaz/gadmin/HEAD/favicon.ico
--------------------------------------------------------------------------------
/docfile/gadmin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hailaz/gadmin/HEAD/docfile/gadmin.png
--------------------------------------------------------------------------------
/docfile/tools/codeCreater/xorm/templates/extend/extend.go.tpl:
--------------------------------------------------------------------------------
1 | package {{.Models}}
2 |
3 |
--------------------------------------------------------------------------------
/static/img/401.089007e7.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hailaz/gadmin/HEAD/static/img/401.089007e7.gif
--------------------------------------------------------------------------------
/static/img/404.a57b6f31.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hailaz/gadmin/HEAD/static/img/404.a57b6f31.png
--------------------------------------------------------------------------------
/vendor.bat:
--------------------------------------------------------------------------------
1 | @echo off
2 | echo will delete vendor dir...
3 | rd /s vendor
4 | go mod vendor
5 | @pause
--------------------------------------------------------------------------------
/docfile/tools/codeCreater/xorm/templates/extend/config:
--------------------------------------------------------------------------------
1 | lang=go
2 | genJson=1
3 | prefix=cos_
4 | postfix=
--------------------------------------------------------------------------------
/static/img/404_cloud.0f4bc32b.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hailaz/gadmin/HEAD/static/img/404_cloud.0f4bc32b.png
--------------------------------------------------------------------------------
/static/fonts/element-icons.6f0a7632.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hailaz/gadmin/HEAD/static/fonts/element-icons.6f0a7632.ttf
--------------------------------------------------------------------------------
/docfile/tools/codeCreater/xorm/templates/struct/config:
--------------------------------------------------------------------------------
1 | lang=go
2 | genJson=1
3 | genOrmType=
4 | prefix=cos_
5 | postfix=_auto_create
--------------------------------------------------------------------------------
/static/fonts/element-icons.2fad952a.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/hailaz/gadmin/HEAD/static/fonts/element-icons.2fad952a.woff
--------------------------------------------------------------------------------
/docfile/tools/codeCreater/xorm/create_extend.bat:
--------------------------------------------------------------------------------
1 | xorm reverse mysql root:root123@tcp(localhost:33061)/gadmin?charset=utf8 .\templates\extend .\model
--------------------------------------------------------------------------------
/library/code/code.go:
--------------------------------------------------------------------------------
1 | package code
2 |
3 | const (
4 | RESPONSE_ERROR = -1
5 | RESPONSE_IllegalToken = 50008
6 | RESPONSE_SUCCESS = 20000
7 | )
8 |
--------------------------------------------------------------------------------
/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/hailaz/gadmin
2 |
3 | go 1.12
4 |
5 | require (
6 | github.com/casbin/casbin v1.9.1
7 | github.com/gogf/gf v1.11.3
8 | github.com/gogf/gf-jwt v1.1.0
9 | )
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | docfile/tools/codeCreater/xorm/model/*
2 |
3 | #编译的可执行文件
4 | *.exe
5 | *.exe~
6 |
7 | #日志文件
8 | *.log
9 |
10 |
11 | debug
12 | .vscode/*
13 | .idea/*
14 | run.bat
15 | mod.bat
16 | config/config.toml
17 | debug.bat
18 |
--------------------------------------------------------------------------------
/docfile/tools/codeCreater/xorm/create_struct.bat:
--------------------------------------------------------------------------------
1 | xorm reverse mysql root:root123@tcp(localhost:33061)/gadmin?charset=utf8 .\templates\struct .\model
2 | ::xorm reverse mysql root:root123@tcp(localhost:33061)/gadmin?charset=utf8 .\templates\struct .\models "^xxx$|^xxx$|^xxx$"
3 | @pause
--------------------------------------------------------------------------------
/static/css/chunk-296d0504.a19c2bc2.css:
--------------------------------------------------------------------------------
1 | .pagination-container[data-v-f3b72548]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-f3b72548]{display:none}.edit-input[data-v-b1948282]{padding-right:100px}.cancel-btn[data-v-b1948282]{position:absolute;right:15px;top:10px}
--------------------------------------------------------------------------------
/config/rbac.conf:
--------------------------------------------------------------------------------
1 | [request_definition]
2 | r = sub, obj, act
3 |
4 | [policy_definition]
5 | p = sub, obj, act
6 |
7 | [role_definition]
8 | g = _, _
9 |
10 | [policy_effect]
11 | e = some(where (p.eft == allow))
12 |
13 | [matchers]
14 | m = (g(r.sub, p.sub)||keyMatch(r.sub, p.sub)) && keyMatch(r.obj, p.obj) && regexMatch(r.act, p.act)
--------------------------------------------------------------------------------
/library/timer/timer.go:
--------------------------------------------------------------------------------
1 | package timer
2 |
3 | import (
4 | "time"
5 |
6 | "github.com/gogf/gf/os/gtimer"
7 | "github.com/hailaz/gadmin/library/common"
8 | )
9 |
10 | // InitTimer 初始化定时任务
11 | //
12 | // createTime:2019年04月24日 14:50:34
13 | // author:hailaz
14 | func InitTimer() {
15 |
16 | gtimer.Add(time.Minute, common.RemoveTimeoutCryptoKey)
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/config/config.default.toml:
--------------------------------------------------------------------------------
1 | #监听端口
2 | port = 8199
3 |
4 | #日志目录,默认log目录
5 | logpath = "log"
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | #数据库
14 | [database]
15 | [[database.default]]
16 | host = "localhost"
17 | port = "33061"
18 | user = "root"
19 | pass = "root123"
20 | name = "gadmin"
21 | type = "mysql"
--------------------------------------------------------------------------------
/static/js/chunk-2d230fe7.9bb0c7e2.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d230fe7"],{ef3c:function(e,r,n){"use strict";n.r(r);n("a481");var t,u,a={created:function(){var e=this.$route,r=e.params,n=e.query,t=r.path;this.$router.replace({path:"/"+t,query:n})},render:function(e){return e()}},c=a,o=n("2877"),p=Object(o["a"])(c,t,u,!1,null,null,null);r["default"]=p.exports}}]);
--------------------------------------------------------------------------------
/library/logger/logger.go:
--------------------------------------------------------------------------------
1 | package logger
2 |
3 | import (
4 | "github.com/gogf/gf/frame/g"
5 | "github.com/gogf/gf/os/glog"
6 | )
7 |
8 | // InitLogger 初始化日志设置
9 | //
10 | // createTime:2019年05月13日 09:46:02
11 | // author:hailaz
12 | func InitLogger() {
13 | path := g.Config().GetString("logpath", "log")
14 | glog.SetPath(path)
15 | glog.SetFlags(glog.F_TIME_STD | glog.F_FILE_SHORT)
16 | }
17 |
--------------------------------------------------------------------------------
/static/js/chunk-2d2105d3.ce6e26e5.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2d2105d3"],{b829:function(n,e,o){"use strict";o.r(e);o("386d");var t,c,a={name:"AuthRedirect",created:function(){var n=window.location.search.slice(1);window.localStorage&&(window.localStorage.setItem("x-admin-oauth-code",n),window.close())},render:function(n){return n()}},d=a,i=o("2877"),l=Object(i["a"])(d,t,c,!1,null,null,null);e["default"]=l.exports}}]);
--------------------------------------------------------------------------------
/library/common/common.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "strings"
5 |
6 | "github.com/hailaz/gadmin/app/model"
7 | )
8 |
9 | func GetAction(act string) string {
10 | acts := strings.Split(strings.Split(strings.Split(act, ";")[0], ":")[0], ",")
11 | action := ""
12 | for _, v := range acts {
13 | if v == "All" || v == "REST" {
14 | return model.ACTION_ALL
15 | }
16 | if action == "" {
17 | action += strings.ToUpper("(" + v + ")")
18 | } else {
19 | action += strings.ToUpper("|(" + v + ")")
20 | }
21 |
22 | }
23 | return action
24 | }
25 |
--------------------------------------------------------------------------------
/app/model/role_menu.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "github.com/gogf/gf/database/gdb"
5 | )
6 |
7 | // DeleteRoleMenus description
8 | //
9 | // createTime:2019年05月21日 17:52:06
10 | // author:hailaz
11 | func DeleteRoleMenus(role string) {
12 | defDB.Delete("role_menu", "role_key=?", role)
13 | }
14 |
15 | // SetRoleMenus description
16 | //
17 | // createTime:2019年05月21日 17:54:38
18 | // author:hailaz
19 | func SetRoleMenus(role string, menus []string) {
20 | DeleteRoleMenus(role)
21 | ms := make(gdb.List, 0)
22 | for _, item := range menus {
23 | ms = append(ms, gdb.Map{"role_key": role, "menu_name": item})
24 | }
25 |
26 | defDB.Table("role_menu").Data(ms).Insert()
27 | }
28 |
--------------------------------------------------------------------------------
/docfile/tools/codeCreater/xorm/readme.txt:
--------------------------------------------------------------------------------
1 | 使用xorm工具,根据数据库自动生成 go 代码 - artong0416 - 博客园 https://www.cnblogs.com/artong0416/p/7456674.html
2 | go get github.com/go-xorm/cmd/xorm
3 |
4 | go get github.com/go-sql-driver/mysql //MyMysql
5 | go get github.com/ziutek/mymysql/godrv //MyMysql
6 | go get github.com/lib/pq //Postgres
7 | go get github.com/mattn/go-sqlite3 //SQLite
8 |
9 | go get github.com/go-xorm/xorm
10 |
11 |
12 | 编译github.com/go-xorm/cmd/xorm时需要cloud.google.com/go/civil
13 | 但因墙无法下载,所以手动使用以下地址:
14 | https://github.com/GoogleCloudPlatform/google-cloud-go
15 |
16 | git clone https://github.com/GoogleCloudPlatform/google-cloud-go.git
17 |
18 |
19 | 环境配置好后使用
20 | build.go
21 | created.bat即可
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/static/css/chunk-2e555135.76ea626a.css:
--------------------------------------------------------------------------------
1 | .errPage-container[data-v-2c77c6fb]{width:800px;max-width:100%;margin:100px auto}.errPage-container .pan-back-btn[data-v-2c77c6fb]{background:#008489;color:#fff;border:none!important}.errPage-container .pan-gif[data-v-2c77c6fb]{margin:0 auto;display:block}.errPage-container .pan-img[data-v-2c77c6fb]{display:block;margin:0 auto;width:100%}.errPage-container .text-jumbo[data-v-2c77c6fb]{font-size:60px;font-weight:700;color:#484848}.errPage-container .list-unstyled[data-v-2c77c6fb]{font-size:14px}.errPage-container .list-unstyled li[data-v-2c77c6fb]{padding-bottom:5px}.errPage-container .list-unstyled a[data-v-2c77c6fb]{color:#008489;text-decoration:none}.errPage-container .list-unstyled a[data-v-2c77c6fb]:hover{text-decoration:underline}
--------------------------------------------------------------------------------
/static/css/chunk-3296490b.9d63d053.css:
--------------------------------------------------------------------------------
1 | .waves-ripple{position:absolute;border-radius:100%;background-color:rgba(0,0,0,.15);background-clip:padding-box;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transform:scale(0);transform:scale(0);opacity:1}.waves-ripple.z-active{opacity:0;-webkit-transform:scale(2);transform:scale(2);-webkit-transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out,-webkit-transform .6s ease-out}.pagination-container[data-v-f3b72548]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-f3b72548]{display:none}
--------------------------------------------------------------------------------
/static/css/chunk-7670121b.9d63d053.css:
--------------------------------------------------------------------------------
1 | .waves-ripple{position:absolute;border-radius:100%;background-color:rgba(0,0,0,.15);background-clip:padding-box;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transform:scale(0);transform:scale(0);opacity:1}.waves-ripple.z-active{opacity:0;-webkit-transform:scale(2);transform:scale(2);-webkit-transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out,-webkit-transform .6s ease-out}.pagination-container[data-v-f3b72548]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-f3b72548]{display:none}
--------------------------------------------------------------------------------
/static/css/chunk-6a4eb3ee.50ac9a65.css:
--------------------------------------------------------------------------------
1 | .waves-ripple{position:absolute;border-radius:100%;background-color:rgba(0,0,0,.15);background-clip:padding-box;pointer-events:none;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-webkit-transform:scale(0);transform:scale(0);opacity:1}.waves-ripple.z-active{opacity:0;-webkit-transform:scale(2);transform:scale(2);-webkit-transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,-webkit-transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out;transition:opacity 1.2s ease-out,transform .6s ease-out,-webkit-transform .6s ease-out}.pagination-container[data-v-f3b72548]{background:#fff;padding:32px 16px}.pagination-container.hidden[data-v-f3b72548]{display:none}.app-container .permission-tree[data-v-0c8289ae]{margin-bottom:30px}
--------------------------------------------------------------------------------
/docfile/sql/role_menu.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : localhost
5 | Source Server Type : MySQL
6 | Source Server Version : 50542
7 | Source Host : localhost:33061
8 | Source Schema : gadmin
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 50542
12 | File Encoding : 65001
13 |
14 | Date: 16/05/2019 15:10:35
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for role_menu
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `role_menu`;
24 | CREATE TABLE `role_menu` (
25 | `id` int(11) NOT NULL AUTO_INCREMENT,
26 | `role_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色key',
27 | `menu_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单关键名',
28 | PRIMARY KEY (`id`) USING BTREE
29 | ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
30 |
31 | SET FOREIGN_KEY_CHECKS = 1;
32 |
--------------------------------------------------------------------------------
/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "github.com/gogf/gf/frame/g"
5 | "github.com/gogf/gf/os/gcmd"
6 | "github.com/gogf/gf/os/gfile"
7 | "github.com/gogf/gf/os/glog"
8 | "github.com/hailaz/gadmin/app/model"
9 | "github.com/hailaz/gadmin/library/logger"
10 | "github.com/hailaz/gadmin/library/timer"
11 | "github.com/hailaz/gadmin/router"
12 | )
13 |
14 | func init() {
15 | cfg := gcmd.GetOpt("c", "config.default.toml")
16 |
17 | if !gfile.Exists(cfg) && !gfile.Exists("config/"+cfg) {
18 | glog.Fatalf("config file(%s) no exist", cfg)
19 | }
20 |
21 | // 设置默认配置文件,默认的 config.toml 将会被覆盖
22 | g.Config().SetFileName(cfg)
23 |
24 | // 初始化日志
25 | logger.InitLogger()
26 |
27 | // 测试数据库
28 | err := g.DB().PingMaster()
29 | if err != nil {
30 | glog.Fatalf("DB err:%v", err)
31 | }
32 |
33 | // 初始化数据库
34 | model.InitModel()
35 |
36 | timer.InitTimer()
37 |
38 | }
39 |
40 | func main() {
41 | s := g.Server()
42 | s.SetIndexFolder(false)
43 | s.SetIndexFiles([]string{"index.html"})
44 | s.SetServerRoot(".")
45 | // 初始化路由
46 | router.InitRouter(s)
47 |
48 | s.SetPort(g.Config().GetInt("port", 8080))
49 | s.Run()
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/docfile/sql/role_name.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : localhost
5 | Source Server Type : MySQL
6 | Source Server Version : 50542
7 | Source Host : localhost:33061
8 | Source Schema : gadmin
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 50542
12 | File Encoding : 65001
13 |
14 | Date: 16/05/2019 15:07:50
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for role_name
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `role_name`;
24 | CREATE TABLE `role_name` (
25 | `id` int(11) NOT NULL AUTO_INCREMENT,
26 | `role_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '角色key',
27 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '角色名',
28 | `descrption` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '描述',
29 | PRIMARY KEY (`id`) USING BTREE,
30 | UNIQUE INDEX `role_key_index`(`role_key`) USING BTREE
31 | ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
32 |
33 | SET FOREIGN_KEY_CHECKS = 1;
34 |
--------------------------------------------------------------------------------
/docfile/sql/policy_name.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : localhost
5 | Source Server Type : MySQL
6 | Source Server Version : 50542
7 | Source Host : localhost:33061
8 | Source Schema : gadmin
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 50542
12 | File Encoding : 65001
13 |
14 | Date: 16/05/2019 15:07:34
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for policy_name
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `policy_name`;
24 | CREATE TABLE `policy_name` (
25 | `id` int(11) NOT NULL AUTO_INCREMENT,
26 | `full_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '权限完整路径',
27 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '权限名称',
28 | `descrption` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT '' COMMENT '描述',
29 | PRIMARY KEY (`id`) USING BTREE,
30 | UNIQUE INDEX `full_path_index`(`full_path`) USING BTREE
31 | ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
32 |
33 | SET FOREIGN_KEY_CHECKS = 1;
34 |
--------------------------------------------------------------------------------
/docfile/sql/menu_meta.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : localhost
5 | Source Server Type : MySQL
6 | Source Server Version : 50542
7 | Source Host : localhost:33061
8 | Source Schema : gadmin
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 50542
12 | File Encoding : 65001
13 |
14 | Date: 16/05/2019 15:57:56
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for menu_meta
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `menu_meta`;
24 | CREATE TABLE `menu_meta` (
25 | `id` int(11) NOT NULL AUTO_INCREMENT,
26 | `menu_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单关键名',
27 | `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名称',
28 | `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '图标',
29 | `nocache` tinyint(1) NULL DEFAULT 0 COMMENT '是否缓存',
30 | PRIMARY KEY (`id`) USING BTREE,
31 | UNIQUE INDEX `key_name`(`menu_name`) USING BTREE
32 | ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
33 |
34 | SET FOREIGN_KEY_CHECKS = 1;
35 |
--------------------------------------------------------------------------------
/readme.md:
--------------------------------------------------------------------------------
1 | #### 项目不定期更新
2 |
3 |
4 | ### 简要说明
5 |
6 | 基于GoFrame框架的前后端分离管理后台,项目首次启动会自动插入管理员用户。
7 |
8 | #### 使用方式
9 |
10 | 1. 准备数据库,数据结构在[docfile/sql](https://github.com/hailaz/gadmin/tree/master/docfile/sql)目录下,all.sql是全部结构。
11 | 2. 修改配置文件config/default.toml,也可指定其它配置文件 -c=xxx.toml
12 | 3. 启动编译后的二进制文件
13 | 4. 访问[http://localhost:8199](http://localhost:8199)
14 | 用户名:admin
15 | 密码:123456
16 |
17 | **当前项目已包含构建后的前端文件。** 未构建的前端项目地址:[gadmin-vue](https://github.com/hailaz/gadmin-vue)
18 |
19 | #### 自述
20 | 第一次设计,整体结构可能有些问题,望见谅,要是能给我个建议什么的就更好了。有bug可以提个issues。
21 |
22 | 
23 |
24 |
25 | ----
26 |
27 | ### 技术栈
28 |
29 | #### 后端
30 |
31 | 框架:[GoFrame](https://github.com/gogf/gf)
32 |
33 | 登录加密:RSA
34 |
35 | 权限管理:[Casbin](https://github.com/casbin/casbin)的RBAC-restful
36 |
37 | API授权方式:JWT,使用[gf-jwt](https://github.com/gogf/gf-jwt)
38 |
39 | ----
40 | #### 前端
41 | 框架:[vue-element-admin](https://github.com/PanJiaChen/vue-element-admin)
42 |
43 | ----
44 | ----
45 | ### 如何访问接口文档?
46 |
47 | 访问[https://petstore.swagger.io](https://petstore.swagger.io/?url=https://raw.githubusercontent.com/hailaz/gadmin/master/docfile/swagger.yaml)查看。
48 |
49 | 或者启动项目后访问[http://localhost:8199/swagger](http://localhost:8199/swagger)显示接口文档。
50 |
51 | 或将docfile目录下的swagger.yaml文件内容复制到[http://editor.swagger.io](http://editor.swagger.io)查看。
52 |
53 |
54 |
--------------------------------------------------------------------------------
/app/model/role_menu_auto_create.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | // RoleMenu 表名:role_menu
8 | // 由数据库自动生成的结构体
9 | type RoleMenu struct {
10 | Id int64 `json:"id"` //
11 | RoleKey string `json:"role_key"` //角色key
12 | MenuName string `json:"menu_name"` //菜单关键名
13 | }
14 |
15 | // TableName 获取表名
16 | func (t *RoleMenu) TableName() string {
17 | return "role_menu"
18 | }
19 |
20 | // Insert 插入一条记录
21 | func (t *RoleMenu) Insert() (int64, error) {
22 | r, err := defDB.Insert("role_menu", t)
23 | if err != nil {
24 | return 0, err
25 | }
26 | id, err := r.LastInsertId()
27 | t.Id = id
28 | return id, err
29 | }
30 |
31 | // Update 更新对象
32 | func (t *RoleMenu) Update() (int64, error) {
33 | if t.Id <= 0 {
34 | return 0, errors.New("primary_key <= 0")
35 | }
36 | r, err := defDB.Update("role_menu", t, "id=?", t.Id)
37 | if err != nil {
38 | return 0, err
39 | }
40 | return r.RowsAffected()
41 | }
42 |
43 | // DeleteById 删除一条记录
44 | func (t *RoleMenu) DeleteById(id int64) (int64, error) {
45 | r, err := defDB.Delete("role_menu", "id=?", id)
46 | if err != nil {
47 | return 0, err
48 | }
49 | return r.RowsAffected()
50 | }
51 |
52 | // GetById 通过id查询记录
53 | func (t *RoleMenu) GetById(id int64) (RoleMenu, error) {
54 | obj := RoleMenu{}
55 | err := defDB.Table("role_menu").Where("id", id).Struct(&obj)
56 | return obj, err
57 | }
58 |
--------------------------------------------------------------------------------
/app/model/role_name_auto_create.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | // RoleName 表名:role_name
8 | // 由数据库自动生成的结构体
9 | type RoleName struct {
10 | Id int64 `json:"id"` //
11 | RoleKey string `json:"role_key"` //角色key
12 | Name string `json:"name"` //角色名
13 | Descrption string `json:"descrption"` //描述
14 | }
15 |
16 | // TableName 获取表名
17 | func (t *RoleName) TableName() string {
18 | return "role_name"
19 | }
20 |
21 | // Insert 插入一条记录
22 | func (t *RoleName) Insert() (int64, error) {
23 | r, err := defDB.Insert("role_name", t)
24 | if err != nil {
25 | return 0, err
26 | }
27 | id, err := r.LastInsertId()
28 | t.Id = id
29 | return id, err
30 | }
31 |
32 | // Update 更新对象
33 | func (t *RoleName) Update() (int64, error) {
34 | if t.Id <= 0 {
35 | return 0, errors.New("primary_key <= 0")
36 | }
37 | r, err := defDB.Update("role_name", t, "id=?", t.Id)
38 | if err != nil {
39 | return 0, err
40 | }
41 | return r.RowsAffected()
42 | }
43 |
44 | // DeleteById 删除一条记录
45 | func (t *RoleName) DeleteById(id int64) (int64, error) {
46 | r, err := defDB.Delete("role_name", "id=?", id)
47 | if err != nil {
48 | return 0, err
49 | }
50 | return r.RowsAffected()
51 | }
52 |
53 | // GetById 通过id查询记录
54 | func (t *RoleName) GetById(id int64) (RoleName, error) {
55 | obj := RoleName{}
56 | err := defDB.Table("role_name").Where("id", id).Struct(&obj)
57 | return obj, err
58 | }
59 |
--------------------------------------------------------------------------------
/app/model/menu_meta_auto_create.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | // MenuMeta 表名:menu_meta
8 | // 由数据库自动生成的结构体
9 | type MenuMeta struct {
10 | Id int64 `json:"id"` //
11 | MenuName string `json:"menu_name"` //菜单关键名
12 | Title string `json:"title"` //名称
13 | Icon string `json:"icon"` //图标
14 | Nocache bool `json:"noCache"` //是否缓存
15 | }
16 |
17 | // TableName 获取表名
18 | func (t *MenuMeta) TableName() string {
19 | return "menu_meta"
20 | }
21 |
22 | // Insert 插入一条记录
23 | func (t *MenuMeta) Insert() (int64, error) {
24 | r, err := defDB.Insert("menu_meta", t)
25 | if err != nil {
26 | return 0, err
27 | }
28 | id, err := r.LastInsertId()
29 | t.Id = id
30 | return id, err
31 | }
32 |
33 | // Update 更新对象
34 | func (t *MenuMeta) Update() (int64, error) {
35 | if t.Id <= 0 {
36 | return 0, errors.New("primary_key <= 0")
37 | }
38 | r, err := defDB.Update("menu_meta", t, "id=?", t.Id)
39 | if err != nil {
40 | return 0, err
41 | }
42 | return r.RowsAffected()
43 | }
44 |
45 | // DeleteById 删除一条记录
46 | func (t *MenuMeta) DeleteById(id int64) (int64, error) {
47 | r, err := defDB.Delete("menu_meta", "id=?", id)
48 | if err != nil {
49 | return 0, err
50 | }
51 | return r.RowsAffected()
52 | }
53 |
54 | // GetById 通过id查询记录
55 | func (t *MenuMeta) GetById(id int64) (MenuMeta, error) {
56 | obj := MenuMeta{}
57 | err := defDB.Table("menu_meta").Where("id", id).Struct(&obj)
58 | return obj, err
59 | }
60 |
--------------------------------------------------------------------------------
/app/model/policy_name_auto_create.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | // PolicyName 表名:policy_name
8 | // 由数据库自动生成的结构体
9 | type PolicyName struct {
10 | Id int64 `json:"id"` //
11 | FullPath string `json:"full_path"` //权限完整路径
12 | Name string `json:"name"` //权限名称
13 | Descrption string `json:"descrption"` //描述
14 | }
15 |
16 | // TableName 获取表名
17 | func (t *PolicyName) TableName() string {
18 | return "policy_name"
19 | }
20 |
21 | // Insert 插入一条记录
22 | func (t *PolicyName) Insert() (int64, error) {
23 | r, err := defDB.Insert("policy_name", t)
24 | if err != nil {
25 | return 0, err
26 | }
27 | id, err := r.LastInsertId()
28 | t.Id = id
29 | return id, err
30 | }
31 |
32 | // Update 更新对象
33 | func (t *PolicyName) Update() (int64, error) {
34 | if t.Id <= 0 {
35 | return 0, errors.New("primary_key <= 0")
36 | }
37 | r, err := defDB.Update("policy_name", t, "id=?", t.Id)
38 | if err != nil {
39 | return 0, err
40 | }
41 | return r.RowsAffected()
42 | }
43 |
44 | // DeleteById 删除一条记录
45 | func (t *PolicyName) DeleteById(id int64) (int64, error) {
46 | r, err := defDB.Delete("policy_name", "id=?", id)
47 | if err != nil {
48 | return 0, err
49 | }
50 | return r.RowsAffected()
51 | }
52 |
53 | // GetById 通过id查询记录
54 | func (t *PolicyName) GetById(id int64) (PolicyName, error) {
55 | obj := PolicyName{}
56 | err := defDB.Table("policy_name").Where("id", id).Struct(&obj)
57 | return obj, err
58 | }
59 |
--------------------------------------------------------------------------------
/docfile/sql/casbin_rule.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : home.xiao3.top
5 | Source Server Type : MySQL
6 | Source Server Version : 50643
7 | Source Host : home.xiao3.top:3306
8 | Source Schema : mixweb
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 50643
12 | File Encoding : 65001
13 |
14 | Date: 23/04/2019 09:04:12
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for casbin_rule
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `casbin_rule`;
24 | CREATE TABLE `casbin_rule` (
25 | `id` int(11) NOT NULL AUTO_INCREMENT,
26 | `p_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
27 | `v0` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
28 | `v1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
29 | `v2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
30 | `v3` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
31 | `v4` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
32 | `v5` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
33 | PRIMARY KEY (`id`) USING BTREE
34 | ) ENGINE = InnoDB AUTO_INCREMENT = 181 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
35 |
36 | SET FOREIGN_KEY_CHECKS = 1;
37 |
--------------------------------------------------------------------------------
/app/api/baseController.go:
--------------------------------------------------------------------------------
1 | package api
2 |
3 | import (
4 | jwt "github.com/gogf/gf-jwt"
5 | "github.com/gogf/gf/frame/gmvc"
6 | "github.com/gogf/gf/net/ghttp"
7 | "github.com/hailaz/gadmin/app/model"
8 | "github.com/hailaz/gadmin/library/code"
9 | )
10 |
11 | type BaseController struct {
12 | gmvc.Controller
13 | }
14 |
15 | // "析构函数"控制器方法
16 | func (c *BaseController) Shut() {
17 |
18 | }
19 |
20 | type BaseResult struct {
21 | Code int `json:"code"`
22 | Message string `json:"message"`
23 | Data interface{} `json:"data"`
24 | }
25 |
26 | // Response API返回
27 | //
28 | // createTime:2019年04月25日 11:32:47
29 | // author:hailaz
30 | func Response(r *ghttp.Request, rs BaseResult) {
31 | r.Response.WriteJson(rs)
32 | r.ExitAll()
33 | }
34 |
35 | // Success 返回成功
36 | //
37 | // createTime:2019年04月25日 11:41:44
38 | // author:hailaz
39 | func Success(r *ghttp.Request, data interface{}) {
40 | Response(r, BaseResult{Code: code.RESPONSE_SUCCESS, Message: "success", Data: data})
41 | }
42 |
43 | // Fail 返回失败
44 | //
45 | // createTime:2019年04月25日 11:43:34
46 | // author:hailaz
47 | func Fail(r *ghttp.Request, errCode int, msg ...string) {
48 | if len(msg) > 0 {
49 | Response(r, BaseResult{Code: errCode, Message: msg[0]})
50 | } else {
51 | Response(r, BaseResult{Code: errCode, Message: "fail"})
52 | }
53 |
54 | }
55 |
56 | // funcName 获取当前用户
57 | //
58 | // createTime:2019年05月13日 10:01:17
59 | // author:hailaz
60 | func (c *BaseController) GetUser() *model.User {
61 | claims := jwt.ExtractClaims(c.Request)
62 | user, _ := model.GetUserByName(claims["username"].(string))
63 | return user
64 | }
65 |
--------------------------------------------------------------------------------
/docfile/sql/menu.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : home.xiao3.top
5 | Source Server Type : MySQL
6 | Source Server Version : 50643
7 | Source Host : home.xiao3.top:3306
8 | Source Schema : gadmin
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 50643
12 | File Encoding : 65001
13 |
14 | Date: 21/06/2019 14:12:48
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for menu
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `menu`;
24 | CREATE TABLE `menu` (
25 | `id` int(11) NOT NULL AUTO_INCREMENT,
26 | `menu_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单路径',
27 | `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '页面模块',
28 | `redirect` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '重定向地址',
29 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '唯一关键名',
30 | `hidden` tinyint(1) NULL DEFAULT 0 COMMENT '是否隐藏',
31 | `alwaysshow` tinyint(1) NULL DEFAULT 0 COMMENT '是否常显示',
32 | `sort` tinyint(2) NULL DEFAULT 0 COMMENT '排序',
33 | `parent_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '父菜级关键名',
34 | `auto_create` tinyint(1) NULL DEFAULT 0 COMMENT '是否自动生成',
35 | PRIMARY KEY (`id`) USING BTREE,
36 | UNIQUE INDEX `key_name`(`name`) USING BTREE
37 | ) ENGINE = InnoDB AUTO_INCREMENT = 11 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
38 |
39 | SET FOREIGN_KEY_CHECKS = 1;
40 |
--------------------------------------------------------------------------------
/app/model/menu_auto_create.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 | )
6 |
7 | // Menu 表名:menu
8 | // 由数据库自动生成的结构体
9 | type Menu struct {
10 | Id int64 `json:"id"` //
11 | MenuPath string `json:"path"` //菜单路径
12 | Component string `json:"component"` //页面模块
13 | Redirect string `json:"redirect"` //重定向地址
14 | Name string `json:"name"` //唯一关键名
15 | Hidden bool `json:"hidden"` //是否隐藏
16 | Alwaysshow bool `json:"alwaysshow"` //是否常显示
17 | Sort int `json:"sort"` //排序
18 | ParentName string `json:"parent_name"` //父菜级关键名
19 | AutoCreate bool `json:"auto_create"` //是否自动生成
20 | MenuMeta MenuMeta `json:"meta"`
21 | }
22 |
23 | // TableName 获取表名
24 | func (t *Menu) TableName() string {
25 | return "menu"
26 | }
27 |
28 | // Insert 插入一条记录
29 | func (t *Menu) Insert() (int64, error) {
30 | r, err := defDB.Insert("menu", t)
31 | if err != nil {
32 | return 0, err
33 | }
34 | id, err := r.LastInsertId()
35 | t.Id = id
36 | return id, err
37 | }
38 |
39 | // Update 更新对象
40 | func (t *Menu) Update() (int64, error) {
41 | if t.Id <= 0 {
42 | return 0, errors.New("primary_key <= 0")
43 | }
44 | r, err := defDB.Update("menu", t, "id=?", t.Id)
45 | if err != nil {
46 | return 0, err
47 | }
48 | return r.RowsAffected()
49 | }
50 |
51 | // DeleteById 删除一条记录
52 | func (t *Menu) DeleteById(id int64) (int64, error) {
53 | r, err := defDB.Delete("menu", "id=?", id)
54 | if err != nil {
55 | return 0, err
56 | }
57 | return r.RowsAffected()
58 | }
59 |
60 | // GetById 通过id查询记录
61 | func (t *Menu) GetById(id int64) (Menu, error) {
62 | obj := Menu{}
63 | err := defDB.Table("menu").Where("id", id).Struct(&obj)
64 | return obj, err
65 | }
66 |
--------------------------------------------------------------------------------
/static/js/chunk-508832c0.eea072a2.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-508832c0"],{"1bc5":function(t,s,a){"use strict";var e=a("9beb"),c=a.n(e);c.a},"1db4":function(t,s,a){"use strict";a.r(s);var e=function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"wscn-http404-container"},[a("div",{staticClass:"wscn-http404"},[t._m(0),t._v(" "),a("div",{staticClass:"bullshit"},[a("div",{staticClass:"bullshit__oops"},[t._v("OOPS!")]),t._v(" "),t._m(1),t._v(" "),a("div",{staticClass:"bullshit__headline"},[t._v(t._s(t.message))]),t._v(" "),a("div",{staticClass:"bullshit__info"},[t._v("Please check that the URL you entered is correct, or click the button below to return to the homepage.")]),t._v(" "),a("a",{staticClass:"bullshit__return-home",attrs:{href:""}},[t._v("Back to home")])])])])},c=[function(){var t=this,s=t.$createElement,e=t._self._c||s;return e("div",{staticClass:"pic-404"},[e("img",{staticClass:"pic-404__parent",attrs:{src:a("a36b"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child left",attrs:{src:a("26fc"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child mid",attrs:{src:a("26fc"),alt:"404"}}),t._v(" "),e("img",{staticClass:"pic-404__child right",attrs:{src:a("26fc"),alt:"404"}})])},function(){var t=this,s=t.$createElement,a=t._self._c||s;return a("div",{staticClass:"bullshit__info"},[t._v("All rights reserved\n "),a("a",{staticStyle:{color:"#20a0ff"},attrs:{href:"https://wallstreetcn.com",target:"_blank"}},[t._v("wallstreetcn")])])}],i={name:"Page404",computed:{message:function(){return"The webmaster said that you can not enter this page..."}}},l=i,n=(a("1bc5"),a("2877")),r=Object(n["a"])(l,e,c,!1,null,"22c31b5a",null);s["default"]=r.exports},"26fc":function(t,s,a){t.exports=a.p+"static/img/404_cloud.0f4bc32b.png"},"9beb":function(t,s,a){},a36b:function(t,s,a){t.exports=a.p+"static/img/404.a57b6f31.png"}}]);
--------------------------------------------------------------------------------
/docfile/tools/codeCreater/xorm/templates/struct/structs.go.tpl:
--------------------------------------------------------------------------------
1 | package {{.Models}}
2 | import (
3 | {{$ilen := len .Imports}}
4 | {{if gt $ilen 0}}
5 |
6 | {{range .Imports}}"{{.}}"{{end}}
7 |
8 | {{end}}
9 | {{range .Tables}}
10 | {{if (PKIsId .)}}"errors"{{end}}
11 | "github.com/gogf/gf/os/gtime"
12 | )
13 | // {{Mapper .Name}} 表名:{{.Name}}
14 | // 由数据库自动生成的结构体
15 | type {{Mapper .Name}} struct { {{$table := .}}
16 | {{range .ColumnsSeq}}{{$col := $table.GetColumn .}} {{Mapper $col.Name}} {{Type $col}} {{Tag $table $col}}
17 | {{end}}}
18 |
19 |
20 |
21 | // TableName 获取表名
22 | func (t *{{Mapper .Name}}) TableName() string {
23 | return "{{.Name}}"
24 | }
25 |
26 | // Insert 插入一条记录
27 | func (t *{{Mapper .Name}}) Insert() (int64, error) {
28 | t.AddTime = gtime.Now().String()
29 | t.UpdateTime = gtime.Now().String()
30 | r, err := defDB.Insert("{{.Name}}", t)
31 | if err != nil {
32 | return 0, err
33 | }
34 | id, err := r.LastInsertId()
35 | t.Id = id
36 | return id, err
37 | }
38 | {{if not (PKIsId .)}}/*{{end}}
39 | // Update 更新对象
40 | func (t *{{Mapper .Name}}) Update() (int64, error) {
41 | if t.Id <= 0 {
42 | return 0, errors.New("primary_key <= 0")
43 | }
44 | t.UpdateTime = gtime.Now().String()
45 | r, err := defDB.Update("{{.Name}}", t, "id=?", t.Id)
46 | if err != nil {
47 | return 0, err
48 | }
49 | return r.RowsAffected()
50 | }
51 |
52 | // DeleteById 删除一条记录
53 | func (t *{{Mapper .Name}}) DeleteById(id int64) (int64, error) {
54 | r, err := defDB.Delete("{{.Name}}", "id=?", id)
55 | if err != nil {
56 | return 0, err
57 | }
58 | return r.RowsAffected()
59 | }
60 |
61 |
62 | // GetById 通过id查询记录
63 | func (t *{{Mapper .Name}}) GetById(id int64) ({{Mapper .Name}}, error) {
64 | obj := {{Mapper .Name}}{}
65 | err := defDB.Table("{{.Name}}").Where("id", id).Struct(&obj)
66 | return obj, err
67 | }
68 | {{if not (PKIsId .)}}*/{{end}}
69 | {{end}}
--------------------------------------------------------------------------------
/static/js/chunk-2e555135.9e9541fc.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2e555135"],{"24e2":function(t,a,i){"use strict";i.r(a);var e=function(){var t=this,a=t.$createElement,i=t._self._c||a;return i("div",{staticClass:"errPage-container"},[i("el-button",{staticClass:"pan-back-btn",attrs:{icon:"arrow-left"},on:{click:t.back}},[t._v("\n 返回\n ")]),t._v(" "),i("el-row",[i("el-col",{attrs:{span:12}},[i("h1",{staticClass:"text-jumbo text-ginormous"},[t._v("\n Oops!\n ")]),t._v("\n gif来源"),i("a",{attrs:{href:"https://zh.airbnb.com/",target:"_blank"}},[t._v("airbnb")]),t._v(" 页面\n "),i("h2",[t._v("你没有权限去该页面")]),t._v(" "),i("h6",[t._v("如有不满请联系你领导")]),t._v(" "),i("ul",{staticClass:"list-unstyled"},[i("li",[t._v("或者你可以去:")]),t._v(" "),i("li",{staticClass:"link-type"},[i("router-link",{attrs:{to:"/dashboard"}},[t._v("\n 回首页\n ")])],1),t._v(" "),i("li",{staticClass:"link-type"},[i("a",{attrs:{href:"https://www.taobao.com/"}},[t._v("随便看看")])]),t._v(" "),i("li",[i("a",{attrs:{href:"#"},on:{click:function(a){a.preventDefault(),t.dialogVisible=!0}}},[t._v("点我看图")])])])]),t._v(" "),i("el-col",{attrs:{span:12}},[i("img",{attrs:{src:t.errGif,width:"313",height:"428",alt:"Girl has dropped her ice cream."}})])],1),t._v(" "),i("el-dialog",{attrs:{visible:t.dialogVisible,title:"随便看"},on:{"update:visible":function(a){t.dialogVisible=a}}},[i("img",{staticClass:"pan-img",attrs:{src:t.ewizardClap}})])],1)},s=[],n=i("cc6c"),r=i.n(n),c={name:"Page401",data:function(){return{errGif:r.a+"?"+ +new Date,ewizardClap:"https://wpimg.wallstcn.com/007ef517-bafd-4066-aae4-6883632d9646",dialogVisible:!1}},methods:{back:function(){this.$route.query.noGoBack?this.$router.push({path:"/dashboard"}):this.$router.go(-1)}}},l=c,o=(i("efaf"),i("2877")),u=Object(o["a"])(l,e,s,!1,null,"2c77c6fb",null);a["default"]=u.exports},bbc8:function(t,a,i){},cc6c:function(t,a,i){t.exports=i.p+"static/img/401.089007e7.gif"},efaf:function(t,a,i){"use strict";var e=i("bbc8"),s=i.n(e);s.a}}]);
--------------------------------------------------------------------------------
/docfile/sql/user.sql:
--------------------------------------------------------------------------------
1 | /*
2 | Navicat Premium Data Transfer
3 |
4 | Source Server : localhost
5 | Source Server Type : MySQL
6 | Source Server Version : 50542
7 | Source Host : localhost:33061
8 | Source Schema : gadmin
9 |
10 | Target Server Type : MySQL
11 | Target Server Version : 50542
12 | File Encoding : 65001
13 |
14 | Date: 16/05/2019 15:07:55
15 | */
16 |
17 | SET NAMES utf8mb4;
18 | SET FOREIGN_KEY_CHECKS = 0;
19 |
20 | -- ----------------------------
21 | -- Table structure for user
22 | -- ----------------------------
23 | DROP TABLE IF EXISTS `user`;
24 | CREATE TABLE `user` (
25 | `id` int(11) NOT NULL AUTO_INCREMENT,
26 | `status` tinyint(1) NOT NULL DEFAULT 0 COMMENT '状态',
27 | `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户名',
28 | `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '昵称',
29 | `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '密码',
30 | `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '邮箱',
31 | `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '手机号',
32 | `sex` tinyint(6) NOT NULL DEFAULT 0 COMMENT '性别',
33 | `age` tinyint(6) NOT NULL DEFAULT 0 COMMENT '年龄',
34 | `add_time` datetime NOT NULL COMMENT '添加时间',
35 | `update_time` datetime NOT NULL COMMENT '修改时间',
36 | `add_user_id` int(11) NOT NULL DEFAULT 0 COMMENT '操作用户',
37 | `Introduction` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '介绍',
38 | `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '头像',
39 | PRIMARY KEY (`id`) USING BTREE,
40 | UNIQUE INDEX `username`(`user_name`) USING BTREE
41 | ) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
42 |
43 | SET FOREIGN_KEY_CHECKS = 1;
44 |
--------------------------------------------------------------------------------
/app/model/user_auto_create.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 |
6 | "github.com/gogf/gf/os/gtime"
7 | )
8 |
9 | // User 表名:user
10 | // 由数据库自动生成的结构体
11 | type User struct {
12 | Id int64 `json:"id"` //
13 | Status int `json:"status"` //状态
14 | UserName string `json:"user_name"` //用户名
15 | NickName string `json:"nick_name"` //昵称
16 | Password string `json:"password"` //密码
17 | Email string `json:"email"` //邮箱
18 | Phone string `json:"phone"` //手机号
19 | Sex int `json:"sex"` //性别
20 | Age int `json:"age"` //年龄
21 | AddTime string `json:"add_time"` //添加时间
22 | UpdateTime string `json:"update_time"` //修改时间
23 | AddUserId int64 `json:"add_user_id"` //操作用户
24 | Introduction string `json:"Introduction"` //介绍
25 | Avatar string `json:"avatar"` //头像
26 | }
27 |
28 | // TableName 获取表名
29 | func (t *User) TableName() string {
30 | return "user"
31 | }
32 |
33 | // Insert 插入一条记录
34 | func (t *User) Insert() (int64, error) {
35 | t.AddTime = gtime.Now().String()
36 | t.UpdateTime = gtime.Now().String()
37 | t.Password = EncryptPassword(t.Password)
38 | r, err := defDB.Insert("user", t)
39 | if err != nil {
40 | return 0, err
41 | }
42 | id, err := r.LastInsertId()
43 | t.Id = id
44 | return id, err
45 | }
46 |
47 | // Update 更新对象
48 | func (t *User) Update() (int64, error) {
49 | if t.Id <= 0 {
50 | return 0, errors.New("primary_key <= 0")
51 | }
52 | t.UpdateTime = gtime.Now().String()
53 | r, err := defDB.Update("user", t, "id=?", t.Id)
54 | if err != nil {
55 | return 0, err
56 | }
57 | return r.RowsAffected()
58 | }
59 |
60 | // DeleteById 删除一条记录
61 | func (t *User) DeleteById(id int64) (int64, error) {
62 | r, err := defDB.Delete("user", "id=?", id)
63 | if err != nil {
64 | return 0, err
65 | }
66 | return r.RowsAffected()
67 | }
68 |
69 | // GetById 通过id查询记录
70 | func (t *User) GetById(id int64) (User, error) {
71 | obj := User{}
72 | err := defDB.Table("user").Where("id", id).Struct(&obj)
73 | return obj, err
74 | }
75 |
--------------------------------------------------------------------------------
/app/api/policyController.go:
--------------------------------------------------------------------------------
1 | package api
2 |
3 | import (
4 | "fmt"
5 | "strings"
6 |
7 | "github.com/hailaz/gadmin/app/model"
8 | "github.com/hailaz/gadmin/library/code"
9 | )
10 |
11 | const (
12 | UNDEFIND_POLICY_NAME = "未命名"
13 | )
14 |
15 | type PolicyController struct {
16 | BaseController
17 | }
18 |
19 | func (c *PolicyController) Get() {
20 | page := c.Request.GetInt("page", 1)
21 | limit := c.Request.GetInt("limit", 10)
22 |
23 | var list struct {
24 | List []model.Policy `json:"items"`
25 | Total int `json:"total"`
26 | }
27 |
28 | list.List, list.Total = model.GetPolicyList(page, limit, UNDEFIND_POLICY_NAME)
29 |
30 | Success(c.Request, list)
31 | }
32 |
33 | func (c *PolicyController) Post() {
34 | Success(c.Request, "Post")
35 | }
36 |
37 | func (c *PolicyController) Put() {
38 | data, _ := c.Request.GetJson()
39 | name := data.GetString("name")
40 | path := data.GetString("policy")
41 | if name == UNDEFIND_POLICY_NAME {
42 | Fail(c.Request, code.RESPONSE_ERROR)
43 | } else {
44 | err := model.UpdatePolicyByFullPath(path, name)
45 | if err != nil {
46 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
47 | }
48 | }
49 | Success(c.Request, "修改成功")
50 | }
51 |
52 | func (c *PolicyController) Delete() {
53 | Success(c.Request, "Delete")
54 | }
55 |
56 | func (c *PolicyController) GetPolicyByRole() {
57 | role := c.Request.GetString("role")
58 | var list struct {
59 | List []model.Policy `json:"all_policy_items"`
60 | RolePolicyList []model.Policy `json:"role_policy_items"`
61 | Total int `json:"total"`
62 | }
63 |
64 | list.List, list.Total = model.GetPolicyList(1, -1, "")
65 | list.RolePolicyList = model.GetPolicyByRole(role)
66 |
67 | Success(c.Request, list)
68 | }
69 |
70 | func (c *PolicyController) SetPolicyByRole() {
71 | data, _ := c.Request.GetJson()
72 | role := data.GetString("role")
73 | policys := data.GetStrings("policys")
74 |
75 | var routerMap = make(map[string]model.RolePolicy)
76 | for _, item := range policys {
77 | list := strings.Split(item, ":")
78 | path := list[0]
79 | atc := list[1]
80 | routerMap[fmt.Sprintf("%v %v %v", role, path, atc)] = model.RolePolicy{Role: role, Path: path, Atc: atc}
81 | }
82 |
83 | model.ReSetPolicy(role, routerMap)
84 |
85 | Success(c.Request, "success")
86 | }
87 |
--------------------------------------------------------------------------------
/app/api/roleController.go:
--------------------------------------------------------------------------------
1 | package api
2 |
3 | import (
4 | "github.com/gogf/gf/os/glog"
5 | "github.com/hailaz/gadmin/app/model"
6 | "github.com/hailaz/gadmin/library/code"
7 | )
8 |
9 | type RoleController struct {
10 | BaseController
11 | }
12 |
13 | func (c *RoleController) Get() {
14 | page := c.Request.GetInt("page", 1)
15 | limit := c.Request.GetInt("limit", 10)
16 | username := c.Request.GetString("username")
17 | var list struct {
18 | List []model.Role `json:"items"`
19 | UserRoleList []model.Role `json:"role_items"`
20 | Total int `json:"total"`
21 | }
22 | list.List, list.Total = model.GetRoleList(page, limit, UNDEFIND_POLICY_NAME)
23 | if username != "" {
24 | list.UserRoleList = model.GetRoleByUserName(username)
25 | }
26 |
27 | Success(c.Request, list)
28 | }
29 |
30 | func (c *RoleController) Post() {
31 | data, _ := c.Request.GetJson()
32 | name := data.GetString("name")
33 | role := data.GetString("role")
34 |
35 | err := model.AddRole(role, name)
36 | if err != nil {
37 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
38 | }
39 |
40 | Success(c.Request, "Post")
41 | }
42 |
43 | func (c *RoleController) Put() {
44 | data, _ := c.Request.GetJson()
45 | name := data.GetString("name")
46 | role := data.GetString("role")
47 | glog.Debug(name, role)
48 | if name == UNDEFIND_POLICY_NAME {
49 | Fail(c.Request, code.RESPONSE_ERROR)
50 | } else {
51 | err := model.UpdateRoleByRoleKey(role, name)
52 | if err != nil {
53 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
54 | }
55 | }
56 | Success(c.Request, "修改成功")
57 | }
58 |
59 | func (c *RoleController) Delete() {
60 | data, _ := c.Request.GetJson()
61 | role := data.GetString("role")
62 |
63 | err := model.DeleteRole(role)
64 | if err != nil {
65 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
66 | }
67 | Success(c.Request, "Delete")
68 | }
69 |
70 | func (c *RoleController) SetRoleByUserName() {
71 | data, _ := c.Request.GetJson()
72 | roles := data.GetStrings("roles")
73 | username := data.GetString("username")
74 | model.SetRoleByUserName(username, roles)
75 |
76 | Success(c.Request, "success")
77 | }
78 |
79 | func (c *RoleController) SetRoleMenus() {
80 | data, _ := c.Request.GetJson()
81 | role := data.GetString("role")
82 | menus := data.GetStrings("menus")
83 | model.SetRoleMenus(role, menus)
84 | Success(c.Request, "success")
85 | }
86 |
--------------------------------------------------------------------------------
/app/api/menuController.go:
--------------------------------------------------------------------------------
1 | package api
2 |
3 | import (
4 | "github.com/gogf/gf/database/gdb"
5 | "github.com/hailaz/gadmin/app/model"
6 | "github.com/hailaz/gadmin/library/code"
7 | )
8 |
9 | type MenuController struct {
10 | BaseController
11 | }
12 |
13 | func (c *MenuController) Get() {
14 | page := c.Request.GetInt("page", 1)
15 | limit := c.Request.GetInt("limit", 10)
16 | var list struct {
17 | List []model.MenuOut `json:"items"`
18 | Total int `json:"total"`
19 | }
20 | list.List, list.Total = model.GetMenuList(page, limit)
21 |
22 | Success(c.Request, list)
23 | }
24 |
25 | func (c *MenuController) Post() {
26 | data, _ := c.Request.GetJson()
27 | m := model.MenuOut{}
28 | data.ToStruct(&m)
29 | model.InsertMenuWithMeta(gdb.List{
30 | {
31 | "name": m.Name,
32 | "menu_path": m.MenuPath,
33 | "component": m.Component,
34 | "sort": m.Sort,
35 | "parent_name": m.ParentName,
36 | "hidden": m.Hidden,
37 | "redirect": m.Redirect,
38 | "alwaysshow": m.Alwaysshow,
39 | "meta": gdb.Map{
40 | "title": m.MenuMetaOut.Title,
41 | "icon": m.MenuMetaOut.Icon,
42 | "noCache": m.MenuMetaOut.Nocache,
43 | },
44 | },
45 | })
46 | Success(c.Request, "添加成功")
47 | }
48 |
49 | func (c *MenuController) Put() {
50 | data, _ := c.Request.GetJson()
51 | m := model.MenuOut{}
52 | data.ToStruct(&m)
53 | err := model.UpdateMenuByName(
54 | m.Name,
55 | gdb.Map{
56 | "menu_path": m.MenuPath,
57 | "component": m.Component,
58 | "sort": m.Sort,
59 | "parent_name": m.ParentName,
60 | "hidden": m.Hidden,
61 | "redirect": m.Redirect,
62 | "alwaysshow": m.Alwaysshow,
63 | "meta": gdb.Map{
64 | "title": m.MenuMetaOut.Title,
65 | "icon": m.MenuMetaOut.Icon,
66 | "noCache": m.MenuMetaOut.Nocache,
67 | },
68 | },
69 | )
70 | if err != nil {
71 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
72 | }
73 | Success(c.Request, "修改成功")
74 | }
75 |
76 | func (c *MenuController) Delete() {
77 | data, _ := c.Request.GetJson()
78 | name := data.GetString("name")
79 | m, err := model.GetMenuByName(name)
80 | if err != nil {
81 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
82 | }
83 | if m.AutoCreate {
84 | Fail(c.Request, code.RESPONSE_ERROR)
85 | }
86 | res, _ := m.DeleteById(m.Id)
87 | if res <= 0 {
88 | Fail(c.Request, code.RESPONSE_ERROR)
89 | }
90 | Success(c.Request, "Delete")
91 | }
92 |
--------------------------------------------------------------------------------
/static/css/chunk-cbf46a0a.c19e23ad.css:
--------------------------------------------------------------------------------
1 | .social-signup-container[data-v-c817cede]{margin:20px 0}.social-signup-container .sign-btn[data-v-c817cede]{display:inline-block;cursor:pointer}.social-signup-container .icon[data-v-c817cede]{color:#fff;font-size:24px;margin-top:8px}.social-signup-container .qq-svg-container[data-v-c817cede],.social-signup-container .wx-svg-container[data-v-c817cede]{display:inline-block;width:40px;height:40px;line-height:40px;text-align:center;padding-top:1px;border-radius:4px;margin-bottom:20px;margin-right:5px}.social-signup-container .wx-svg-container[data-v-c817cede]{background-color:#24da70}.social-signup-container .qq-svg-container[data-v-c817cede]{background-color:#6ba2d6;margin-left:50px}@supports (-webkit-mask:none) and (not (cater-color:#fff)){.login-container .el-input input{color:#fff}}.login-container .el-input{display:inline-block;height:47px;width:85%}.login-container .el-input input{background:transparent;border:0;-webkit-appearance:none;border-radius:0;padding:12px 5px 12px 15px;color:#fff;height:47px;caret-color:#fff}.login-container .el-input input:-webkit-autofill{-webkit-box-shadow:0 0 0 1000px #283443 inset!important;box-shadow:inset 0 0 0 1000px #283443!important;-webkit-text-fill-color:#fff!important}.login-container .el-form-item{border:1px solid hsla(0,0%,100%,.1);background:rgba(0,0,0,.1);border-radius:5px;color:#454545}.login-container[data-v-40da4f90]{min-height:100%;width:100%;background-color:#2d3a4b;overflow:hidden}.login-container .login-form[data-v-40da4f90]{position:relative;width:520px;max-width:100%;padding:160px 35px 0;margin:0 auto;overflow:hidden}.login-container .tips[data-v-40da4f90]{font-size:14px;color:#fff;margin-bottom:10px}.login-container .tips span[data-v-40da4f90]:first-of-type{margin-right:16px}.login-container .svg-container[data-v-40da4f90]{padding:6px 5px 6px 15px;color:#889aa4;vertical-align:middle;width:30px;display:inline-block}.login-container .title-container[data-v-40da4f90]{position:relative}.login-container .title-container .title[data-v-40da4f90]{font-size:26px;color:#eee;margin:0 auto 40px auto;text-align:center;font-weight:700}.login-container .title-container .set-language[data-v-40da4f90]{color:#fff;position:absolute;top:3px;font-size:18px;right:0;cursor:pointer}.login-container .show-pwd[data-v-40da4f90]{position:absolute;right:10px;top:7px;font-size:16px;color:#889aa4;cursor:pointer;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.login-container .thirdparty-button[data-v-40da4f90]{position:absolute;right:0;bottom:6px}@media only screen and (max-width:470px){.login-container .thirdparty-button[data-v-40da4f90]{display:none}}
--------------------------------------------------------------------------------
/static/css/chunk-libs.3dfb7769.css:
--------------------------------------------------------------------------------
1 | /*! normalize.css v7.0.0 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}article,aside,footer,header,nav,section{display:block}h1{font-size:2em;margin:.67em 0}figcaption,figure,main{display:block}figure{margin:1em 40px}hr{-webkit-box-sizing:content-box;box-sizing:content-box;height:0;overflow:visible}pre{font-family:monospace,monospace;font-size:1em}a{background-color:transparent;-webkit-text-decoration-skip:objects}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}b,strong{font-weight:inherit;font-weight:bolder}code,kbd,samp{font-family:monospace,monospace;font-size:1em}dfn{font-style:italic}mark{background-color:#ff0;color:#000}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}audio,video{display:inline-block}audio:not([controls]){display:none;height:0}img{border-style:none}svg:not(:root){overflow:hidden}button,input,optgroup,select,textarea{font-family:sans-serif;font-size:100%;line-height:1.15;margin:0}button,input{overflow:visible}button,select{text-transform:none}[type=reset],[type=submit],button,html [type=button]{-webkit-appearance:button}[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner,button::-moz-focus-inner{border-style:none;padding:0}[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring,button:-moz-focusring{outline:1px dotted ButtonText}fieldset{padding:.35em .75em .625em}legend{-webkit-box-sizing:border-box;box-sizing:border-box;color:inherit;display:table;max-width:100%;padding:0;white-space:normal}progress{display:inline-block;vertical-align:baseline}textarea{overflow:auto}[type=checkbox],[type=radio]{-webkit-box-sizing:border-box;box-sizing:border-box;padding:0}[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}[type=search]::-webkit-search-cancel-button,[type=search]::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}details,menu{display:block}summary{display:list-item}canvas{display:inline-block}[hidden],template{display:none}#nprogress{pointer-events:none}#nprogress .bar{background:#29d;position:fixed;z-index:1031;top:0;left:0;width:100%;height:2px}#nprogress .peg{display:block;position:absolute;right:0;width:100px;height:100%;-webkit-box-shadow:0 0 10px #29d,0 0 5px #29d;box-shadow:0 0 10px #29d,0 0 5px #29d;opacity:1;-webkit-transform:rotate(3deg) translateY(-4px);transform:rotate(3deg) translateY(-4px)}#nprogress .spinner{display:block;position:fixed;z-index:1031;top:15px;right:15px}#nprogress .spinner-icon{width:18px;height:18px;-webkit-box-sizing:border-box;box-sizing:border-box;border:2px solid transparent;border-top-color:#29d;border-left-color:#29d;border-radius:50%;-webkit-animation:nprogress-spinner .4s linear infinite;animation:nprogress-spinner .4s linear infinite}.nprogress-custom-parent{overflow:hidden;position:relative}.nprogress-custom-parent #nprogress .bar,.nprogress-custom-parent #nprogress .spinner{position:absolute}@-webkit-keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg)}to{-webkit-transform:rotate(1turn)}}@keyframes nprogress-spinner{0%{-webkit-transform:rotate(0deg);transform:rotate(0deg)}to{-webkit-transform:rotate(1turn);transform:rotate(1turn)}}
--------------------------------------------------------------------------------
/app/model/model.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "github.com/casbin/casbin"
5 | "github.com/gogf/gf/database/gdb"
6 | "github.com/gogf/gf/frame/g"
7 | // _ "github.com/lib/pq"
8 | // _ "github.com/mattn/go-sqlite3"
9 | )
10 |
11 | var defDB gdb.DB
12 | var Enforcer *casbin.Enforcer
13 |
14 | const (
15 | ACTION_GET = "(GET)"
16 | ACTION_POST = "(POST)"
17 | ACTION_PUT = "(PUT)"
18 | ACTION_DELETE = "(DELETE)"
19 | ACTION_ALL = "(GET)|(POST)|(PUT)|(DELETE)|(PATCH)|(OPTIONS)|(HEAD)"
20 | ADMIN_NAME = "admin" //超级管理员用户名
21 | ADMIN_NICK_NAME = "超级管理员" //超级管理员显示名称
22 | ADMIN_DEFAULT_PASSWORD = "123456" //超级管理员默认密码
23 | )
24 |
25 | // InitModel 初始化数据模型
26 | //
27 | // createTime:2019年05月13日 09:47:08
28 | // author:hailaz
29 | func InitModel() {
30 | defDB = g.DB()
31 | //defDB.SetDebug(true)
32 | initUser()
33 | initCasbin()
34 | initMenu()
35 | }
36 |
37 | // initUser 初始化用户
38 | //
39 | // createTime:2019年04月23日 14:57:23
40 | // author:hailaz
41 | func initUser() {
42 | u, err := GetUserByName(ADMIN_NAME)
43 | if err == nil && u != nil && u.Id != 0 {
44 | return
45 | }
46 | admin := User{
47 | UserName: ADMIN_NAME,
48 | NickName: ADMIN_NICK_NAME,
49 | Password: ADMIN_DEFAULT_PASSWORD,
50 | }
51 | admin.Insert()
52 | }
53 |
54 | // initMenu 初始化菜单数据
55 | //
56 | // createTime:2019年05月16日 15:39:54
57 | // author:hailaz
58 | func initMenu() {
59 | InsertMenuWithMeta(gdb.List{
60 | {
61 | "name": "user",
62 | "menu_path": "/user",
63 | "component": "layout",
64 | "redirect": "/user/list",
65 | "sort": "0",
66 | "parent_name": "",
67 | "auto_create": true,
68 | "meta": gdb.Map{
69 | "title": "user",
70 | "icon": "user",
71 | "noCache": 0},
72 | },
73 | {
74 | "name": "userList",
75 | "menu_path": "list",
76 | "component": "user/user",
77 | "sort": "0",
78 | "parent_name": "user",
79 | "auto_create": true,
80 | "meta": gdb.Map{
81 | "title": "userList",
82 | "icon": "",
83 | "noCache": 0},
84 | },
85 | {
86 | "name": "roleList",
87 | "menu_path": "/role/list",
88 | "component": "user/role",
89 | "sort": "1",
90 | "parent_name": "user",
91 | "auto_create": true,
92 | "meta": gdb.Map{
93 | "title": "roleList",
94 | "icon": "",
95 | "noCache": 0},
96 | },
97 | {
98 | "name": "policyList",
99 | "menu_path": "/policy/list",
100 | "component": "user/policy",
101 | "sort": "2",
102 | "parent_name": "user",
103 | "auto_create": true,
104 | "meta": gdb.Map{
105 | "title": "policyList",
106 | "icon": "",
107 | "noCache": 0},
108 | },
109 | {
110 | "name": "menuList",
111 | "menu_path": "/menu/list",
112 | "component": "user/menu",
113 | "sort": "3",
114 | "parent_name": "user",
115 | "auto_create": true,
116 | "meta": gdb.Map{
117 | "title": "menuList",
118 | "icon": "",
119 | "noCache": 0},
120 | },
121 | })
122 |
123 | }
124 |
125 | // initCasbin 初始化Casbin
126 | //
127 | // createTime:2019年04月23日 14:45:20
128 | // author:hailaz
129 | func initCasbin() {
130 | a := NewAdapter(defDB)
131 | Enforcer = casbin.NewEnforcer("./config/rbac.conf", a)
132 | Enforcer.LoadPolicy()
133 | //Enforcer.DeletePermissionsForUser("group_admin")
134 | Enforcer.AddPolicy(ADMIN_NAME, "*", ACTION_ALL)
135 | //Enforcer.AddGroupingPolicy("system", "user")
136 |
137 | }
138 |
139 | // GetDB 获取默认DB
140 | //
141 | // createTime:2019年04月23日 11:53:21
142 | // author:hailaz
143 | func GetDB() gdb.DB {
144 | return defDB
145 | }
146 |
--------------------------------------------------------------------------------
/app/model/user.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 |
6 | "github.com/gogf/gf/crypto/gmd5"
7 | "github.com/gogf/gf/database/gdb"
8 | "github.com/gogf/gf/os/gtime"
9 | )
10 |
11 | const (
12 | ENCRYPTMD5 = "gadmin"
13 | )
14 |
15 | type UserOut struct {
16 | Id int64 `json:"id"` //
17 | Status int `json:"status"` //
18 | UserName string `json:"user_name"` //
19 | NickName string `json:"nick_name"` //
20 | Email string `json:"email"` //
21 | Phone string `json:"phone"` //
22 | Sex int `json:"sex"` //
23 | Age int `json:"age"` //
24 | AddTime string `json:"add_time"` //
25 | UpdateTime string `json:"update_time"` //
26 | AddUserId int64 `json:"add_user_id"` //
27 | ThirdPartyId int64 `json:"third_party_id"` //
28 | Introduction string `json:"Introduction"` //
29 | Avatar string `json:"avatar"` //
30 | }
31 |
32 | type UserInfo struct {
33 | Roles []string `json:"roles"`
34 | Introduction string `json:"introduction"`
35 | Avatar string `json:"avatar"`
36 | Name string `json:"name"`
37 | }
38 |
39 | // GetUserByPageLimt 获取用户
40 | //
41 | // createTime:2019年05月07日 16:11:41
42 | // author:hailaz
43 | func GetUserByPageLimt(page, limit int) ([]UserOut, int) {
44 | if page < 1 {
45 | page = 1
46 | }
47 | if limit < 1 {
48 | limit = 10
49 | }
50 | total, _ := defDB.Table("user").Count()
51 | if total == 0 {
52 | return nil, 0
53 | }
54 |
55 | userList := make([]UserOut, 0)
56 | if total < page*limit {
57 | if total < limit {
58 | page = 1
59 | }
60 | }
61 | r, err := defDB.Table("user").Limit((page-1)*limit, (page-1)*limit+limit).Select()
62 | if err != nil {
63 | return nil, 0
64 | }
65 | r.ToStructs(&userList)
66 | return userList, total
67 |
68 | }
69 |
70 | // GetAllUser 获取所有用户
71 | //
72 | // createTime:2019年04月30日 10:20:50
73 | // author:hailaz
74 | func GetAllUser() (gdb.Result, error) {
75 | return defDB.Table("user").All()
76 | }
77 |
78 | // GetUserByName 根据用户名获取用户
79 | //
80 | // createTime:2019年04月23日 17:14:22
81 | // author:hailaz
82 | func GetUserByName(name string) (*User, error) {
83 | u := User{}
84 | err := defDB.Table("user").Where("user_name", name).Struct(&u)
85 | if err != nil {
86 | return nil, err
87 | }
88 | return &u, nil
89 | }
90 |
91 | // EncryptPassword 加密密码
92 | //
93 | // createTime:2019年04月25日 10:19:13
94 | // author:hailaz
95 | func EncryptPassword(data string) string {
96 | md5Str, _ := gmd5.EncryptString(data + ENCRYPTMD5)
97 | return md5Str
98 | }
99 |
100 | // UpdateUserById 更新用户
101 | //
102 | // createTime:2019年05月08日 14:28:18
103 | // author:hailaz
104 | func UpdateUserById(id int64, udmap gdb.Map) error {
105 | udmap["update_time"] = gtime.Now().String()
106 | r, err := defDB.Table("user").Data(udmap).Where("id=?", id).Update()
107 | if err != nil {
108 | return err
109 | }
110 | i, _ := r.RowsAffected()
111 | if i < 0 {
112 | return errors.New("update fail")
113 | }
114 | return nil
115 | }
116 |
117 | // {
118 | // roles: ['admin'],
119 | // introduction: 'I am a super administrator',
120 | // avatar: 'https://wpimg.wallstcn.com/f778738c-e4f8-4870-b634-56703b4acafe.gif',
121 | // name: 'Super Admin'
122 | // }
123 | // GetUserInfo 获取用户信息
124 | //
125 | // createTime:2019年05月08日 16:53:24
126 | // author:hailaz
127 | func (u *User) GetUserInfo() UserInfo {
128 | info := UserInfo{}
129 | if u.UserName == ADMIN_NAME {
130 | info.Roles = []string{ADMIN_NAME}
131 | } else {
132 | info.Roles, _ = Enforcer.GetRolesForUser(u.UserName)
133 | }
134 |
135 | info.Avatar = u.Avatar
136 | info.Introduction = u.Introduction
137 | info.Name = u.NickName
138 |
139 | return info
140 | }
141 |
--------------------------------------------------------------------------------
/library/common/rsa.go:
--------------------------------------------------------------------------------
1 | package common
2 |
3 | import (
4 | "bytes"
5 | "crypto/rand"
6 | "crypto/rsa"
7 | "crypto/x509"
8 | "encoding/pem"
9 | "errors"
10 |
11 | "github.com/gogf/gf/container/gmap"
12 | "github.com/gogf/gf/os/glog"
13 | "github.com/gogf/gf/os/gtime"
14 | )
15 |
16 | var CryptoKeyList = gmap.New()
17 |
18 | type CryptoKey struct {
19 | Id string `json:"kid"`
20 | CryptoType string `json:"cryptotype"`
21 | Key string `json:"key"`
22 | PrivateKey string `json:"-"`
23 | TimeStamp int64 `json:"timestamp"` //sec
24 | }
25 |
26 | // GetCryptoKey 获取加密key
27 | //
28 | // createTime:2019年04月26日 15:03:24
29 | // author:hailaz
30 | func GetCryptoKey(id string) *CryptoKey {
31 | var ck CryptoKey
32 | if k := CryptoKeyList.Get(id); k != nil {
33 | CryptoKeyList.Remove(id) //移除已使用密钥
34 | ck = k.(CryptoKey)
35 | return &ck
36 | }
37 | return nil
38 | }
39 |
40 | // RemoveTimeoutCryptoKey 移除超时加密key
41 | //
42 | // createTime:2019年04月26日 15:00:23
43 | // author:hailaz
44 | func RemoveTimeoutCryptoKey() {
45 | kList := make([]interface{}, 0)
46 | nowSec := gtime.Second()
47 | //遍历加密key
48 | CryptoKeyList.Iterator(func(k interface{}, v interface{}) bool {
49 | ck := v.(CryptoKey)
50 | if nowSec-ck.TimeStamp >= 10 {
51 | kList = append(kList, k)
52 | }
53 | return true
54 | })
55 | //移除超时的加密key
56 | for _, v := range kList {
57 | CryptoKeyList.Remove(v)
58 | glog.Debugf("remove key:%v", v)
59 | }
60 | }
61 |
62 | // GenCryptoKey 创建加密key
63 | //
64 | // createTime:2019年04月26日 10:27:48
65 | // author:hailaz
66 | func GenCryptoKey(id string) CryptoKey {
67 | rsakp, _ := GenRsaKey(2048)
68 | ck := CryptoKey{
69 | Id: id,
70 | CryptoType: "RSA-PKCS1v1.5",
71 | Key: rsakp.PublicKey,
72 | PrivateKey: rsakp.PrivateKey,
73 | TimeStamp: gtime.Second(),
74 | }
75 | CryptoKeyList.Set(id, ck)
76 | return ck
77 |
78 | }
79 |
80 | type RASKeyPair struct {
81 | PrivateKey string
82 | PublicKey string
83 | }
84 |
85 | // RAS密钥对生成可选1024 2048 4096
86 | func GenRsaKey(bits int) (*RASKeyPair, error) {
87 | kp := &RASKeyPair{}
88 | // 生成私钥文件
89 | privateKey, err := rsa.GenerateKey(rand.Reader, bits)
90 | if err != nil {
91 | return nil, err
92 | }
93 | derStream := x509.MarshalPKCS1PrivateKey(privateKey)
94 | block := &pem.Block{
95 | Type: "RSA PRIVATE KEY",
96 | Bytes: derStream,
97 | }
98 | b := bytes.NewBuffer(make([]byte, 0))
99 | pem.Encode(b, block)
100 | kp.PrivateKey = b.String()
101 | //glog.Debug(b.String())
102 | // 生成公钥文件
103 | derPkix, err := x509.MarshalPKIXPublicKey(&privateKey.PublicKey)
104 | if err != nil {
105 | return nil, err
106 | }
107 | block = &pem.Block{
108 | Type: "PUBLIC KEY",
109 | Bytes: derPkix,
110 | }
111 | b1 := bytes.NewBuffer(make([]byte, 0))
112 | pem.Encode(b1, block)
113 | //glog.Debug(b1.String())
114 | kp.PublicKey = b1.String()
115 |
116 | return kp, nil
117 | }
118 |
119 | // 加密
120 | func RsaEncrypt(origData, publicKey []byte) ([]byte, error) {
121 | //解密pem格式的公钥
122 | block, _ := pem.Decode(publicKey)
123 | if block == nil {
124 | return nil, errors.New("public key error")
125 | }
126 | // 解析公钥
127 | pubInterface, err := x509.ParsePKIXPublicKey(block.Bytes)
128 | if err != nil {
129 | return nil, err
130 | }
131 | // 类型断言
132 | pub := pubInterface.(*rsa.PublicKey)
133 | //加密
134 | return rsa.EncryptPKCS1v15(rand.Reader, pub, origData)
135 | }
136 |
137 | // 解密
138 | func RsaDecrypt(ciphertext, privateKey []byte) ([]byte, error) {
139 | //解密
140 | block, _ := pem.Decode(privateKey)
141 | if block == nil {
142 | return nil, errors.New("private key error!")
143 | }
144 | //解析PKCS1格式的私钥
145 | priv, err := x509.ParsePKCS1PrivateKey(block.Bytes)
146 | if err != nil {
147 | return nil, err
148 | }
149 | // 解密
150 | return rsa.DecryptPKCS1v15(rand.Reader, priv, ciphertext)
151 | }
152 |
--------------------------------------------------------------------------------
/app/model/policy.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 | "fmt"
6 |
7 | "github.com/gogf/gf/os/glog"
8 |
9 | "github.com/gogf/gf/database/gdb"
10 | )
11 |
12 | type Policy struct {
13 | Policy string `json:"policy"` //
14 | Name string `json:"name"` //
15 | Descrption string `json:"descrption"` //
16 | }
17 |
18 | type RolePolicy struct {
19 | Role string
20 | Path string
21 | Atc string
22 | }
23 |
24 | // GetPolicyList 获取权限列表
25 | //
26 | // createTime:2019年05月06日 17:24:12
27 | // author:hailaz
28 | func GetPolicyList(page, limit int, defaultname string) ([]Policy, int) {
29 | if page < 1 {
30 | page = 1
31 | }
32 | policyList := make([]Policy, 0)
33 | policys := Enforcer.GetPermissionsForUser("system")
34 | total := len(policys)
35 | r, _ := GetAllPolicy()
36 | pn := make([]PolicyName, 0)
37 | r.ToStructs(&pn)
38 |
39 | for _, item := range policys {
40 | full := fmt.Sprintf("%v:%v", item[1], item[2])
41 | p := Policy{Policy: full, Name: defaultname}
42 | for _, itempn := range pn {
43 | if itempn.FullPath == full {
44 | p.Name = itempn.Name
45 | p.Descrption = itempn.Descrption
46 | break
47 | }
48 | }
49 | policyList = append(policyList, p)
50 | }
51 | if limit == -1 {
52 | return policyList, total
53 | }
54 | if len(policyList) < page*limit {
55 | if len(policyList) < limit {
56 | policyList = policyList
57 | } else {
58 | policyList = policyList[(page-1)*limit:]
59 | }
60 | } else {
61 | policyList = policyList[(page-1)*limit : (page-1)*limit+limit]
62 | }
63 | return policyList, total
64 | }
65 |
66 | // GetPolicyByRole 根据角色获取权限
67 | //
68 | // createTime:2019年05月07日 11:35:33
69 | // author:hailaz
70 | func GetPolicyByRole(role string) []Policy {
71 | policyList := make([]Policy, 0)
72 | policys := Enforcer.GetPermissionsForUser(role)
73 | glog.Debug(policys)
74 | for _, item := range policys {
75 | full := fmt.Sprintf("%v:%v", item[1], item[2])
76 | p := Policy{Policy: full}
77 | policyList = append(policyList, p)
78 | }
79 | return policyList
80 | }
81 |
82 | // GetAllPolicy 获取所有权限名称
83 | //
84 | // createTime:2019年04月30日 10:20:50
85 | // author:hailaz
86 | func GetAllPolicy() (gdb.Result, error) {
87 | return defDB.Table("policy_name").All()
88 | }
89 |
90 | // GetPolicyByFullPath 根据权限全路径获取权限
91 | //
92 | // createTime:2019年05月06日 15:53:08
93 | // author:hailaz
94 | func GetPolicyByFullPath(path string) (PolicyName, error) {
95 | obj := PolicyName{}
96 | err := defDB.Table("policy_name").Where("full_path", path).Struct(&obj)
97 | return obj, err
98 | }
99 |
100 | // UpdatePolicyByFullPath 更新权限信息
101 | //
102 | // createTime:2019年05月06日 15:47:35
103 | // author:hailaz
104 | func UpdatePolicyByFullPath(path, name string) error {
105 | p, err := GetPolicyByFullPath(path)
106 | // 不存在插入新数据
107 | if err != nil || p.Id == 0 {
108 | p.FullPath = path
109 | p.Name = name
110 | id, _ := p.Insert()
111 | if id > 0 {
112 | return nil
113 | } else {
114 | return errors.New("update fail")
115 | }
116 | }
117 | // 存在则更新
118 | p.Name = name
119 | i, err := p.Update()
120 | if err != nil {
121 | glog.Error(err)
122 | return err
123 | }
124 | if i < 0 {
125 | return errors.New("update fail")
126 | }
127 | return nil
128 | }
129 |
130 | // ReSetPolicy 更新路由权限
131 | //
132 | // createTime:2019年04月29日 17:30:26
133 | // author:hailaz
134 | func ReSetPolicy(role string, rmap map[string]RolePolicy) {
135 | old := Enforcer.GetPermissionsForUser(role)
136 | for _, item := range old {
137 | glog.Debug(item)
138 | full := fmt.Sprintf("%v %v %v", item[0], item[1], item[2])
139 | if _, ok := rmap[full]; ok { //从待插入列表中删除已存在的路由
140 | delete(rmap, full)
141 | } else { //删除不存在的旧路由
142 | Enforcer.DeletePermissionForUser(item[0], item[1], item[2])
143 | if role == "system" {
144 | p, _ := GetPolicyByFullPath(fmt.Sprintf("%v:%v", item[1], item[2]))
145 | if p.Id > 0 {
146 | p.DeleteById(p.Id)
147 | }
148 | }
149 | }
150 | }
151 | for _, item := range rmap { //插入新路由
152 | Enforcer.AddPolicy(item.Role, item.Path, item.Atc)
153 | }
154 | }
155 |
--------------------------------------------------------------------------------
/static/css/chunk-2a330e22.d5adff47.css:
--------------------------------------------------------------------------------
1 | .dashboard-editor-container[data-v-6eb39d8e]{padding:32px;background-color:#f0f2f5;position:relative}.dashboard-editor-container .github-corner[data-v-6eb39d8e]{position:absolute;top:0;border:0;right:0}.dashboard-editor-container .chart-wrapper[data-v-6eb39d8e]{background:#fff;padding:16px 16px 0;margin-bottom:32px}.pan-item[data-v-0d3d578f]{width:200px;height:200px;border-radius:50%;display:inline-block;position:relative;cursor:default;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.2);box-shadow:0 1px 3px rgba(0,0,0,.2)}.pan-info-roles-container[data-v-0d3d578f]{padding:20px;text-align:center}.pan-thumb[data-v-0d3d578f]{width:100%;height:100%;background-size:100%;border-radius:50%;overflow:hidden;position:absolute;-webkit-transform-origin:95% 40%;transform-origin:95% 40%;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.pan-thumb[data-v-0d3d578f]:after{content:"";width:8px;height:8px;position:absolute;border-radius:50%;top:40%;left:95%;margin:-4px 0 0 -4px;background:radial-gradient(ellipse at center,#0e0e0e 0,#7d7e7d 100%);-webkit-box-shadow:0 0 1px hsla(0,0%,100%,.9);box-shadow:0 0 1px hsla(0,0%,100%,.9)}.pan-info[data-v-0d3d578f]{position:absolute;width:inherit;height:inherit;border-radius:50%;overflow:hidden;-webkit-box-shadow:inset 0 0 0 5px rgba(0,0,0,.05);box-shadow:inset 0 0 0 5px rgba(0,0,0,.05)}.pan-info h3[data-v-0d3d578f]{color:#fff;text-transform:uppercase;position:relative;letter-spacing:2px;font-size:18px;margin:0 60px;padding:22px 0 0 0;height:85px;font-family:Open Sans,Arial,sans-serif;text-shadow:0 0 1px #fff,0 1px 2px rgba(0,0,0,.3)}.pan-info p[data-v-0d3d578f]{color:#fff;padding:10px 5px;font-style:italic;margin:0 30px;font-size:12px;border-top:1px solid hsla(0,0%,100%,.5)}.pan-info p a[data-v-0d3d578f]{display:block;color:#333;width:80px;height:80px;background:hsla(0,0%,100%,.3);border-radius:50%;color:#fff;font-style:normal;font-weight:700;text-transform:uppercase;font-size:9px;letter-spacing:1px;padding-top:24px;margin:7px auto 0;font-family:Open Sans,Arial,sans-serif;opacity:0;-webkit-transition:opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;transition:opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;transition:transform .3s ease-in-out .2s,opacity .3s ease-in-out .2s,background .2s linear 0s;transition:transform .3s ease-in-out .2s,opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;-webkit-transform:translateX(60px) rotate(90deg);transform:translateX(60px) rotate(90deg)}.pan-info p a[data-v-0d3d578f]:hover{background:hsla(0,0%,100%,.5)}.pan-item:hover .pan-thumb[data-v-0d3d578f]{-webkit-transform:rotate(-110deg);transform:rotate(-110deg)}.pan-item:hover .pan-info p a[data-v-0d3d578f]{opacity:1;-webkit-transform:translateX(0) rotate(0deg);transform:translateX(0) rotate(0deg)}.github-corner:hover .octo-arm[data-v-4c6d8d88]{-webkit-animation:octocat-wave-data-v-4c6d8d88 .56s ease-in-out;animation:octocat-wave-data-v-4c6d8d88 .56s ease-in-out}@-webkit-keyframes octocat-wave-data-v-4c6d8d88{0%,to{-webkit-transform:rotate(0);transform:rotate(0)}20%,60%{-webkit-transform:rotate(-25deg);transform:rotate(-25deg)}40%,80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}}@keyframes octocat-wave-data-v-4c6d8d88{0%,to{-webkit-transform:rotate(0);transform:rotate(0)}20%,60%{-webkit-transform:rotate(-25deg);transform:rotate(-25deg)}40%,80%{-webkit-transform:rotate(10deg);transform:rotate(10deg)}}@media (max-width:500px){.github-corner:hover .octo-arm[data-v-4c6d8d88]{-webkit-animation:none;animation:none}.github-corner .octo-arm[data-v-4c6d8d88]{-webkit-animation:octocat-wave-data-v-4c6d8d88 .56s ease-in-out;animation:octocat-wave-data-v-4c6d8d88 .56s ease-in-out}}.emptyGif[data-v-9c953d6a]{display:block;width:45%;margin:0 auto}.dashboard-editor-container[data-v-9c953d6a]{background-color:#e3e3e3;min-height:100vh;padding:50px 60px 0}.dashboard-editor-container .pan-info-roles[data-v-9c953d6a]{font-size:12px;font-weight:700;color:#333;display:block}.dashboard-editor-container .info-container[data-v-9c953d6a]{position:relative;margin-left:190px;height:150px;line-height:200px}.dashboard-editor-container .info-container .display_name[data-v-9c953d6a]{font-size:48px;line-height:48px;color:#212121;position:absolute;top:25px}
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
GAdmin vue
--------------------------------------------------------------------------------
/app/model/role.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "errors"
5 |
6 | "github.com/gogf/gf/database/gdb"
7 | "github.com/gogf/gf/os/glog"
8 | )
9 |
10 | type Role struct {
11 | Role string `json:"role"` //
12 | Name string `json:"name"` //
13 | Descrption string `json:"descrption"` //
14 | }
15 |
16 | // GetRoleList 获取权限列表
17 | //
18 | // createTime:2019年05月06日 17:24:12
19 | // author:hailaz
20 | func GetRoleList(page, limit int, defaultname string) ([]Role, int) {
21 | if page < 1 {
22 | page = 1
23 | }
24 | roleList := make([]Role, 0)
25 | roles := Enforcer.GetAllRoles()
26 | total := len(roles)
27 | r, _ := GetAllRole()
28 | pn := make([]RoleName, 0)
29 | r.ToStructs(&pn)
30 |
31 | for _, item := range roles {
32 | p := Role{Role: item, Name: defaultname}
33 | for _, itempn := range pn {
34 | if itempn.RoleKey == item {
35 | p.Name = itempn.Name
36 | p.Descrption = itempn.Descrption
37 | break
38 | }
39 | }
40 | roleList = append(roleList, p)
41 | }
42 | if limit == -1 {
43 | return roleList, total
44 | }
45 | if len(roleList) < page*limit {
46 | if len(roleList) < limit {
47 | roleList = roleList
48 | } else {
49 | roleList = roleList[(page-1)*limit:]
50 | }
51 | } else {
52 | roleList = roleList[(page-1)*limit : (page-1)*limit+limit]
53 | }
54 | return roleList, total
55 | }
56 |
57 | // GetRoleByUserName 根据用户名获取对应角色
58 | //
59 | // createTime:2019年05月08日 15:08:19
60 | // author:hailaz
61 | func GetRoleByUserName(userName string) []Role {
62 | roles, _ := Enforcer.GetRolesForUser(userName)
63 | roleList := make([]Role, 0)
64 | for _, item := range roles {
65 | p := Role{Role: item}
66 | roleList = append(roleList, p)
67 | }
68 | return roleList
69 | }
70 |
71 | // GetAllRole 获取所有角色名称
72 | //
73 | // createTime:2019年04月30日 10:20:50
74 | // author:hailaz
75 | func GetAllRole() (gdb.Result, error) {
76 | return defDB.Table("role_name").All()
77 | }
78 |
79 | // GetRoleByRoleKey 根据角色唯一键获取角色
80 | //
81 | // createTime:2019年05月06日 15:53:08
82 | // author:hailaz
83 | func GetRoleByRoleKey(role string) (RoleName, error) {
84 | obj := RoleName{}
85 | err := defDB.Table("role_name").Where("role_key", role).Struct(&obj)
86 | return obj, err
87 | }
88 |
89 | // UpdateRoleByRoleKey 更新角色信息
90 | //
91 | // createTime:2019年05月06日 15:47:35
92 | // author:hailaz
93 | func UpdateRoleByRoleKey(role, name string) error {
94 | p, err := GetRoleByRoleKey(role)
95 | // 不存在插入新数据
96 | if err != nil || p.Id == 0 {
97 | p.RoleKey = role
98 | p.Name = name
99 | id, _ := p.Insert()
100 | if id > 0 {
101 | return nil
102 | } else {
103 | return errors.New("update fail")
104 | }
105 | }
106 | // 存在则更新
107 | p.Name = name
108 | i, err := p.Update()
109 | if err != nil {
110 | glog.Error(err)
111 | return err
112 | }
113 | if i < 0 {
114 | return errors.New("update fail")
115 | }
116 | return nil
117 | }
118 |
119 | // AddRole 添加角色
120 | //
121 | // createTime:2019年05月07日 10:45:04
122 | // author:hailaz
123 | func AddRole(role, name string) error {
124 | p, err := GetRoleByRoleKey(role)
125 | // 不存在插入新数据
126 | if err != nil || p.Id == 0 {
127 | res := Enforcer.AddGroupingPolicy("system", role)
128 | if !res {
129 | return errors.New("add fail")
130 | }
131 | p.RoleKey = role
132 | p.Name = name
133 | id, _ := p.Insert()
134 | if id > 0 {
135 | return nil
136 | } else {
137 | return errors.New("add fail")
138 | }
139 | }
140 | return errors.New("add fail")
141 | }
142 |
143 | // DeleteRole 删除角色
144 | //
145 | // createTime:2019年05月07日 11:12:59
146 | // author:hailaz
147 | func DeleteRole(role string) error {
148 | p, err := GetRoleByRoleKey(role)
149 | if err != nil || p.Id == 0 {
150 | return errors.New("delete fail")
151 | }
152 | Enforcer.DeleteRole(role)
153 | DeleteRoleMenus(role)
154 | i, _ := p.DeleteById(p.Id)
155 | if i > 0 {
156 | return nil
157 | }
158 | return errors.New("delete fail")
159 | }
160 |
161 | // SetRoleByUserName 设置用户角色
162 | //
163 | // createTime:2019年05月08日 15:22:05
164 | // author:hailaz
165 | func SetRoleByUserName(userName string, roles []string) {
166 | Enforcer.DeleteRolesForUser(userName)
167 | for _, item := range roles {
168 | Enforcer.AddRoleForUser(userName, item)
169 | }
170 | }
171 |
--------------------------------------------------------------------------------
/static/css/chunk-015d6b7a.0a66699f.css:
--------------------------------------------------------------------------------
1 | .pan-item[data-v-0d3d578f]{width:200px;height:200px;border-radius:50%;display:inline-block;position:relative;cursor:default;-webkit-box-shadow:0 1px 3px rgba(0,0,0,.2);box-shadow:0 1px 3px rgba(0,0,0,.2)}.pan-info-roles-container[data-v-0d3d578f]{padding:20px;text-align:center}.pan-thumb[data-v-0d3d578f]{width:100%;height:100%;background-size:100%;border-radius:50%;overflow:hidden;position:absolute;-webkit-transform-origin:95% 40%;transform-origin:95% 40%;-webkit-transition:all .3s ease-in-out;transition:all .3s ease-in-out}.pan-thumb[data-v-0d3d578f]:after{content:"";width:8px;height:8px;position:absolute;border-radius:50%;top:40%;left:95%;margin:-4px 0 0 -4px;background:radial-gradient(ellipse at center,#0e0e0e 0,#7d7e7d 100%);-webkit-box-shadow:0 0 1px hsla(0,0%,100%,.9);box-shadow:0 0 1px hsla(0,0%,100%,.9)}.pan-info[data-v-0d3d578f]{position:absolute;width:inherit;height:inherit;border-radius:50%;overflow:hidden;-webkit-box-shadow:inset 0 0 0 5px rgba(0,0,0,.05);box-shadow:inset 0 0 0 5px rgba(0,0,0,.05)}.pan-info h3[data-v-0d3d578f]{color:#fff;text-transform:uppercase;position:relative;letter-spacing:2px;font-size:18px;margin:0 60px;padding:22px 0 0 0;height:85px;font-family:Open Sans,Arial,sans-serif;text-shadow:0 0 1px #fff,0 1px 2px rgba(0,0,0,.3)}.pan-info p[data-v-0d3d578f]{color:#fff;padding:10px 5px;font-style:italic;margin:0 30px;font-size:12px;border-top:1px solid hsla(0,0%,100%,.5)}.pan-info p a[data-v-0d3d578f]{display:block;color:#333;width:80px;height:80px;background:hsla(0,0%,100%,.3);border-radius:50%;color:#fff;font-style:normal;font-weight:700;text-transform:uppercase;font-size:9px;letter-spacing:1px;padding-top:24px;margin:7px auto 0;font-family:Open Sans,Arial,sans-serif;opacity:0;-webkit-transition:opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;transition:opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;transition:transform .3s ease-in-out .2s,opacity .3s ease-in-out .2s,background .2s linear 0s;transition:transform .3s ease-in-out .2s,opacity .3s ease-in-out .2s,background .2s linear 0s,-webkit-transform .3s ease-in-out .2s;-webkit-transform:translateX(60px) rotate(90deg);transform:translateX(60px) rotate(90deg)}.pan-info p a[data-v-0d3d578f]:hover{background:hsla(0,0%,100%,.5)}.pan-item:hover .pan-thumb[data-v-0d3d578f]{-webkit-transform:rotate(-110deg);transform:rotate(-110deg)}.pan-item:hover .pan-info p a[data-v-0d3d578f]{opacity:1;-webkit-transform:translateX(0) rotate(0deg);transform:translateX(0) rotate(0deg)}.box-center[data-v-562f534e]{margin:0 auto;display:table}.text-muted[data-v-562f534e]{color:#777}.user-profile .user-name[data-v-562f534e]{font-weight:700}.user-profile .box-center[data-v-562f534e]{padding-top:10px}.user-profile .user-role[data-v-562f534e]{padding-top:10px;font-weight:400;font-size:14px}.user-profile .box-social[data-v-562f534e]{padding-top:30px}.user-profile .box-social .el-table[data-v-562f534e]{border-top:1px solid #dfe6ec}.user-profile .user-follow[data-v-562f534e]{padding-top:20px}.user-bio[data-v-562f534e]{margin-top:20px;color:#606266}.user-bio span[data-v-562f534e]{padding-left:4px}.user-bio .user-bio-section[data-v-562f534e]{font-size:14px;padding:15px 0}.user-bio .user-bio-section .user-bio-section-header[data-v-562f534e]{border-bottom:1px solid #dfe6ec;padding-bottom:10px;margin-bottom:10px;font-weight:700}.user-activity .user-block .description[data-v-6fd9b025],.user-activity .user-block .username[data-v-6fd9b025]{display:block;margin-left:50px;padding:2px 0}.user-activity .user-block .username[data-v-6fd9b025]{font-size:16px;color:#000}.user-activity .user-block[data-v-6fd9b025] :after{clear:both}.user-activity .user-block .img-circle[data-v-6fd9b025]{border-radius:50%;width:40px;height:40px;float:left}.user-activity .user-block span[data-v-6fd9b025]{font-weight:500;font-size:12px}.user-activity .post[data-v-6fd9b025]{font-size:14px;border-bottom:1px solid #d2d6de;margin-bottom:15px;padding-bottom:15px;color:#666}.user-activity .post .image[data-v-6fd9b025]{width:100%;height:100%}.user-activity .post .user-images[data-v-6fd9b025]{padding-top:20px}.user-activity .list-inline[data-v-6fd9b025]{padding-left:0;margin-left:-5px;list-style:none}.user-activity .list-inline li[data-v-6fd9b025]{display:inline-block;padding-right:5px;padding-left:5px;font-size:13px}.user-activity .list-inline .link-black[data-v-6fd9b025]:focus,.user-activity .list-inline .link-black[data-v-6fd9b025]:hover{color:#999}.box-center[data-v-6fd9b025]{margin:0 auto;display:table}.text-muted[data-v-6fd9b025]{color:#777}
--------------------------------------------------------------------------------
/static/css/chunk-508832c0.fed07099.css:
--------------------------------------------------------------------------------
1 | .wscn-http404-container[data-v-22c31b5a]{-webkit-transform:translate(-50%,-50%);transform:translate(-50%,-50%);position:absolute;top:40%;left:50%}.wscn-http404[data-v-22c31b5a]{position:relative;width:1200px;padding:0 50px;overflow:hidden}.wscn-http404 .pic-404[data-v-22c31b5a]{position:relative;float:left;width:600px;overflow:hidden}.wscn-http404 .pic-404__parent[data-v-22c31b5a]{width:100%}.wscn-http404 .pic-404__child[data-v-22c31b5a]{position:absolute}.wscn-http404 .pic-404__child.left[data-v-22c31b5a]{width:80px;top:17px;left:220px;opacity:0;-webkit-animation-name:cloudLeft-data-v-22c31b5a;animation-name:cloudLeft-data-v-22c31b5a;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}.wscn-http404 .pic-404__child.mid[data-v-22c31b5a]{width:46px;top:10px;left:420px;opacity:0;-webkit-animation-name:cloudMid-data-v-22c31b5a;animation-name:cloudMid-data-v-22c31b5a;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1.2s;animation-delay:1.2s}.wscn-http404 .pic-404__child.right[data-v-22c31b5a]{width:62px;top:100px;left:500px;opacity:0;-webkit-animation-name:cloudRight-data-v-22c31b5a;animation-name:cloudRight-data-v-22c31b5a;-webkit-animation-duration:2s;animation-duration:2s;-webkit-animation-timing-function:linear;animation-timing-function:linear;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-delay:1s;animation-delay:1s}@-webkit-keyframes cloudLeft-data-v-22c31b5a{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@keyframes cloudLeft-data-v-22c31b5a{0%{top:17px;left:220px;opacity:0}20%{top:33px;left:188px;opacity:1}80%{top:81px;left:92px;opacity:1}to{top:97px;left:60px;opacity:0}}@-webkit-keyframes cloudMid-data-v-22c31b5a{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@keyframes cloudMid-data-v-22c31b5a{0%{top:10px;left:420px;opacity:0}20%{top:40px;left:360px;opacity:1}70%{top:130px;left:180px;opacity:1}to{top:160px;left:120px;opacity:0}}@-webkit-keyframes cloudRight-data-v-22c31b5a{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}@keyframes cloudRight-data-v-22c31b5a{0%{top:100px;left:500px;opacity:0}20%{top:120px;left:460px;opacity:1}80%{top:180px;left:340px;opacity:1}to{top:200px;left:300px;opacity:0}}.wscn-http404 .bullshit[data-v-22c31b5a]{position:relative;float:left;width:300px;padding:30px 0;overflow:hidden}.wscn-http404 .bullshit__oops[data-v-22c31b5a]{font-size:32px;line-height:40px;color:#1482f0;margin-bottom:20px;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__headline[data-v-22c31b5a],.wscn-http404 .bullshit__oops[data-v-22c31b5a]{font-weight:700;opacity:0;-webkit-animation-name:slideUp-data-v-22c31b5a;animation-name:slideUp-data-v-22c31b5a;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__headline[data-v-22c31b5a]{font-size:20px;line-height:24px;color:#222;margin-bottom:10px;-webkit-animation-delay:.1s;animation-delay:.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-22c31b5a]{font-size:13px;line-height:21px;color:grey;margin-bottom:30px;-webkit-animation-delay:.2s;animation-delay:.2s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}.wscn-http404 .bullshit__info[data-v-22c31b5a],.wscn-http404 .bullshit__return-home[data-v-22c31b5a]{opacity:0;-webkit-animation-name:slideUp-data-v-22c31b5a;animation-name:slideUp-data-v-22c31b5a;-webkit-animation-duration:.5s;animation-duration:.5s}.wscn-http404 .bullshit__return-home[data-v-22c31b5a]{display:block;float:left;width:110px;height:36px;background:#1482f0;border-radius:100px;text-align:center;color:#fff;font-size:14px;line-height:36px;cursor:pointer;-webkit-animation-delay:.3s;animation-delay:.3s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards}@-webkit-keyframes slideUp-data-v-22c31b5a{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}@keyframes slideUp-data-v-22c31b5a{0%{-webkit-transform:translateY(60px);transform:translateY(60px);opacity:0}to{-webkit-transform:translateY(0);transform:translateY(0);opacity:1}}
--------------------------------------------------------------------------------
/app/model/casbin_adapter.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "fmt"
5 | "runtime"
6 |
7 | "github.com/casbin/casbin/model"
8 | "github.com/casbin/casbin/persist"
9 | "github.com/gogf/gf/database/gdb"
10 | )
11 |
12 | type CasbinRule struct {
13 | Id int64 `json:"id"` //
14 | PType string `json:"p_type"` //
15 | V0 string `json:"v0"` //
16 | V1 string `json:"v1"` //
17 | V2 string `json:"v2"` //
18 | V3 string `json:"v3"` //
19 | V4 string `json:"v4"` //
20 | V5 string `json:"v5"` //
21 | }
22 |
23 | const (
24 | CASBINRULE_TABLE_NAME = "casbin_rule"
25 | )
26 |
27 | // Adapter represents the Xorm adapter for policy storage.
28 | type Adapter struct {
29 | o gdb.DB
30 | }
31 |
32 | func NewAdapter(db gdb.DB) *Adapter {
33 | a := &Adapter{o: db}
34 |
35 | // Open the DB, create it if not existed.
36 | a.open()
37 |
38 | // Call the destructor when the object is released.
39 | runtime.SetFinalizer(a, finalizer)
40 |
41 | return a
42 | }
43 |
44 | // finalizer is the destructor for Adapter.
45 | func finalizer(a *Adapter) {
46 | }
47 |
48 | func (a *Adapter) open() {
49 |
50 | }
51 |
52 | func (a *Adapter) close() {
53 | a.o = nil
54 | }
55 |
56 | func (a *Adapter) createTable() {
57 | }
58 |
59 | func (a *Adapter) dropTable() {
60 | }
61 |
62 | func loadPolicyLine(line CasbinRule, model model.Model) {
63 | lineText := line.PType
64 | if line.V0 != "" {
65 | lineText += ", " + line.V0
66 | }
67 | if line.V1 != "" {
68 | lineText += ", " + line.V1
69 | }
70 | if line.V2 != "" {
71 | lineText += ", " + line.V2
72 | }
73 | if line.V3 != "" {
74 | lineText += ", " + line.V3
75 | }
76 | if line.V4 != "" {
77 | lineText += ", " + line.V4
78 | }
79 | if line.V5 != "" {
80 | lineText += ", " + line.V5
81 | }
82 |
83 | persist.LoadPolicyLine(lineText, model)
84 | }
85 |
86 | // LoadPolicy loads policy from database.
87 | func (a *Adapter) LoadPolicy(model model.Model) error {
88 | var lines []CasbinRule
89 | err := a.o.Table(CASBINRULE_TABLE_NAME).Structs(&lines)
90 |
91 | if err != nil {
92 | return err
93 | }
94 |
95 | for _, line := range lines {
96 | loadPolicyLine(line, model)
97 | }
98 |
99 | return nil
100 | }
101 |
102 | func savePolicyLine(ptype string, rule []string) CasbinRule {
103 | line := CasbinRule{}
104 |
105 | line.PType = ptype
106 | if len(rule) > 0 {
107 | line.V0 = rule[0]
108 | }
109 | if len(rule) > 1 {
110 | line.V1 = rule[1]
111 | }
112 | if len(rule) > 2 {
113 | line.V2 = rule[2]
114 | }
115 | if len(rule) > 3 {
116 | line.V3 = rule[3]
117 | }
118 | if len(rule) > 4 {
119 | line.V4 = rule[4]
120 | }
121 | if len(rule) > 5 {
122 | line.V5 = rule[5]
123 | }
124 |
125 | return line
126 | }
127 |
128 | // SavePolicy saves policy to database.
129 | func (a *Adapter) SavePolicy(model model.Model) error {
130 |
131 | var lines []CasbinRule
132 |
133 | for ptype, ast := range model["p"] {
134 | for _, rule := range ast.Policy {
135 | line := savePolicyLine(ptype, rule)
136 | lines = append(lines, line)
137 | }
138 | }
139 |
140 | for ptype, ast := range model["g"] {
141 | for _, rule := range ast.Policy {
142 | line := savePolicyLine(ptype, rule)
143 | lines = append(lines, line)
144 | }
145 | }
146 |
147 | _, err := a.o.BatchInsert(CASBINRULE_TABLE_NAME, lines)
148 | return err
149 | }
150 |
151 | // AddPolicy adds a policy rule to the storage.
152 | func (a *Adapter) AddPolicy(sec string, ptype string, rule []string) error {
153 | line := savePolicyLine(ptype, rule)
154 | _, err := a.o.Insert(CASBINRULE_TABLE_NAME, &line)
155 | return err
156 | }
157 |
158 | // RemovePolicy removes a policy rule from the storage.
159 | func (a *Adapter) RemovePolicy(sec string, ptype string, rule []string) error {
160 | qs := a.o.Table(CASBINRULE_TABLE_NAME).Safe()
161 | qs = qs.Where("p_type", ptype)
162 | for index := 0; index < len(rule); index++ {
163 | qs = qs.And(fmt.Sprintf("v%d", index), rule[index])
164 | }
165 | _, err := qs.Delete()
166 | return err
167 |
168 | }
169 |
170 | // RemoveFilteredPolicy removes policy rules that match the filter from the storage.
171 | func (a *Adapter) RemoveFilteredPolicy(sec string, ptype string, fieldIndex int, fieldValues ...string) error {
172 | qs := a.o.Table(CASBINRULE_TABLE_NAME).Safe()
173 | qs = qs.Where("p_type", ptype)
174 | for index := 0; index <= 5; index++ {
175 | if fieldIndex <= index && index < fieldIndex+len(fieldValues) {
176 | qs = qs.And(fmt.Sprintf("v%d", index), fieldValues[index-fieldIndex])
177 | }
178 | }
179 | _, err := qs.Delete()
180 | return err
181 | }
182 |
--------------------------------------------------------------------------------
/app/api/userController.go:
--------------------------------------------------------------------------------
1 | package api
2 |
3 | import (
4 | "github.com/gogf/gf/database/gdb"
5 |
6 | "github.com/gogf/gf/os/glog"
7 | "github.com/hailaz/gadmin/app/model"
8 | "github.com/hailaz/gadmin/library/code"
9 | )
10 |
11 | type UserController struct {
12 | BaseController
13 | }
14 |
15 | func (c *UserController) Info() {
16 | u := c.GetUser()
17 | if u != nil {
18 | Success(c.Request, u.GetUserInfo())
19 | }
20 | Fail(c.Request, code.RESPONSE_ERROR, "获取用户信息失败")
21 | }
22 |
23 | func (c *UserController) Menu() {
24 | rolename := c.Request.GetString("rolename")
25 | if rolename != "" {
26 | var list struct {
27 | Menus []model.MenuOut `json:"menus"`
28 | RoleMenus []model.MenuOut `json:"role_menus"`
29 | }
30 | list.Menus = model.GetMenuByRoleName([]string{model.ADMIN_NAME})
31 | list.RoleMenus = model.GetMenuByRoleName([]string{rolename})
32 | Success(c.Request, list)
33 | }
34 | u := c.GetUser()
35 | if u != nil {
36 | if u.UserName == model.ADMIN_NAME {
37 | Success(c.Request, model.GetMenuByRoleName([]string{model.ADMIN_NAME}))
38 | } else {
39 | roles, _ := model.Enforcer.GetRolesForUser(u.UserName)
40 | Success(c.Request, model.GetMenuByRoleName(roles))
41 | }
42 |
43 | }
44 | Fail(c.Request, code.RESPONSE_ERROR, "获取用户菜单失败")
45 | }
46 |
47 | func (c *UserController) Get() {
48 | page := c.Request.GetInt("page", 1)
49 | limit := c.Request.GetInt("limit", 10)
50 | var userList struct {
51 | List []model.UserOut `json:"items"`
52 | Total int `json:"total"`
53 | }
54 | userList.List, userList.Total = model.GetUserByPageLimt(page, limit)
55 | Success(c.Request, userList)
56 | }
57 | func (c *UserController) Post() {
58 | data, _ := c.Request.GetJson()
59 | username := data.GetString("user_name")
60 |
61 | nickname := data.GetString("nick_name")
62 | email := data.GetString("email")
63 | password := data.GetString("password")
64 | passwordconfirm := data.GetString("passwordconfirm")
65 | phone := data.GetString("phone")
66 |
67 | u, err := model.GetUserByName(username)
68 | if u != nil || err == nil {
69 | Fail(c.Request, code.RESPONSE_ERROR, "用户已存在")
70 | }
71 | if password == "" {
72 | Fail(c.Request, code.RESPONSE_ERROR, "密码为空")
73 | }
74 | if password != passwordconfirm {
75 | Fail(c.Request, code.RESPONSE_ERROR, "输入密码不一致")
76 | }
77 | addu := c.GetUser()
78 | var addUserId int64 = 0
79 | if addu != nil {
80 | addUserId = addu.Id
81 | }
82 | user := model.User{UserName: username, Password: password, NickName: nickname, Email: email, Phone: phone, AddUserId: addUserId}
83 | uid, _ := user.Insert()
84 | if uid > 0 {
85 | Success(c.Request, "success")
86 | }
87 |
88 | glog.Debug(uid)
89 | glog.Debug(data.ToJsonString())
90 | Fail(c.Request, code.RESPONSE_ERROR)
91 | }
92 | func (c *UserController) Put() {
93 | data, _ := c.Request.GetJson()
94 | username := data.GetString("user_name")
95 | nickname := data.GetString("nick_name")
96 | email := data.GetString("email")
97 | password := data.GetString("password")
98 | passwordconfirm := data.GetString("passwordconfirm")
99 | phone := data.GetString("phone")
100 |
101 | u, err := model.GetUserByName(username)
102 | if err != nil || u.Id == 0 {
103 | Fail(c.Request, code.RESPONSE_ERROR, "用户不存在")
104 | }
105 | umap := gdb.Map{}
106 | if nickname != u.NickName && nickname != "" {
107 | umap["nick_name"] = nickname
108 | }
109 | if email != u.Email && email != "" {
110 | umap["email"] = email
111 | }
112 | if phone != u.Phone && phone != "" {
113 | umap["phone"] = phone
114 | }
115 | if password == "" {
116 | err := model.UpdateUserById(u.Id, umap)
117 | if err != nil {
118 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
119 | }
120 | } else {
121 | if password != passwordconfirm {
122 | Fail(c.Request, code.RESPONSE_ERROR, "输入密码不一致")
123 | }
124 | umap["password"] = model.EncryptPassword(password)
125 | err := model.UpdateUserById(u.Id, umap)
126 | if err != nil {
127 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
128 | }
129 | }
130 |
131 | Success(c.Request, "success")
132 | }
133 | func (c *UserController) Delete() {
134 | data, _ := c.Request.GetJson()
135 | id := data.GetInt64("id")
136 | if id < 1 {
137 | Fail(c.Request, code.RESPONSE_ERROR)
138 | }
139 | u := new(model.User)
140 | user, err := u.GetById(id)
141 | if err != nil {
142 | Fail(c.Request, code.RESPONSE_ERROR, err.Error())
143 | }
144 | if user.UserName == model.ADMIN_NAME {
145 | Fail(c.Request, code.RESPONSE_ERROR, "无权限")
146 | }
147 | res, _ := u.DeleteById(id)
148 | if res <= 0 {
149 | Fail(c.Request, code.RESPONSE_ERROR)
150 | }
151 | model.Enforcer.DeleteRolesForUser(user.UserName)
152 | Success(c.Request, "success")
153 | }
154 |
--------------------------------------------------------------------------------
/router/router.go:
--------------------------------------------------------------------------------
1 | package router
2 |
3 | import (
4 | "fmt"
5 |
6 | "github.com/gogf/gf/encoding/gparser"
7 | "github.com/gogf/gf/frame/g"
8 |
9 | "github.com/gogf/gf/net/ghttp"
10 | "github.com/gogf/gf/os/glog"
11 | "github.com/gogf/gf/util/gconv"
12 | "github.com/hailaz/gadmin/app/api"
13 | "github.com/hailaz/gadmin/app/model"
14 | "github.com/hailaz/gadmin/library/common"
15 | )
16 |
17 | var routerMap = make(map[string]model.RolePolicy)
18 |
19 | func showURL(r *ghttp.Request) {
20 | glog.Debug("请求路径:", r.Method, r.Request.RequestURI)
21 | //r.Response.CORSDefault()
22 | }
23 |
24 | // InitRouter 初始化路由
25 | //
26 | // createTime:2019年05月13日 09:32:58
27 | // author:hailaz
28 | func InitRouter(s *ghttp.Server) {
29 | initApiDocRouter(s)
30 |
31 | s.BindHookHandler("/*", ghttp.HOOK_BEFORE_SERVE, showURL)
32 | InitV1(s)
33 |
34 | model.ReSetPolicy("system", routerMap)
35 | }
36 |
37 | // authHook 鉴权钩子
38 | //
39 | // createTime:2019年05月13日 09:33:58
40 | // author:hailaz
41 | // authHook is the HOOK function implements JWT logistics.
42 | func authHook(r *ghttp.Request) {
43 | switch r.Request.RequestURI { //登录相关免鉴权
44 | case "/v1/loginkey":
45 | return
46 | case "/v1/login":
47 | return
48 | default:
49 | r.Response.CORSDefault() //开启跨域
50 | api.GfJWTMiddleware.MiddlewareFunc()(r) //鉴权中间件
51 | }
52 | }
53 |
54 | // InitV1 初始化V1
55 | //
56 | // createTime:2019年04月25日 09:24:06
57 | // author:hailaz
58 | func InitV1(s *ghttp.Server) {
59 | //v1 := s.Group("/v1")
60 | //权限验证
61 | s.Group("/v1").ALL("/*any", authHook, ghttp.HOOK_BEFORE_SERVE)
62 | userCtrl := new(api.UserController)
63 | roleCtrl := new(api.RoleController)
64 | policyCtrl := new(api.PolicyController)
65 | menuCtrl := new(api.MenuController)
66 |
67 | // user
68 | BindGroup(s, "/v1", []ghttp.GroupItem{
69 | //登录
70 | {"false", "GET", "/loginkey", api.GetLoginCryptoKey}, //获取登录加密公钥
71 | {"false", "POST", "/login", api.GfJWTMiddleware.LoginHandler}, //登录
72 | {"false", "GET", "/refresh_token", api.GfJWTMiddleware.RefreshHandler}, //获取登录加密公钥
73 | {"false", "POST", "/logout", api.Logout}, //登出
74 | //menu
75 | {"", "REST", "/menu", menuCtrl},
76 | // 用户
77 | {"false", "GET", "/user/info", userCtrl, "Info"},
78 | {"false", "GET", "/user/menu", userCtrl, "Menu"},
79 | {"", "REST", "/user", userCtrl},
80 | // 角色
81 | {"", "REST", "/role", roleCtrl},
82 | {"", "PUT", "/role/byuser", roleCtrl, "SetRoleByUserName"},
83 | {"", "PUT", "/role/menu", roleCtrl, "SetRoleMenus"},
84 | // 权限
85 | {"", "REST", "/policy", policyCtrl},
86 | {"", "GET", "/policy/byrole", policyCtrl, "GetPolicyByRole"},
87 | {"", "PUT", "/policy/byrole", policyCtrl, "SetPolicyByRole"},
88 | })
89 | }
90 |
91 | // BindGroup 绑定分组路由
92 | //
93 | // createTime:2019年04月29日 16:45:55
94 | // author:hailaz
95 | func BindGroup(s *ghttp.Server, path string, items []ghttp.GroupItem) {
96 | for index, item := range items {
97 | if gconv.String(item[0]) == "false" { //不走权限的api
98 | addPolicy("*", path+gconv.String(item[2]), common.GetAction(gconv.String(item[1])))
99 | } else { //走权限的api
100 | if gconv.String(item[1]) == "REST" { //rest api
101 | addPolicy("system", path+gconv.String(item[2]), model.ACTION_GET)
102 | addPolicy("system", path+gconv.String(item[2]), model.ACTION_POST)
103 | addPolicy("system", path+gconv.String(item[2]), model.ACTION_PUT)
104 | addPolicy("system", path+gconv.String(item[2]), model.ACTION_DELETE)
105 | } else {
106 | addPolicy("system", path+gconv.String(item[2]), common.GetAction(gconv.String(item[1])))
107 | }
108 | }
109 | // 裁切掉权限控制
110 | items[index] = items[index][1:]
111 | }
112 |
113 | g := s.Group(path)
114 | g.Bind(items)
115 |
116 | }
117 |
118 | // addPolicy 记录需要系统路由
119 | //
120 | // createTime:2019年04月29日 17:18:25
121 | // author:hailaz
122 | func addPolicy(role, path, atc string) {
123 | routerMap[fmt.Sprintf("%v %v %v", role, path, atc)] = model.RolePolicy{Role: role, Path: path, Atc: atc}
124 | }
125 |
126 | // initApiDocRouter 初始化api文档路由
127 | //
128 | // createTime:2019年05月14日 09:05:26
129 | // author:hailaz
130 | func initApiDocRouter(s *ghttp.Server) {
131 | s.BindHandler("/swagger.{mime}", func(r *ghttp.Request) {
132 | r.Response.CORSDefault()
133 | r.Response.Header().Set("Access-Control-Allow-Origin", "*")
134 | //r.Response.Writeln(r.Get("mime"))
135 | p, err := gparser.Load("docfile/swagger.yaml")
136 | if err != nil {
137 | r.Response.Writeln(err.Error())
138 | return
139 | }
140 |
141 | switch r.Get("mime") {
142 | case "json":
143 | j, _ := p.ToJson()
144 | r.Response.WriteJson(j)
145 | default:
146 | y, _ := p.ToYaml()
147 | r.Response.Write(y)
148 | }
149 |
150 | })
151 | s.BindHandler("/swagger", func(r *ghttp.Request) {
152 | r.Response.RedirectTo("https://petstore.swagger.io/?url=http://localhost:" + g.Config().GetString("port", "8080") + "/swagger.yaml")
153 | })
154 | }
155 |
--------------------------------------------------------------------------------
/static/js/chunk-cbf46a0a.daf42114.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-cbf46a0a"],{"01e6":function(t,n,e){},2017:function(t,n,e){"use strict";var s=e("3b76"),o=e.n(s);o.a},"3b76":function(t,n,e){},"4cba":function(t,n,e){"use strict";var s=e("b63b"),o=e.n(s);o.a},"9ed6":function(t,n,e){"use strict";e.r(n);var s=function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",{staticClass:"login-container"},[e("el-form",{ref:"loginForm",staticClass:"login-form",attrs:{model:t.loginForm,rules:t.loginRules,"auto-complete":"on","label-position":"left"}},[e("div",{staticClass:"title-container"},[e("h3",{staticClass:"title"},[t._v("\n "+t._s(t.$t("login.title"))+"\n ")]),t._v(" "),e("lang-select",{staticClass:"set-language"})],1),t._v(" "),e("el-form-item",{attrs:{prop:"username"}},[e("span",{staticClass:"svg-container"},[e("svg-icon",{attrs:{"icon-class":"user"}})],1),t._v(" "),e("el-input",{ref:"username",attrs:{placeholder:t.$t("login.username"),name:"username",type:"text",tabindex:"1","auto-complete":"on"},model:{value:t.loginForm.username,callback:function(n){t.$set(t.loginForm,"username",n)},expression:"loginForm.username"}})],1),t._v(" "),e("el-tooltip",{attrs:{content:"Caps lock is On",placement:"right",manual:""},model:{value:t.capsTooltip,callback:function(n){t.capsTooltip=n},expression:"capsTooltip"}},[e("el-form-item",{attrs:{prop:"password"}},[e("span",{staticClass:"svg-container"},[e("svg-icon",{attrs:{"icon-class":"password"}})],1),t._v(" "),e("el-input",{key:t.passwordType,ref:"password",attrs:{type:t.passwordType,placeholder:t.$t("login.password"),name:"password",tabindex:"2","auto-complete":"on"},on:{blur:function(n){t.capsTooltip=!1}},nativeOn:{keyup:[function(n){return t.checkCapslock(n)},function(n){return!n.type.indexOf("key")&&t._k(n.keyCode,"enter",13,n.key,"Enter")?null:t.handleLogin(n)}]},model:{value:t.loginForm.password,callback:function(n){t.$set(t.loginForm,"password",n)},expression:"loginForm.password"}}),t._v(" "),e("span",{staticClass:"show-pwd",on:{click:t.showPwd}},[e("svg-icon",{attrs:{"icon-class":"password"===t.passwordType?"eye":"eye-open"}})],1)],1)],1),t._v(" "),e("el-button",{staticStyle:{width:"100%","margin-bottom":"30px"},attrs:{loading:t.loading,type:"primary"},nativeOn:{click:function(n){return n.preventDefault(),t.handleLogin(n)}}},[t._v("\n "+t._s(t.$t("login.logIn"))+"\n ")])],1),t._v(" "),e("el-dialog",{attrs:{title:t.$t("login.thirdparty"),visible:t.showDialog},on:{"update:visible":function(n){t.showDialog=n}}},[t._v("\n "+t._s(t.$t("login.thirdpartyTips"))+"\n "),e("br"),t._v(" "),e("br"),t._v(" "),e("br"),t._v(" "),e("social-sign")],1)],1)},o=[],i=e("a4bb"),a=e.n(i),r=e("1131"),c=function(){var t=this,n=t.$createElement,e=t._self._c||n;return e("div",{staticClass:"social-signup-container"},[e("div",{staticClass:"sign-btn",on:{click:function(n){return t.wechatHandleClick("wechat")}}},[e("span",{staticClass:"wx-svg-container"},[e("svg-icon",{staticClass:"icon",attrs:{"icon-class":"wechat"}})],1),t._v("\n WeChat\n ")]),t._v(" "),e("div",{staticClass:"sign-btn",on:{click:function(n){return t.tencentHandleClick("tencent")}}},[e("span",{staticClass:"qq-svg-container"},[e("svg-icon",{staticClass:"icon",attrs:{"icon-class":"qq"}})],1),t._v("\n QQ\n ")])])},l=[],u={name:"SocialSignin",methods:{wechatHandleClick:function(t){alert("ok")},tencentHandleClick:function(t){alert("ok")}}},p=u,d=(e("edc1"),e("2877")),g=Object(d["a"])(p,c,l,!1,null,"c817cede",null),h=g.exports,f={name:"Login",components:{LangSelect:r["a"],SocialSign:h},data:function(){var t=function(t,n,e){e()},n=function(t,n,e){n.length<6?e(new Error("The password can not be less than 6 digits")):e()};return{loginForm:{username:"admin",password:"123456"},loginRules:{username:[{required:!0,trigger:"blur",validator:t}],password:[{required:!0,trigger:"blur",validator:n}]},passwordType:"password",capsTooltip:!1,loading:!1,showDialog:!1,redirect:void 0,otherQuery:{}}},watch:{$route:{handler:function(t){var n=t.query;n&&(this.redirect=n.redirect,this.otherQuery=this.getOtherQuery(n))},immediate:!0}},created:function(){},mounted:function(){""===this.loginForm.username?this.$refs.username.focus():""===this.loginForm.password&&this.$refs.password.focus()},destroyed:function(){},methods:{checkCapslock:function(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},n=t.shiftKey,e=t.key;e&&1===e.length&&(this.capsTooltip=!!(n&&e>="a"&&e<="z"||!n&&e>="A"&&e<="Z")),"CapsLock"===e&&!0===this.capsTooltip&&(this.capsTooltip=!1)},showPwd:function(){var t=this;"password"===this.passwordType?this.passwordType="":this.passwordType="password",this.$nextTick(function(){t.$refs.password.focus()})},handleLogin:function(){var t=this;this.$refs.loginForm.validate(function(n){if(!n)return console.log("error submit!!"),!1;t.loading=!0,t.$store.dispatch("user/login",t.loginForm).then(function(){t.$router.push({path:t.redirect||"/",query:t.otherQuery}),t.loading=!1}).catch(function(){t.loading=!1})})},getOtherQuery:function(t){return a()(t).reduce(function(n,e){return"redirect"!==e&&(n[e]=t[e]),n},{})}}},m=f,v=(e("2017"),e("4cba"),Object(d["a"])(m,s,o,!1,null,"40da4f90",null));n["default"]=v.exports},b63b:function(t,n,e){},edc1:function(t,n,e){"use strict";var s=e("01e6"),o=e.n(s);o.a}}]);
--------------------------------------------------------------------------------
/static/js/chunk-2a330e22.9d637d72.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-2a330e22"],{"0bca":function(t,a,e){"use strict";var n=e("e9b4"),i=e.n(n);i.a},"22a6":function(t,a,e){},2452:function(t,a,e){"use strict";var n=e("8715"),i=e.n(n);i.a},"364d":function(t,a,e){"use strict";var n=e("c65c"),i=e.n(n);i.a},"3cbc":function(t,a,e){"use strict";var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"pan-item",style:{zIndex:t.zIndex,height:t.height,width:t.width}},[e("div",{staticClass:"pan-info"},[e("div",{staticClass:"pan-info-roles-container"},[t._t("default")],2)]),t._v(" "),e("img",{staticClass:"pan-thumb",attrs:{src:t.image}})])},i=[],s=(e("c5f6"),{name:"PanThumb",props:{image:{type:String,required:!0},zIndex:{type:Number,default:1},width:{type:String,default:"150px"},height:{type:String,default:"150px"}}}),r=s,c=(e("2452"),e("2877")),o=Object(c["a"])(r,n,i,!1,null,"0d3d578f",null);a["a"]=o.exports},8715:function(t,a,e){},9406:function(t,a,e){"use strict";e.r(a);var n=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"dashboard-container"},[e(t.currentRole,{tag:"component"})],1)},i=[],s=(e("6762"),e("2fdb"),e("cebc")),r=e("2f62"),c=function(){var t=this,a=t.$createElement;t._self._c;return t._m(0)},o=[function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"dashboard-editor-container"},[t._v("\n Welcome to gadmin!\n "),e("br"),t._v(" "),e("a",{attrs:{href:"https://github.com/hailaz/gadmin",target:"_blank",rel:"noopener noreferrer"}},[e("img",{staticStyle:{width:"90%","max-width":"1200px"},attrs:{src:"https://github.com/hailaz/gadmin/raw/master/docfile/gadmin.png",alt:"gadmin结构",title:"访问 gadmin github"}})])])}],l={newVisitis:{expectedData:[100,120,161,134,105,160,165],actualData:[120,82,91,154,162,140,145]},messages:{expectedData:[200,192,120,144,160,130,140],actualData:[180,160,151,106,145,150,130]},purchases:{expectedData:[80,100,121,104,105,90,100],actualData:[120,90,100,138,142,130,130]},shoppings:{expectedData:[130,140,141,142,145,150,160],actualData:[120,82,91,154,162,140,130]}},d={name:"DashboardAdmin",components:{},data:function(){return{lineChartData:l.newVisitis}},methods:{handleSetLineChartData:function(t){this.lineChartData=l[t]}}},u=d,h=(e("0bca"),e("2877")),f=Object(h["a"])(u,c,o,!1,null,"6eb39d8e",null),p=f.exports,m=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("div",{staticClass:"dashboard-editor-container"},[e("div",{staticClass:" clearfix"},[e("pan-thumb",{staticStyle:{float:"left"},attrs:{image:t.avatar}},[t._v("\n Your roles:\n "),t._l(t.roles,function(a){return e("span",{key:a,staticClass:"pan-info-roles"},[t._v(t._s(a))])})],2),t._v(" "),e("github-corner",{staticStyle:{position:"absolute",top:"0px",border:"0",right:"0"}}),t._v(" "),e("div",{staticClass:"info-container"},[e("span",{staticClass:"display_name"},[t._v(t._s(t.name))]),t._v(" "),e("span",{staticStyle:{"font-size":"20px","padding-top":"20px",display:"inline-block"}},[t._v("Editor's Dashboard")])])],1),t._v(" "),e("div",[e("img",{staticClass:"emptyGif",attrs:{src:t.emptyGif}})])])},b=[],C=e("3cbc"),v=function(){var t=this,a=t.$createElement,e=t._self._c||a;return e("a",{staticClass:"github-corner",attrs:{href:"https://github.com/PanJiaChen/vue-element-admin",target:"_blank","aria-label":"View source on Github"}},[e("svg",{staticStyle:{fill:"#40c9c6",color:"#fff"},attrs:{width:"80",height:"80",viewBox:"0 0 250 250","aria-hidden":"true"}},[e("path",{attrs:{d:"M0,0 L115,115 L130,115 L142,142 L250,250 L250,0 Z"}}),t._v(" "),e("path",{staticClass:"octo-arm",staticStyle:{"transform-origin":"130px 106px"},attrs:{d:"M128.3,109.0 C113.8,99.7 119.0,89.6 119.0,89.6 C122.0,82.7 120.5,78.6 120.5,78.6 C119.2,72.0 123.4,76.3 123.4,76.3 C127.3,80.9 125.5,87.3 125.5,87.3 C122.9,97.6 130.6,101.9 134.4,103.2",fill:"currentColor"}}),t._v(" "),e("path",{staticClass:"octo-body",attrs:{d:"M115.0,115.0 C114.9,115.1 118.7,116.5 119.8,115.4 L133.7,101.6 C136.9,99.2 139.9,98.4 142.2,98.6 C133.8,88.0 127.5,74.4 143.8,58.0 C148.5,53.4 154.0,51.2 159.7,51.0 C160.3,49.4 163.2,43.6 171.4,40.1 C171.4,40.1 176.1,42.5 178.8,56.2 C183.1,58.6 187.2,61.8 190.9,65.4 C194.5,69.0 197.7,73.2 200.1,77.6 C213.8,80.2 216.3,84.9 216.3,84.9 C212.7,93.1 206.9,96.0 205.4,96.6 C205.1,102.4 203.0,107.8 198.3,112.5 C181.9,128.9 168.3,122.5 157.7,114.1 C157.9,116.9 156.7,120.9 152.7,124.9 L141.0,136.5 C139.8,137.7 141.6,141.9 141.8,141.8 Z",fill:"currentColor"}})])])},g=[],_=(e("364d"),{}),x=Object(h["a"])(_,v,g,!1,null,"4c6d8d88",null),w=x.exports,D={name:"DashboardEditor",components:{PanThumb:C["a"],GithubCorner:w},data:function(){return{emptyGif:"https://wpimg.wallstcn.com/0e03b7da-db9e-4819-ba10-9016ddfdaed3"}},computed:Object(s["a"])({},Object(r["b"])(["name","avatar","roles"]))},y=D,S=(e("efff"),Object(h["a"])(y,m,b,!1,null,"9c953d6a",null)),j=S.exports,O={name:"Dashboard",components:{adminDashboard:p,editorDashboard:j},data:function(){return{currentRole:"adminDashboard"}},computed:Object(s["a"])({},Object(r["b"])(["roles"])),created:function(){this.roles.includes("admin")||(this.currentRole="editorDashboard")}},E=O,L=Object(h["a"])(E,n,i,!1,null,null,null);a["default"]=L.exports},c65c:function(t,a,e){},e9b4:function(t,a,e){},efff:function(t,a,e){"use strict";var n=e("22a6"),i=e.n(n);i.a}}]);
--------------------------------------------------------------------------------
/go.sum:
--------------------------------------------------------------------------------
1 | github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
2 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
3 | github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw=
4 | github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
5 | github.com/casbin/casbin v1.9.1 h1:ucjbS5zTrmSLtH4XogqOG920Poe6QatdXtz1FEbApeM=
6 | github.com/casbin/casbin v1.9.1/go.mod h1:z8uPsfBJGUsnkagrt3G8QvjgTKFMBJ32UP8HpZllfog=
7 | github.com/clbanning/mxj v1.8.4 h1:HuhwZtbyvyOw+3Z1AowPkU87JkJUSv751ELWaiTpj8I=
8 | github.com/clbanning/mxj v1.8.4/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng=
9 | github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
10 | github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
11 | github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
12 | github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
13 | github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
14 | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
15 | github.com/gf-third/mysql v1.4.2 h1:f1M5CNFUG3WkE07UOomtu4o0n/KJKeuUUf5Nc9ZFXs4=
16 | github.com/gf-third/mysql v1.4.2/go.mod h1:+dd90V663ppI2fV5uQ6+rHk0u8KCyU6FkG8Um8Cx3ms=
17 | github.com/gf-third/yaml v1.0.1 h1:pqD4ix+65DqGphU1MDnToPZfGYk0tuuwRzuTSl3g0d0=
18 | github.com/gf-third/yaml v1.0.1/go.mod h1:t443vj0txEw3+E0MOtkr83kt+PrZg2I8SRuYfn85NM0=
19 | github.com/gogf/gf v1.9.7/go.mod h1:sitJZHjmT9B+923N4mH5rkM19AugKG+BxI47R64bR08=
20 | github.com/gogf/gf v1.11.3 h1:2CRPTGqbeSRTLZLBF8r6TOeT3eMinQfUWReLWiJTJ9Q=
21 | github.com/gogf/gf v1.11.3/go.mod h1:/37gncPmuM06D4YSqiDze9GsasDtF2QnWkUfKeiGW/Q=
22 | github.com/gogf/gf-jwt v1.1.0 h1:FrtDAMyaexbj/cEDTcSn2ViPVwAvkds2eGhKO80ZA8w=
23 | github.com/gogf/gf-jwt v1.1.0/go.mod h1:m4TC9GrveQM7peXcZfsgz9QUkMlacSsk39e6kYQPUQs=
24 | github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
25 | github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0=
26 | github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4=
27 | github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
28 | github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
29 | github.com/gorilla/websocket v1.4.1 h1:q7AeDBpnBk8AogcD4DSag/Ukw/KV+YhzLj2bP5HvKCM=
30 | github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
31 | github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf h1:wIOAyJMMen0ELGiFzlmqxdcV1yGbkyHBAB6PolcNbLA=
32 | github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
33 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
34 | github.com/mattn/go-runewidth v0.0.7 h1:Ei8KR0497xHyKJPAv59M1dkC+rOZCMBJ+t3fZ+twI54=
35 | github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
36 | github.com/olekukonko/tablewriter v0.0.1 h1:b3iUnf1v+ppJiOfNX4yxxqfWKMQPZR5yoh8urCTFX88=
37 | github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
38 | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
39 | golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
40 | golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
41 | golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
42 | golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
43 | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
44 | golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
45 | golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
46 | golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
47 | golang.org/x/sys v0.0.0-20190924092210-98129a5cf4a0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
48 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e h1:9vRrk9YW2BTzLP0VCB9ZDjU4cPqkg+IDWL7XgxA1yxQ=
49 | golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
50 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
51 | golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
52 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
53 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
54 | golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
55 | google.golang.org/appengine v1.6.3 h1:hvZejVcIxAKHR8Pq2gXaDggf6CWT1QEqO+JEBeOKCG8=
56 | google.golang.org/appengine v1.6.3/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
57 |
--------------------------------------------------------------------------------
/app/api/auth.go:
--------------------------------------------------------------------------------
1 | package api
2 |
3 | import (
4 | "encoding/base64"
5 | "time"
6 |
7 | jwt "github.com/gogf/gf-jwt"
8 | "github.com/gogf/gf/frame/g"
9 | "github.com/gogf/gf/net/ghttp"
10 | "github.com/gogf/gf/os/glog"
11 | "github.com/gogf/gf/os/gtime"
12 | "github.com/hailaz/gadmin/app/model"
13 | "github.com/hailaz/gadmin/library/common"
14 | )
15 |
16 | var (
17 | // The underlying JWT middleware.
18 | GfJWTMiddleware *jwt.GfJWTMiddleware
19 | )
20 |
21 | // Initialization function,
22 | // rewrite this function to customized your own JWT settings.
23 | func init() {
24 | authMiddleware, err := jwt.New(&jwt.GfJWTMiddleware{
25 | Realm: "gf admin",
26 | Key: []byte("secret key"),
27 | Timeout: time.Minute * 10, //token有效时间
28 | MaxRefresh: time.Minute * 10, //token刷新有效时间
29 | IdentityKey: "username", // 用户关键字
30 | TokenLookup: "header: Authorization", // 捕抓请求的指定数据
31 | TokenHeadName: "gadmin", // token 头名称
32 | TimeFunc: time.Now,
33 | Authenticator: Authenticator, //登录验证
34 | LoginResponse: LoginResponse, //登录返回token
35 | RefreshResponse: RefreshResponse, //刷新token
36 | Unauthorized: Unauthorized, //未登录返回
37 | IdentityHandler: IdentityHandler, //返回数据给Authorizator
38 | PayloadFunc: PayloadFunc, //将Authenticator返回的内容记录到jwt
39 | Authorizator: Authorizator, //接收IdentityHandler数据并判断权限
40 | HTTPStatusMessageFunc: HTTPStatusMessageFunc, //错误处理
41 | })
42 | if err != nil {
43 | glog.Fatal("JWT Error:" + err.Error())
44 | }
45 | GfJWTMiddleware = authMiddleware
46 | }
47 |
48 | // GetLoginCryptoKey 获取登录的加密key
49 | //
50 | // createTime:2019年04月24日 13:57:34
51 | // author:hailaz
52 | func GetLoginCryptoKey(r *ghttp.Request) {
53 | kid := r.Session.Id()
54 | ck := common.GenCryptoKey(kid)
55 | // glog.Debug("kid:" + kid)
56 | Success(r, ck)
57 | }
58 |
59 | func Logout(r *ghttp.Request) {
60 | Success(r, "success")
61 | }
62 |
63 | func PayloadFunc(data interface{}) jwt.MapClaims {
64 | claims := jwt.MapClaims{}
65 | params := data.(map[string]interface{})
66 | if len(params) > 0 {
67 | for k, v := range params {
68 | claims[k] = v
69 | }
70 | }
71 | return claims
72 | }
73 |
74 | func Authorizator(data interface{}, r *ghttp.Request) bool {
75 | method := r.Method
76 | path := r.URL.Path
77 | //glog.Debugf("user:%v ,method:%v ,path:%v", data, method, path)
78 | return model.Enforcer.Enforce(data, path, method)
79 | }
80 |
81 | // IdentityHandler sets the identity for JWT.
82 | func IdentityHandler(r *ghttp.Request) interface{} {
83 | claims := jwt.ExtractClaims(r)
84 | return claims["username"]
85 | }
86 |
87 | // Unauthorized is used to define customized Unauthorized callback function.
88 | func Unauthorized(r *ghttp.Request, code int, message string) {
89 | Fail(r, code, message)
90 | }
91 |
92 | func HTTPStatusMessageFunc(e error, r *ghttp.Request) string {
93 | glog.Debug(e.Error())
94 | switch e.Error() {
95 | case "Token is expired":
96 | return "token超时"
97 | }
98 | return e.Error()
99 | }
100 |
101 | // LoginResponse is used to define customized login-successful callback function.
102 | func LoginResponse(r *ghttp.Request, code int, token string, expire time.Time) {
103 | var tk struct {
104 | Token string `json:"token"`
105 | Expire string `json:"expire"`
106 | }
107 | tk.Token = GfJWTMiddleware.TokenHeadName + " " + token
108 | tk.Expire = expire.Format(time.RFC3339)
109 | Success(r, tk)
110 | }
111 |
112 | // RefreshResponse is used to get a new token no matter current token is expired or not.
113 | func RefreshResponse(r *ghttp.Request, code int, token string, expire time.Time) {
114 | var tk struct {
115 | Token string `json:"token"`
116 | Expire string `json:"expire"`
117 | }
118 | tk.Token = GfJWTMiddleware.TokenHeadName + " " + token
119 | tk.Expire = expire.Format(time.RFC3339)
120 | Success(r, tk)
121 | }
122 |
123 | // Authenticator 登录验证
124 | //
125 | // createTime:2019年05月13日 10:00:22
126 | // author:hailaz
127 | func Authenticator(r *ghttp.Request) (interface{}, error) {
128 | data, _ := r.GetJson()
129 | name := data.GetString("username")
130 | pwd := data.GetString("password")
131 | kid := data.GetString("kid")
132 |
133 | if ck := common.GetCryptoKey(kid); ck != nil {
134 | if gtime.Second()-ck.TimeStamp >= 5 { //加密key超时时间
135 | return nil, jwt.ErrFailedAuthentication
136 | }
137 | //glog.Debugf("%v", ck.Id)
138 | //glog.Debugf("%v", ck.Key)
139 | //glog.Debugf("%v %v", name, pwd)
140 | decodePwd, err := base64.StdEncoding.DecodeString(pwd)
141 | if err != nil {
142 | return nil, err
143 | }
144 | decryptPwd, _ := common.RsaDecrypt(decodePwd, []byte(ck.PrivateKey))
145 | //glog.Debug(string(decryptPwd))
146 | password := string(decryptPwd)
147 | //glog.Debugf("%v %v", name, password)
148 | if password != "" {
149 | u, err := model.GetUserByName(name)
150 | if err != nil {
151 | return nil, err
152 | }
153 | if u.Password == model.EncryptPassword(password) {
154 | return g.Map{
155 | "username": u.UserName,
156 | "id": u.Id,
157 | }, nil
158 | }
159 |
160 | }
161 | }
162 |
163 | return nil, jwt.ErrFailedAuthentication
164 | }
165 |
--------------------------------------------------------------------------------
/app/model/menu.go:
--------------------------------------------------------------------------------
1 | package model
2 |
3 | import (
4 | "github.com/gogf/gf/frame/g"
5 | "github.com/gogf/gf/database/gdb"
6 | )
7 |
8 | type MenuMetaOut struct {
9 | Id int64 `json:"-"` //
10 | MenuName string `json:"-"` //菜单关键名
11 | Title string `json:"title"` //名称
12 | Icon string `json:"icon"` //图标
13 | Nocache bool `json:"noCache"` //是否缓存
14 | }
15 |
16 | type MenuOut struct {
17 | Id int64 `json:"-"` //
18 | MenuPath string `json:"path"` //菜单路径
19 | Component string `json:"component"` //页面模块
20 | Redirect string `json:"redirect"` //重定向地址
21 | Name string `json:"name"` //唯一关键名
22 | Hidden bool `json:"hidden"` //是否隐藏
23 | Alwaysshow bool `json:"alwaysShow"` //是否常显示
24 | Sort int `json:"sort"` //排序
25 | ParentName string `json:"parent_name"` //父菜级关键名
26 | AutoCreate bool `json:"auto_create"` //是否自动生成
27 | MenuMetaOut MenuMetaOut `json:"meta"`
28 | Children []MenuOut `json:"children"`
29 | }
30 |
31 | // IsStringInSlice description
32 | //
33 | // createTime:2019年05月21日 15:50:15
34 | // author:hailaz
35 | func IsStringInSlice(str string, strs []string) bool {
36 | for _, item := range strs {
37 | if item == str {
38 | return true
39 | }
40 | }
41 | return false
42 | }
43 |
44 | // GetMenuByRoleName description
45 | //
46 | // createTime:2019年05月16日 17:19:53
47 | // author:hailaz
48 | func GetMenuByRoleName(roles []string) []MenuOut {
49 | menus := make([]MenuOut, 0)
50 | if IsStringInSlice(ADMIN_NAME, roles) {
51 | r, _ := defDB.Table("menu").All()
52 | r.ToStructs(&menus)
53 | } else {
54 | roleSlice := make(g.Slice, 0)
55 | for _, item := range roles {
56 | roleSlice = append(roleSlice, item)
57 | }
58 | r, _ := defDB.Table("role_menu rm,menu m").Where("rm.menu_name=m.name AND rm.role_key IN (?)", roleSlice).Fields("m.*").All()
59 | r.ToStructs(&menus)
60 | }
61 |
62 | for index, item := range menus {
63 | meta := MenuMetaOut{}
64 | r, _ := defDB.Table("menu_meta").Where("menu_name=?", item.Name).One()
65 | r.ToStruct(&meta)
66 | menus[index].MenuMetaOut = meta
67 | }
68 | menuRoot := make([]MenuOut, 0)
69 | childs := make([]*MenuOut, 0)
70 | for index, item := range menus { //分类菜单,一级菜单与非一级菜单
71 | if item.ParentName == "" {
72 | menuRoot = append(menuRoot, item)
73 | } else {
74 | childs = append(childs, &menus[index])
75 | }
76 | }
77 | for index, _ := range menuRoot {
78 | FindChildren(&menuRoot[index], childs)
79 | }
80 |
81 | return menuRoot
82 | }
83 |
84 | // FindChildren 找子菜单
85 | //
86 | // createTime:2019年05月17日 09:15:52
87 | // author:hailaz
88 | func FindChildren(mo *MenuOut, list []*MenuOut) {
89 | for _, item := range list {
90 | if item.ParentName == mo.Name {
91 | mo.Children = append(mo.Children, *item)
92 | }
93 | }
94 | for index := 0; index < len(mo.Children); index++ {
95 | FindChildren(&mo.Children[index], list)
96 | }
97 | }
98 |
99 | // GetMenuByName 根据名称获取菜单
100 | //
101 | // createTime:2019年04月23日 17:14:22
102 | // author:hailaz
103 | func GetMenuByName(name string) (*Menu, error) {
104 | m := Menu{}
105 | err := defDB.Table("menu").Where("name", name).Struct(&m)
106 | if err != nil {
107 | return nil, err
108 | }
109 | return &m, nil
110 | }
111 |
112 | // IsMenuExist 菜单是否存在
113 | //
114 | // createTime:2019年05月17日 11:04:45
115 | // author:hailaz
116 | func IsMenuExist(name string) bool {
117 | m := Menu{}
118 | defDB.Table("menu").Where("name", name).Struct(&m)
119 | if m.Id > 0 {
120 | return true
121 | }
122 | return false
123 | }
124 |
125 | // InsertMenuWithMeta 插入菜单
126 | //
127 | // createTime:2019年05月17日 11:12:13
128 | // author:hailaz
129 | func InsertMenuWithMeta(list gdb.List) {
130 | for _, item := range list {
131 | if !IsMenuExist(item["name"].(string)) {
132 | mate := item["meta"].(gdb.Map)
133 | mate["menu_name"] = item["name"].(string)
134 | delete(item, "meta")
135 | defDB.Insert("menu", item)
136 | defDB.Insert("menu_meta", mate)
137 | }
138 | }
139 | }
140 |
141 | // GetMenuList 获取菜单列表
142 | //
143 | // createTime:2019年05月17日 16:17:33
144 | // author:hailaz
145 | func GetMenuList(page, limit int) ([]MenuOut, int) {
146 | if page < 1 {
147 | page = 1
148 | }
149 | if limit < 1 {
150 | limit = 10
151 | }
152 | total, _ := defDB.Table("menu").Count()
153 | if total == 0 {
154 | return nil, 0
155 | }
156 |
157 | menuList := make([]MenuOut, 0)
158 | if total < page*limit {
159 | if total < limit {
160 | page = 1
161 | }
162 | }
163 | r, err := defDB.Table("menu").Limit((page-1)*limit, (page-1)*limit+limit).Select()
164 | if err != nil {
165 | return nil, 0
166 | }
167 | r.ToStructs(&menuList)
168 | for index, item := range menuList {
169 | meta := MenuMetaOut{}
170 | r, _ := defDB.Table("menu_meta").Where("menu_name=?", item.Name).One()
171 | r.ToStruct(&meta)
172 | menuList[index].MenuMetaOut = meta
173 | }
174 | return menuList, total
175 | }
176 |
177 | // UpdateMenuByName description
178 | //
179 | // createTime:2019年05月17日 17:54:40
180 | // author:hailaz
181 | func UpdateMenuByName(name string, dataMap gdb.Map) error {
182 | mate := dataMap["meta"].(gdb.Map)
183 | delete(dataMap, "meta")
184 | _, err := defDB.Update("menu", dataMap, "name=?", name)
185 | if err != nil {
186 | return err
187 | }
188 | _, err = defDB.Update("menu_meta", mate, "menu_name=?", name)
189 | if err != nil {
190 | return err
191 | }
192 | return nil
193 | }
194 |
--------------------------------------------------------------------------------
/static/js/chunk-296d0504.61c10fec.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-296d0504"],{"0f7b":function(t,e,n){"use strict";var i=n("e4d3"),a=n.n(i);a.a},"1b26":function(t,e,n){"use strict";n.d(e,"b",function(){return a}),n.d(e,"d",function(){return o}),n.d(e,"a",function(){return r}),n.d(e,"c",function(){return u});var i=n("b775");function a(t){return Object(i["a"])({url:"/policy",method:"get",params:t})}function o(t){return Object(i["a"])({url:"/policy",method:"put",data:t})}function r(t){return Object(i["a"])({url:"/policy/byrole",method:"get",params:t})}function u(t){return Object(i["a"])({url:"/policy/byrole",method:"put",data:t})}},"1c64":function(t,e,n){},"1cc6":function(t,e,n){"use strict";var i=n("1c64"),a=n.n(i);a.a},"333d":function(t,e,n){"use strict";var i=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"pagination-container",class:{hidden:t.hidden}},[n("el-pagination",t._b({attrs:{background:t.background,"current-page":t.currentPage,"page-size":t.pageSize,layout:t.layout,"page-sizes":t.pageSizes,total:t.total},on:{"update:currentPage":function(e){t.currentPage=e},"update:current-page":function(e){t.currentPage=e},"update:pageSize":function(e){t.pageSize=e},"update:page-size":function(e){t.pageSize=e},"size-change":t.handleSizeChange,"current-change":t.handleCurrentChange}},"el-pagination",t.$attrs,!1))],1)},a=[];n("c5f6");Math.easeInOutQuad=function(t,e,n,i){return t/=i/2,t<1?n/2*t*t+e:(t--,-n/2*(t*(t-2)-1)+e)};var o=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(t){window.setTimeout(t,1e3/60)}}();function r(t){document.documentElement.scrollTop=t,document.body.parentNode.scrollTop=t,document.body.scrollTop=t}function u(){return document.documentElement.scrollTop||document.body.parentNode.scrollTop||document.body.scrollTop}function c(t,e,n){var i=u(),a=t-i,c=20,l=0;e="undefined"===typeof e?500:e;var s=function t(){l+=c;var u=Math.easeInOutQuad(l,i,a,e);r(u),l0,expression:"total>0"}],attrs:{total:t.total,page:t.listQuery.page,limit:t.listQuery.limit},on:{"update:page":function(e){return t.$set(t.listQuery,"page",e)},"update:limit":function(e){return t.$set(t.listQuery,"limit",e)},pagination:t.getList}})],1)},a=[],o=(n("7f7f"),n("1b26")),r=n("333d"),u={name:"InlineEditTable",components:{Pagination:r["a"]},filters:{statusFilter:function(t){var e={published:"success",draft:"info",deleted:"danger"};return e[t]}},data:function(){return{list:null,listLoading:!0,total:0,listQuery:{page:1,limit:10,importance:void 0,title:void 0,type:void 0}}},created:function(){this.getList()},methods:{getList:function(){var t=this;this.listLoading=!0,Object(o["b"])(this.listQuery).then(function(e){t.total=e.data.total,t.list=e.data.items.map(function(e){return t.$set(e,"edit",!1),e.originalName=e.name,e}),setTimeout(function(){t.listLoading=!1},500)})},cancelEdit:function(t){t.name=t.originalName,t.edit=!1},confirmEdit:function(t){var e=this;t.edit=!1,t.originalName=t.name,Object(o["d"])(t).then(function(){console.log("123"),e.$message({message:"The title has been edited",type:"success"})}).catch(function(){e.$message({message:"编辑失败",type:"error"})})}}},c=u,l=(n("0f7b"),n("2877")),s=Object(l["a"])(c,i,a,!1,null,"b1948282",null);e["default"]=s.exports},e4d3:function(t,e,n){}}]);
--------------------------------------------------------------------------------
/docfile/sql/all.sql:
--------------------------------------------------------------------------------
1 | CREATE DATABASE IF NOT EXISTS `gadmin` /*!40100 DEFAULT CHARACTER SET utf8 COLLATE utf8_bin */ /*!80016 DEFAULT ENCRYPTION='N' */;
2 | USE `gadmin`;
3 | -- MySQL dump 10.13 Distrib 8.0.17, for Win64 (x86_64)
4 | --
5 | -- Host: localhost Database: gadmin
6 | -- ------------------------------------------------------
7 | -- Server version 8.0.17
8 |
9 | /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
10 | /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
11 | /*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
12 | /*!50503 SET NAMES utf8 */;
13 | /*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
14 | /*!40103 SET TIME_ZONE='+00:00' */;
15 | /*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
16 | /*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
17 | /*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
18 | /*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
19 |
20 | --
21 | -- Table structure for table `casbin_rule`
22 | --
23 |
24 | DROP TABLE IF EXISTS `casbin_rule`;
25 | /*!40101 SET @saved_cs_client = @@character_set_client */;
26 | /*!50503 SET character_set_client = utf8mb4 */;
27 | CREATE TABLE `casbin_rule` (
28 | `id` int(11) NOT NULL AUTO_INCREMENT,
29 | `p_type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
30 | `v0` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
31 | `v1` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
32 | `v2` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
33 | `v3` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
34 | `v4` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
35 | `v5` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '',
36 | PRIMARY KEY (`id`) USING BTREE
37 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
38 | /*!40101 SET character_set_client = @saved_cs_client */;
39 |
40 | --
41 | -- Table structure for table `menu`
42 | --
43 |
44 | DROP TABLE IF EXISTS `menu`;
45 | /*!40101 SET @saved_cs_client = @@character_set_client */;
46 | /*!50503 SET character_set_client = utf8mb4 */;
47 | CREATE TABLE `menu` (
48 | `id` int(11) NOT NULL AUTO_INCREMENT,
49 | `menu_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单路径',
50 | `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '页面模块',
51 | `redirect` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '重定向地址',
52 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '唯一关键名',
53 | `hidden` tinyint(1) DEFAULT '0' COMMENT '是否隐藏',
54 | `alwaysshow` tinyint(1) DEFAULT '0' COMMENT '是否常显示',
55 | `sort` tinyint(2) DEFAULT '0' COMMENT '排序',
56 | `parent_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '父菜级关键名',
57 | `auto_create` tinyint(1) DEFAULT '0' COMMENT '是否自动生成',
58 | PRIMARY KEY (`id`) USING BTREE,
59 | UNIQUE KEY `key_name` (`name`) USING BTREE
60 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
61 | /*!40101 SET character_set_client = @saved_cs_client */;
62 |
63 | --
64 | -- Table structure for table `menu_meta`
65 | --
66 |
67 | DROP TABLE IF EXISTS `menu_meta`;
68 | /*!40101 SET @saved_cs_client = @@character_set_client */;
69 | /*!50503 SET character_set_client = utf8mb4 */;
70 | CREATE TABLE `menu_meta` (
71 | `id` int(11) NOT NULL AUTO_INCREMENT,
72 | `menu_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单关键名',
73 | `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '名称',
74 | `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '图标',
75 | `nocache` tinyint(1) DEFAULT '0' COMMENT '是否缓存',
76 | PRIMARY KEY (`id`) USING BTREE,
77 | UNIQUE KEY `key_name` (`menu_name`) USING BTREE
78 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
79 | /*!40101 SET character_set_client = @saved_cs_client */;
80 |
81 | --
82 | -- Table structure for table `policy_name`
83 | --
84 |
85 | DROP TABLE IF EXISTS `policy_name`;
86 | /*!40101 SET @saved_cs_client = @@character_set_client */;
87 | /*!50503 SET character_set_client = utf8mb4 */;
88 | CREATE TABLE `policy_name` (
89 | `id` int(11) NOT NULL AUTO_INCREMENT,
90 | `full_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '权限完整路径',
91 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '权限名称',
92 | `descrption` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '描述',
93 | PRIMARY KEY (`id`) USING BTREE,
94 | UNIQUE KEY `full_path_index` (`full_path`) USING BTREE
95 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
96 | /*!40101 SET character_set_client = @saved_cs_client */;
97 |
98 | --
99 | -- Table structure for table `role_menu`
100 | --
101 |
102 | DROP TABLE IF EXISTS `role_menu`;
103 | /*!40101 SET @saved_cs_client = @@character_set_client */;
104 | /*!50503 SET character_set_client = utf8mb4 */;
105 | CREATE TABLE `role_menu` (
106 | `id` int(11) NOT NULL AUTO_INCREMENT,
107 | `role_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色key',
108 | `menu_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '菜单关键名',
109 | PRIMARY KEY (`id`) USING BTREE
110 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
111 | /*!40101 SET character_set_client = @saved_cs_client */;
112 |
113 | --
114 | -- Table structure for table `role_name`
115 | --
116 |
117 | DROP TABLE IF EXISTS `role_name`;
118 | /*!40101 SET @saved_cs_client = @@character_set_client */;
119 | /*!50503 SET character_set_client = utf8mb4 */;
120 | CREATE TABLE `role_name` (
121 | `id` int(11) NOT NULL AUTO_INCREMENT,
122 | `role_key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '0' COMMENT '角色key',
123 | `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '角色名',
124 | `descrption` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT '' COMMENT '描述',
125 | PRIMARY KEY (`id`) USING BTREE,
126 | UNIQUE KEY `role_key_index` (`role_key`) USING BTREE
127 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
128 | /*!40101 SET character_set_client = @saved_cs_client */;
129 |
130 | --
131 | -- Table structure for table `user`
132 | --
133 |
134 | DROP TABLE IF EXISTS `user`;
135 | /*!40101 SET @saved_cs_client = @@character_set_client */;
136 | /*!50503 SET character_set_client = utf8mb4 */;
137 | CREATE TABLE `user` (
138 | `id` int(11) NOT NULL AUTO_INCREMENT,
139 | `status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态',
140 | `user_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '用户名',
141 | `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '昵称',
142 | `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL DEFAULT '' COMMENT '密码',
143 | `email` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '邮箱',
144 | `phone` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '手机号',
145 | `sex` tinyint(6) NOT NULL DEFAULT '0' COMMENT '性别',
146 | `age` tinyint(6) NOT NULL DEFAULT '0' COMMENT '年龄',
147 | `add_time` datetime NOT NULL COMMENT '添加时间',
148 | `update_time` datetime NOT NULL COMMENT '修改时间',
149 | `add_user_id` int(11) NOT NULL DEFAULT '0' COMMENT '操作用户',
150 | `Introduction` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '介绍',
151 | `avatar` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL COMMENT '头像',
152 | PRIMARY KEY (`id`) USING BTREE,
153 | UNIQUE KEY `username` (`user_name`) USING BTREE
154 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8 ROW_FORMAT=COMPACT;
155 | /*!40101 SET character_set_client = @saved_cs_client */;
156 | /*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;
157 |
158 | /*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
159 | /*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
160 | /*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
161 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
162 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
163 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
164 | /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
165 |
166 | -- Dump completed on 2020-01-16 16:19:47
167 |
--------------------------------------------------------------------------------
/static/js/chunk-015d6b7a.3faa4a94.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-015d6b7a"],{"22e9":function(t,e,s){},2452:function(t,e,s){"use strict";var a=s("8715"),i=s.n(a);i.a},"3cbc":function(t,e,s){"use strict";var a=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"pan-item",style:{zIndex:t.zIndex,height:t.height,width:t.width}},[s("div",{staticClass:"pan-info"},[s("div",{staticClass:"pan-info-roles-container"},[t._t("default")],2)]),t._v(" "),s("img",{staticClass:"pan-thumb",attrs:{src:t.image}})])},i=[],n=(s("c5f6"),{name:"PanThumb",props:{image:{type:String,required:!0},zIndex:{type:Number,default:1},width:{type:String,default:"150px"},height:{type:String,default:"150px"}}}),r=n,l=(s("2452"),s("2877")),c=Object(l["a"])(r,a,i,!1,null,"0d3d578f",null);e["a"]=c.exports},6975:function(t,e,s){},8715:function(t,e,s){},"8fa5":function(t,e,s){"use strict";var a=s("22e9"),i=s.n(a);i.a},ec02:function(t,e,s){"use strict";var a=s("6975"),i=s.n(a);i.a},ecac:function(t,e,s){"use strict";s.r(e);var a=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"app-container"},[t.user?s("div",[s("el-row",{attrs:{gutter:20}},[s("el-col",{attrs:{span:6,xs:24}},[s("user-card",{attrs:{user:t.user}})],1),t._v(" "),s("el-col",{attrs:{span:18,xs:24}},[s("el-card",[s("el-tabs",{model:{value:t.activeTab,callback:function(e){t.activeTab=e},expression:"activeTab"}},[s("el-tab-pane",{attrs:{label:"Activity",name:"activity"}},[s("activity")],1),t._v(" "),s("el-tab-pane",{attrs:{label:"Timeline",name:"timeline"}},[s("timeline")],1),t._v(" "),s("el-tab-pane",{attrs:{label:"Account",name:"account"}},[s("account",{attrs:{user:t.user}})],1)],1)],1)],1)],1)],1):t._e()])},i=[],n=(s("7f7f"),s("cebc")),r=s("2f62"),l=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("el-card",{staticStyle:{"margin-bottom":"20px"}},[s("div",{staticClass:"clearfix",attrs:{slot:"header"},slot:"header"},[s("span",[t._v("About me")])]),t._v(" "),s("div",{staticClass:"user-profile"},[s("div",{staticClass:"box-center"},[s("pan-thumb",{attrs:{image:t.user.avatar,height:"100px",width:"100px",hoverable:!1}},[s("div",[t._v("Hello")]),t._v("\n "+t._s(t.user.role)+"\n ")])],1),t._v(" "),s("div",{staticClass:"box-center"},[s("div",{staticClass:"user-name text-center"},[t._v(t._s(t.user.name))]),t._v(" "),s("div",{staticClass:"user-role text-center text-muted"},[t._v(t._s(t._f("uppercaseFirst")(t.user.role)))])])]),t._v(" "),s("div",{staticClass:"user-bio"},[s("div",{staticClass:"user-education user-bio-section"},[s("div",{staticClass:"user-bio-section-header"},[s("svg-icon",{attrs:{"icon-class":"education"}}),s("span",[t._v("Education")])],1),t._v(" "),s("div",{staticClass:"user-bio-section-body"},[s("div",{staticClass:"text-muted"},[t._v("\n JS in Computer Science from the University of Technology\n ")])])]),t._v(" "),s("div",{staticClass:"user-skills user-bio-section"},[s("div",{staticClass:"user-bio-section-header"},[s("svg-icon",{attrs:{"icon-class":"skill"}}),s("span",[t._v("Skills")])],1),t._v(" "),s("div",{staticClass:"user-bio-section-body"},[s("div",{staticClass:"progress-item"},[s("span",[t._v("Vue")]),t._v(" "),s("el-progress",{attrs:{percentage:70}})],1),t._v(" "),s("div",{staticClass:"progress-item"},[s("span",[t._v("JavaScript")]),t._v(" "),s("el-progress",{attrs:{percentage:18}})],1),t._v(" "),s("div",{staticClass:"progress-item"},[s("span",[t._v("Css")]),t._v(" "),s("el-progress",{attrs:{percentage:12}})],1),t._v(" "),s("div",{staticClass:"progress-item"},[s("span",[t._v("ESLint")]),t._v(" "),s("el-progress",{attrs:{percentage:100,status:"success"}})],1)])])])])},c=[],o=s("3cbc"),u={components:{PanThumb:o["a"]},props:{user:{type:Object,default:function(){return{name:"",email:"",avatar:"",roles:""}}}}},m=u,p=(s("ec02"),s("2877")),v=Object(p["a"])(m,l,c,!1,null,"562f534e",null),d=v.exports,f=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"user-activity"},[s("div",{staticClass:"post"},[s("div",{staticClass:"user-block"},[s("img",{staticClass:"img-circle",attrs:{src:"https://wpimg.wallstcn.com/57ed425a-c71e-4201-9428-68760c0537c4.jpg"+t.avatarPrefix}}),t._v(" "),s("span",{staticClass:"username text-muted"},[t._v("Iron Man")]),t._v(" "),s("span",{staticClass:"description"},[t._v("Shared publicly - 7:30 PM today")])]),t._v(" "),s("p",[t._v("\n Lorem ipsum represents a long-held tradition for designers,\n typographers and the like. Some people hate it and argue for\n its demise, but others ignore the hate as they create awesome\n tools to help create filler text for everyone from bacon lovers\n to Charlie Sheen fans.\n ")]),t._v(" "),s("ul",{staticClass:"list-inline"},[t._m(0),t._v(" "),s("li",[s("span",{staticClass:"link-black text-sm"},[s("svg-icon",{attrs:{"icon-class":"like"}}),t._v("\n Like\n ")],1)])])]),t._v(" "),s("div",{staticClass:"post"},[s("div",{staticClass:"user-block"},[s("img",{staticClass:"img-circle",attrs:{src:"https://wpimg.wallstcn.com/9e2a5d0a-bd5b-457f-ac8e-86554616c87b.jpg"+t.avatarPrefix}}),t._v(" "),s("span",{staticClass:"username text-muted"},[t._v("Captain American")]),t._v(" "),s("span",{staticClass:"description"},[t._v("Sent you a message - yesterday")])]),t._v(" "),s("p",[t._v("\n Lorem ipsum represents a long-held tradition for designers,\n typographers and the like. Some people hate it and argue for\n its demise, but others ignore the hate as they create awesome\n tools to help create filler text for everyone from bacon lovers\n to Charlie Sheen fans.\n ")]),t._v(" "),s("ul",{staticClass:"list-inline"},[t._m(1),t._v(" "),s("li",[s("span",{staticClass:"link-black text-sm"},[s("svg-icon",{attrs:{"icon-class":"like"}}),t._v("\n Like\n ")],1)])])]),t._v(" "),s("div",{staticClass:"post"},[s("div",{staticClass:"user-block"},[s("img",{staticClass:"img-circle",attrs:{src:"https://wpimg.wallstcn.com/fb57f689-e1ab-443c-af12-8d4066e202e2.jpg"+t.avatarPrefix}}),t._v(" "),s("span",{staticClass:"username"},[t._v("Spider Man")]),t._v(" "),s("span",{staticClass:"description"},[t._v("Posted 4 photos - 2 days ago")])]),t._v(" "),s("div",{staticClass:"user-images"},[s("el-carousel",{attrs:{interval:6e3,type:"card",height:"220px"}},t._l(t.carouselImages,function(e){return s("el-carousel-item",{key:e},[s("img",{staticClass:"image",attrs:{src:e+t.carouselPrefix}})])}),1)],1),t._v(" "),s("ul",{staticClass:"list-inline"},[t._m(2),t._v(" "),s("li",[s("span",{staticClass:"link-black text-sm"},[s("svg-icon",{attrs:{"icon-class":"like"}}),t._v(" Like")],1)])])])])},_=[function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("li",[s("span",{staticClass:"link-black text-sm"},[s("i",{staticClass:"el-icon-share"}),t._v("\n Share\n ")])])},function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("li",[s("span",{staticClass:"link-black text-sm"},[s("i",{staticClass:"el-icon-share"}),t._v("\n Share\n ")])])},function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("li",[s("span",{staticClass:"link-black text-sm"},[s("i",{staticClass:"el-icon-share"}),t._v(" Share")])])}],h="?imageView2/1/w/80/h/80",b="?imageView2/2/h/440",g={data:function(){return{carouselImages:["https://wpimg.wallstcn.com/9679ffb0-9e0b-4451-9916-e21992218054.jpg","https://wpimg.wallstcn.com/bcce3734-0837-4b9f-9261-351ef384f75a.jpg","https://wpimg.wallstcn.com/d1d7b033-d75e-4cd6-ae39-fcd5f1c0a7c5.jpg","https://wpimg.wallstcn.com/50530061-851b-4ca5-9dc5-2fead928a939.jpg"],avatarPrefix:h,carouselPrefix:b}}},C=g,x=(s("8fa5"),Object(p["a"])(C,f,_,!1,null,"6fd9b025",null)),y=x.exports,k=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("div",{staticClass:"block"},[s("el-timeline",t._l(t.timeline,function(e,a){return s("el-timeline-item",{key:a,attrs:{timestamp:e.timestamp,placement:"top"}},[s("el-card",[s("h4",[t._v(t._s(e.title))]),t._v(" "),s("p",[t._v(t._s(e.content))])])],1)}),1)],1)},w=[],S={data:function(){return{timeline:[{timestamp:"2019/4/20",title:"Update Github template",content:"PanJiaChen committed 2019/4/20 20:46"},{timestamp:"2019/4/21",title:"Update Github template",content:"PanJiaChen committed 2019/4/21 20:46"},{timestamp:"2019/4/22",title:"Build Template",content:"PanJiaChen committed 2019/4/22 20:46"},{timestamp:"2019/4/23",title:"Release New Version",content:"PanJiaChen committed 2019/4/23 20:46"}]}}},j=S,P=Object(p["a"])(j,k,w,!1,null,null,null),E=P.exports,$=function(){var t=this,e=t.$createElement,s=t._self._c||e;return s("el-form",[s("el-form-item",{attrs:{label:"Name"}},[s("el-input",{model:{value:t.user.name,callback:function(e){t.$set(t.user,"name","string"===typeof e?e.trim():e)},expression:"user.name"}})],1),t._v(" "),s("el-form-item",{attrs:{label:"Email"}},[s("el-input",{model:{value:t.user.email,callback:function(e){t.$set(t.user,"email","string"===typeof e?e.trim():e)},expression:"user.email"}})],1),t._v(" "),s("el-form-item",[s("el-button",{attrs:{type:"primary"},on:{click:t.submit}},[t._v("Update")])],1)],1)},O=[],T={props:{user:{type:Object,default:function(){return{name:"",email:""}}}},methods:{submit:function(){this.$message({message:"User information has been updated successfully",type:"success",duration:5e3})}}},J=T,U=Object(p["a"])(J,$,O,!1,null,null,null),A=U.exports,I={name:"Profile",components:{UserCard:d,Activity:y,Timeline:E,Account:A},data:function(){return{user:{},activeTab:"activity"}},computed:Object(n["a"])({},Object(r["b"])(["name","avatar","roles"])),created:function(){this.getUser()},methods:{getUser:function(){this.user={name:this.name,role:this.roles.join(" | "),email:"admin@test.com",avatar:this.avatar}}}},L=I,V=Object(p["a"])(L,a,i,!1,null,null,null);e["default"]=V.exports}}]);
--------------------------------------------------------------------------------
/static/js/chunk-3296490b.44372469.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-3296490b"],{"1c64":function(e,t,n){},"1cc6":function(e,t,n){"use strict";var a=n("1c64"),i=n.n(a);i.a},"333d":function(e,t,n){"use strict";var a=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"pagination-container",class:{hidden:e.hidden}},[n("el-pagination",e._b({attrs:{background:e.background,"current-page":e.currentPage,"page-size":e.pageSize,layout:e.layout,"page-sizes":e.pageSizes,total:e.total},on:{"update:currentPage":function(t){e.currentPage=t},"update:current-page":function(t){e.currentPage=t},"update:pageSize":function(t){e.pageSize=t},"update:page-size":function(t){e.pageSize=t},"size-change":e.handleSizeChange,"current-change":e.handleCurrentChange}},"el-pagination",e.$attrs,!1))],1)},i=[];n("c5f6");Math.easeInOutQuad=function(e,t,n,a){return e/=a/2,e<1?n/2*e*e+t:(e--,-n/2*(e*(e-2)-1)+t)};var l=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}();function o(e){document.documentElement.scrollTop=e,document.body.parentNode.scrollTop=e,document.body.scrollTop=e}function r(){return document.documentElement.scrollTop||document.body.parentNode.scrollTop||document.body.scrollTop}function s(e,t,n){var a=r(),i=e-a,s=20,c=0;t="undefined"===typeof t?500:t;var u=function e(){c+=s;var r=Math.easeInOutQuad(c,a,i,t);o(r),c0,expression:"total>0"}],attrs:{total:e.total,page:e.listQuery.page,limit:e.listQuery.limit},on:{"update:page":function(t){return e.$set(e.listQuery,"page",t)},"update:limit":function(t){return e.$set(e.listQuery,"limit",t)},pagination:e.getList}}),e._v(" "),n("el-dialog",{attrs:{title:e.textMap[e.dialogStatus],visible:e.dialogFormVisible},on:{"update:visible":function(t){e.dialogFormVisible=t}}},[n("el-form",{ref:"dataForm",staticStyle:{width:"400px","margin-left":"50px"},attrs:{rules:e.rules,model:e.temp,"label-position":"left","label-width":"120px"}},[n("el-form-item",{attrs:{label:e.$t("table.userName"),prop:"user_name"}},["create"===e.dialogStatus?n("el-input",{model:{value:e.temp.user_name,callback:function(t){e.$set(e.temp,"user_name",t)},expression:"temp.user_name"}}):n("span",[e._v(e._s(e.temp.user_name))])],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.nickName"),prop:"nick_name"}},[n("el-input",{model:{value:e.temp.nick_name,callback:function(t){e.$set(e.temp,"nick_name",t)},expression:"temp.nick_name"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.password"),prop:"password"}},[n("el-input",{attrs:{type:"password"},model:{value:e.temp.password,callback:function(t){e.$set(e.temp,"password",t)},expression:"temp.password"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.passwordconfirm"),prop:"passwordconfirm"}},[n("el-input",{attrs:{type:"password"},model:{value:e.temp.passwordconfirm,callback:function(t){e.$set(e.temp,"passwordconfirm",t)},expression:"temp.passwordconfirm"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.email"),prop:"email"}},[n("el-input",{model:{value:e.temp.email,callback:function(t){e.$set(e.temp,"email",t)},expression:"temp.email"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.phone"),prop:"phone"}},[n("el-input",{model:{value:e.temp.phone,callback:function(t){e.$set(e.temp,"phone",t)},expression:"temp.phone"}})],1)],1),e._v(" "),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.dialogFormVisible=!1}}},[e._v("\n "+e._s(e.$t("table.cancel"))+"\n ")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:function(t){"create"===e.dialogStatus?e.createData():e.updateData()}}},[e._v("\n "+e._s(e.$t("table.confirm"))+"\n ")])],1)],1),e._v(" "),n("el-dialog",{attrs:{visible:e.dialogRoleVisible,title:"权限修改"},on:{"update:visible":function(t){e.dialogRoleVisible=t}}},[n("el-checkbox",{attrs:{indeterminate:e.isIndeterminate},on:{change:e.handleCheckAllChange},model:{value:e.checkAll,callback:function(t){e.checkAll=t},expression:"checkAll"}},[e._v("全选")]),e._v(" "),n("div",{staticStyle:{margin:"15px 0"}}),e._v(" "),n("el-checkbox-group",{attrs:{min:1},on:{change:e.handleCheckedRolesChange},model:{value:e.checkedRoles,callback:function(t){e.checkedRoles=t},expression:"checkedRoles"}},e._l(e.allRoles,function(t){return n("el-checkbox",{key:t.role,attrs:{label:t.role}},[e._v(e._s(t.name))])}),1),e._v(" "),n("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.dialogRoleVisible=!1}}},[e._v("\n "+e._s(e.$t("table.cancel"))+"\n ")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:function(t){return e.handleUpdateRoleRole()}}},[e._v("\n "+e._s(e.$t("table.confirm"))+"\n ")])],1)],1)],1)},i=[],l=(n("7f7f"),n("ac6a"),n("5176")),o=n.n(l),r=n("c24f"),s=n("cc5e"),c=n("61f7"),u=n("6724"),d=n("333d"),p={name:"ComplexTable",components:{Pagination:d["a"]},directives:{waves:u["a"]},filters:{statusFilter:function(e){var t={published:"success",draft:"info",deleted:"danger"};return t[e]}},data:function(){var e=this,t=function(t,n,a){""===n&&"create"===e.dialogStatus?a(new Error("请输入密码")):(""!==e.temp.passwordconfirm&&e.$refs.dataForm.validateField("passwordconfirm"),a())},n=function(t,n,a){""===n&&"create"===e.dialogStatus?a(new Error("请再次输入密码")):n!==e.temp.password?a(new Error("两次输入密码不一致!")):a()},a=function(e,t,n){Object(c["d"])(t)?n():n(new Error("Please enter the correct user name"))};return{list:null,total:0,listLoading:!0,listQuery:{page:1,limit:10,name:void 0,sort:"+id"},showReviewer:!1,temp:{user_name:"",nick_name:"",email:"",phone:"",password:"",passwordconfirm:""},dialogFormVisible:!1,dialogStatus:"",textMap:{update:"Edit",create:"Create"},rules:{user_name:[{required:!0,message:"username is required",trigger:"blur"}],nick_name:[{required:!0,message:"nickname is required",trigger:"blur"}],email:[{required:!0,trigger:"blur",validator:a}],phone:[{required:!0,message:"phone is required",trigger:"blur"}],password:[{validator:t,trigger:"blur"}],passwordconfirm:[{validator:n,trigger:"blur"}]},dialogRoleVisible:!1,checkAll:!1,checkedRoles:[],checkedAllRoles:[],allRoles:[],isIndeterminate:!1,currentUserName:""}},created:function(){this.getList()},methods:{getList:function(){var e=this;this.listLoading=!0,Object(r["d"])(this.listQuery).then(function(t){e.list=t.data.items,e.total=t.data.total,setTimeout(function(){e.listLoading=!1},500)})},handleFilter:function(){this.listQuery.page=1,this.getList()},handleModifyStatus:function(e,t){"deleted"===t&&this.handleDelete(e)},resetTemp:function(){this.temp={user_name:"",nick_name:"",email:"",phone:"",password:"",passwordconfirm:""}},handleCreate:function(){var e=this;this.resetTemp(),this.dialogStatus="create",this.dialogFormVisible=!0,this.$nextTick(function(){e.$refs["dataForm"].clearValidate()})},createData:function(){var e=this;this.$refs["dataForm"].validate(function(t){t&&(e.temp.author="vue-element-admin",Object(r["a"])(e.temp).then(function(){e.dialogFormVisible=!1,e.getList(),e.$notify({title:"成功",message:"创建成功",type:"success",duration:2e3})}))})},handleUpdate:function(e){var t=this;this.temp=o()({},e),this.dialogStatus="update",this.dialogFormVisible=!0,this.$nextTick(function(){t.$refs["dataForm"].clearValidate()})},updateData:function(){var e=this;this.$refs["dataForm"].validate(function(t){if(t){var n=o()({},e.temp);Object(r["j"])(n).then(function(){e.dialogFormVisible=!1,e.getList(),e.$notify({title:"成功",message:"更新成功",type:"success",duration:2e3})})}})},handleDelete:function(e){var t=this;this.$confirm("是否删除?","确认信息",{distinguishCancelAndClose:!0,confirmButtonText:"删除",cancelButtonText:"取消"}).then(function(){Object(r["b"])({id:e.id}).then(function(){t.getList(),t.$notify({title:"成功",message:"删除成功",type:"success",duration:2e3})})})},handleUpdateRole:function(e){var t=this;this.currentUserName=e.user_name,Object(s["c"])({limit:-1,username:e.user_name}).then(function(e){t.allRoles=[],t.checkedRoles=[],t.checkedAllRoles=[],e.data.items.forEach(function(e){t.checkedAllRoles.push(e.role),""!==e.name?t.allRoles.push(e):(e.name=e.role,t.allRoles.push(e))}),e.data.role_items.forEach(function(e){t.checkedRoles.push(e.role)}),t.checkedRoles.length>0?(t.checkAll=t.checkedRoles.length===t.allRoles.length,t.isIndeterminate=!t.checkAll):(t.isIndeterminate=!1,t.checkAll=!1),t.dialogRoleVisible=!0})},handleCheckAllChange:function(e){this.checkedRoles=e?this.checkedAllRoles:[],this.isIndeterminate=!1},handleCheckedRolesChange:function(e){var t=e.length;this.checkAll=t===this.allRoles.length,this.isIndeterminate=t>0&&t0,expression:"total>0"}],attrs:{total:e.total,page:e.listQuery.page,limit:e.listQuery.limit},on:{"update:page":function(t){return e.$set(e.listQuery,"page",t)},"update:limit":function(t){return e.$set(e.listQuery,"limit",t)},pagination:e.getList}}),e._v(" "),n("el-dialog",{attrs:{title:e.textMap[e.dialogStatus],visible:e.dialogFormVisible},on:{"update:visible":function(t){e.dialogFormVisible=t}}},[n("el-form",{ref:"dataForm",staticStyle:{width:"400px","margin-left":"50px"},attrs:{rules:e.rules,model:e.temp,"label-position":"left","label-width":"90px"}},[n("el-form-item",{attrs:{label:e.$t("table.role"),prop:"role"}},["create"===e.dialogStatus?n("el-input",{model:{value:e.temp.role,callback:function(t){e.$set(e.temp,"role",t)},expression:"temp.role"}}):n("span",[e._v(e._s(e.temp.role))])],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.roleName"),prop:"name"}},[n("el-input",{model:{value:e.temp.name,callback:function(t){e.$set(e.temp,"name",t)},expression:"temp.name"}})],1)],1),e._v(" "),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.dialogFormVisible=!1}}},[e._v("\n "+e._s(e.$t("table.cancel"))+"\n ")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:function(t){"create"===e.dialogStatus?e.createData():e.updateData()}}},[e._v("\n "+e._s(e.$t("table.confirm"))+"\n ")])],1)],1),e._v(" "),n("el-dialog",{attrs:{visible:e.dialogPolicyVisible,title:"权限修改"},on:{"update:visible":function(t){e.dialogPolicyVisible=t}}},[n("el-checkbox",{attrs:{indeterminate:e.isIndeterminate},on:{change:e.handleCheckAllChange},model:{value:e.checkAll,callback:function(t){e.checkAll=t},expression:"checkAll"}},[e._v("全选")]),e._v(" "),n("div",{staticStyle:{margin:"15px 0"}}),e._v(" "),n("el-checkbox-group",{on:{change:e.handleCheckedPolicysChange},model:{value:e.checkedPolicys,callback:function(t){e.checkedPolicys=t},expression:"checkedPolicys"}},e._l(e.allPolicys,function(t){return n("el-checkbox",{key:t.policy,attrs:{label:t.policy}},[e._v(e._s(t.name))])}),1),e._v(" "),n("span",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.dialogPolicyVisible=!1}}},[e._v("\n "+e._s(e.$t("table.cancel"))+"\n ")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:function(t){return e.handleUpdateRolePolicy()}}},[e._v("\n "+e._s(e.$t("table.confirm"))+"\n ")])],1)],1),e._v(" "),n("el-dialog",{attrs:{visible:e.dialogViewMenuVisible,title:"预览菜单"},on:{"update:visible":function(t){e.dialogViewMenuVisible=t}}},[n("el-form",{attrs:{"label-width":"80px","label-position":"left"}},[n("el-tree",{ref:"tree",staticClass:"permission-tree",attrs:{data:e.routesData,"check-strictly":e.checkStrictly,props:e.defaultProps,"show-checkbox":"","default-expand-all":!0,"node-key":"name"}})],1),e._v(" "),n("div",{staticStyle:{"text-align":"right"}},[n("el-button",{attrs:{type:"danger"},on:{click:function(t){e.dialogViewMenuVisible=!1}}},[e._v("\n "+e._s(e.$t("permission.cancel"))+"\n ")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:e.confirmRoleMenus}},[e._v("\n "+e._s(e.$t("permission.confirm"))+"\n ")])],1)],1)],1)},a=[],l=n("cebc"),o=(n("96cf"),n("3b8d")),r=n("b6d0"),c=n.n(r),s=n("774e"),u=n.n(s),d=n("75fc"),h=(n("55dd"),n("5d73")),p=n.n(h),f=(n("7f7f"),n("ac6a"),n("5176")),m=n.n(f),g=n("1f27"),v=n("cc5e"),y=n("1b26"),b=n("6724"),k=n("333d"),w=n("df7c"),_=n.n(w),P=n("9923"),x={name:"ComplexTable",components:{Pagination:k["a"]},directives:{waves:b["a"]},filters:{statusFilter:function(e){var t={published:"success",draft:"info",deleted:"danger"};return t[e]}},data:function(){return{list:null,total:0,listLoading:!0,listQuery:{page:1,limit:10,name:void 0,sort:"+id"},showReviewer:!1,temp:{role:"",name:""},dialogFormVisible:!1,dialogStatus:"",textMap:{update:"Edit",create:"Create"},rules:{role:[{required:!0,message:"role is required",trigger:"blur"}],name:[{required:!0,message:"name is required",trigger:"blur"}]},dialogPolicyVisible:!1,checkAll:!1,checkedPolicys:[],checkedAllPolicys:[],allPolicys:[],isIndeterminate:!1,currentRole:"",routes:[],roleRoutes:[],dialogViewMenuVisible:!1,checkStrictly:!1,defaultProps:{children:"children",label:"title"}}},computed:{routesData:function(){return this.routes}},created:function(){this.getList()},methods:{i18n:function(e){var t=this,n=e.map(function(e){return e.title=P["a"].t("route.".concat(e.title)),e.children&&(e.children=t.i18n(e.children)),e});return n},getList:function(){var e=this;this.listLoading=!0,Object(v["c"])(this.listQuery).then(function(t){e.list=t.data.items,e.total=t.data.total,setTimeout(function(){e.listLoading=!1},500)})},handleFilter:function(){this.listQuery.page=1,this.getList()},handleModifyStatus:function(e,t){"deleted"===t&&this.handleDelete(e)},resetTemp:function(){this.temp={role:"",name:""}},handleCreate:function(){var e=this;this.resetTemp(),this.dialogStatus="create",this.dialogFormVisible=!0,this.$nextTick(function(){e.$refs["dataForm"].clearValidate()})},createData:function(){var e=this;this.$refs["dataForm"].validate(function(t){t&&(e.temp.author="vue-element-admin",Object(v["a"])(e.temp).then(function(){e.list.unshift(e.temp),e.dialogFormVisible=!1,e.$notify({title:"成功",message:"创建成功",type:"success",duration:2e3})}))})},handleUpdate:function(e){var t=this;this.temp=m()({},e),this.dialogStatus="update",this.dialogFormVisible=!0,this.$nextTick(function(){t.$refs["dataForm"].clearValidate()})},handleUpdatePolicy:function(e){var t=this;this.currentRole=e.role,Object(y["a"])({role:e.role}).then(function(e){t.allPolicys=[],t.checkedPolicys=[],t.checkedAllPolicys=[],e.data.all_policy_items.forEach(function(e){t.checkedAllPolicys.push(e.policy),""!==e.name?t.allPolicys.push(e):(e.name=e.policy,t.allPolicys.push(e))}),e.data.role_policy_items.forEach(function(e){t.checkedPolicys.push(e.policy)}),t.checkedPolicys.length>0?(t.checkAll=t.checkedPolicys.length===t.allPolicys.length,t.isIndeterminate=!t.checkAll):(t.isIndeterminate=!1,t.checkAll=!1),t.dialogPolicyVisible=!0})},updateData:function(){var e=this;this.$refs["dataForm"].validate(function(t){if(t){var n=m()({},e.temp);Object(v["f"])(n).then(function(){var t=!0,n=!1,i=void 0;try{for(var a,l=p()(e.list);!(t=(a=l.next()).done);t=!0){var o=a.value;if(o.id===e.temp.id){var r=e.list.indexOf(o);e.list.splice(r,1,e.temp);break}}}catch(c){n=!0,i=c}finally{try{t||null==l.return||l.return()}finally{if(n)throw i}}e.dialogFormVisible=!1,e.$notify({title:"成功",message:"更新成功",type:"success",duration:2e3})})}})},handleDelete:function(e){var t=this;this.$confirm("是否删除?","确认信息",{distinguishCancelAndClose:!0,confirmButtonText:"删除",cancelButtonText:"取消"}).then(function(){t.temp=m()({},e),Object(v["b"])(t.temp).then(function(){var n=t.list.indexOf(e);t.list.splice(n,1),t.$notify({title:"成功",message:"删除成功",type:"success",duration:2e3})})})},handleCheckAllChange:function(e){this.checkedPolicys=e?this.checkedAllPolicys:[],this.isIndeterminate=!1},handleCheckedPolicysChange:function(e){var t=e.length;this.checkAll=t===this.allPolicys.length,this.isIndeterminate=t>0&&t1&&void 0!==arguments[1]?arguments[1]:"/",n=[];e.sort(function(e,t){return e.sort-t.sort});var i=!0,a=!1,l=void 0;try{for(var o,r=p()(e);!(i=(o=r.next()).done);i=!0){var c=o.value;if(!c.hidden){var s=this.onlyOneShowingChild(c.children,c);c.children&&s&&!c.alwaysShow&&(c=s);var u={name:c.name,path:_.a.resolve(t,c.path),title:c.meta&&c.meta.title,parent_name:c.parent_name};c.children&&(c.children.sort(function(e,t){return e.sort-t.sort}),u.children=this.generateRoutes(c.children,u.path)),n.push(u)}}}catch(d){a=!0,l=d}finally{try{i||null==r.return||r.return()}finally{if(a)throw l}}return n},generateArr:function(e){var t=this,n=[];return e.forEach(function(e){if(n.push(e),e.children){var i=t.generateArr(e.children);i.length>0&&(n=[].concat(Object(d["a"])(n),Object(d["a"])(i)))}}),n},getRealKeys:function(e){var t=[];return e.forEach(function(e){t.push(e.name),""!==e.parent_name&&t.push(e.parent_name)}),u()(new c.a(t))},confirmRoleMenus:function(){var e=Object(o["a"])(regeneratorRuntime.mark(function e(){var t,n=this;return regeneratorRuntime.wrap(function(e){while(1)switch(e.prev=e.next){case 0:t=this.$refs.tree.getCheckedNodes(),Object(v["d"])({role:this.currentRole,menus:this.getRealKeys(t)}).then(function(){n.currentRole="",n.dialogViewMenuVisible=!1,n.$message({type:"success",message:"success!"})});case 2:case"end":return e.stop()}},e,this)}));function t(){return e.apply(this,arguments)}return t}(),onlyOneShowingChild:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1?arguments[1]:void 0,n=null;if(null==e)return!1;var i=e.filter(function(e){return!e.hidden});return 1===i.length?(n=i[0],n.path=_.a.resolve(t.path,n.path),n):0===i.length&&(n=Object(l["a"])({},t,{path:"",noShowingChildren:!0}),n)}}},$=x,S=n("2877"),C=Object(S["a"])($,i,a,!1,null,null,null);t["default"]=C.exports},cc5e:function(e,t,n){"use strict";n.d(t,"c",function(){return a}),n.d(t,"a",function(){return l}),n.d(t,"f",function(){return o}),n.d(t,"b",function(){return r}),n.d(t,"e",function(){return c}),n.d(t,"d",function(){return s});var i=n("b775");function a(e){return Object(i["a"])({url:"/role",method:"get",params:e})}function l(e){return Object(i["a"])({url:"/role",method:"post",data:e})}function o(e){return Object(i["a"])({url:"/role",method:"put",data:e})}function r(e){return Object(i["a"])({url:"/role",method:"delete",data:e})}function c(e){return Object(i["a"])({url:"/role/byuser",method:"put",data:e})}function s(e){return Object(i["a"])({url:"/role/menu",method:"put",data:e})}}}]);
--------------------------------------------------------------------------------
/static/js/chunk-6a4eb3ee.9b859229.js:
--------------------------------------------------------------------------------
1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["chunk-6a4eb3ee"],{"0795":function(e,t,n){},"1c64":function(e,t,n){},"1cc6":function(e,t,n){"use strict";var a=n("1c64"),i=n.n(a);i.a},"333d":function(e,t,n){"use strict";var a=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticClass:"pagination-container",class:{hidden:e.hidden}},[n("el-pagination",e._b({attrs:{background:e.background,"current-page":e.currentPage,"page-size":e.pageSize,layout:e.layout,"page-sizes":e.pageSizes,total:e.total},on:{"update:currentPage":function(t){e.currentPage=t},"update:current-page":function(t){e.currentPage=t},"update:pageSize":function(t){e.pageSize=t},"update:page-size":function(t){e.pageSize=t},"size-change":e.handleSizeChange,"current-change":e.handleCurrentChange}},"el-pagination",e.$attrs,!1))],1)},i=[];n("c5f6");Math.easeInOutQuad=function(e,t,n,a){return e/=a/2,e<1?n/2*e*e+t:(e--,-n/2*(e*(e-2)-1)+t)};var l=function(){return window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||function(e){window.setTimeout(e,1e3/60)}}();function o(e){document.documentElement.scrollTop=e,document.body.parentNode.scrollTop=e,document.body.scrollTop=e}function r(){return document.documentElement.scrollTop||document.body.parentNode.scrollTop||document.body.scrollTop}function s(e,t,n){var a=r(),i=e-a,s=20,c=0;t="undefined"===typeof t?500:t;var u=function e(){c+=s;var r=Math.easeInOutQuad(c,a,i,t);o(r),c0,expression:"total>0"}],attrs:{total:e.total,page:e.listQuery.page,limit:e.listQuery.limit},on:{"update:page":function(t){return e.$set(e.listQuery,"page",t)},"update:limit":function(t){return e.$set(e.listQuery,"limit",t)},pagination:e.getList}}),e._v(" "),n("el-dialog",{attrs:{title:e.textMap[e.dialogStatus],visible:e.dialogFormVisible},on:{"update:visible":function(t){e.dialogFormVisible=t}}},[n("el-form",{ref:"dataForm",staticStyle:{width:"400px","margin-left":"50px"},attrs:{rules:e.rules,model:e.temp,"label-position":"left","label-width":"120px"}},[n("el-form-item",{attrs:{label:e.$t("table.name"),prop:"name"}},["create"===e.dialogStatus?n("el-input",{model:{value:e.temp.name,callback:function(t){e.$set(e.temp,"name",t)},expression:"temp.name"}}):n("span",[e._v(e._s(e.temp.name))])],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.title"),prop:"title"}},[n("el-input",{model:{value:e.temp.meta.title,callback:function(t){e.$set(e.temp.meta,"title",t)},expression:"temp.meta.title"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.path"),prop:"path"}},[n("el-input",{model:{value:e.temp.path,callback:function(t){e.$set(e.temp,"path",t)},expression:"temp.path"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.redirect"),prop:"redirect"}},[n("el-input",{model:{value:e.temp.redirect,callback:function(t){e.$set(e.temp,"redirect",t)},expression:"temp.redirect"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.hidden"),prop:"hidden"}},[n("el-select",{staticClass:"filter-item",attrs:{placeholder:"Please select"},model:{value:e.temp.hidden,callback:function(t){e.$set(e.temp,"hidden",t)},expression:"temp.hidden"}},e._l(e.tofOptions,function(e){return n("el-option",{key:e.key,attrs:{label:e.label,value:e.value}})}),1)],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.alwaysShow"),prop:"alwaysShow"}},[n("el-select",{staticClass:"filter-item",attrs:{placeholder:"Please select"},model:{value:e.temp.alwaysShow,callback:function(t){e.$set(e.temp,"alwaysShow",t)},expression:"temp.alwaysShow"}},e._l(e.tofOptions,function(e){return n("el-option",{key:e.key,attrs:{label:e.label,value:e.value}})}),1)],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.parentName"),prop:"parentName"}},[n("el-select",{staticClass:"filter-item",attrs:{placeholder:"Please select"},model:{value:e.temp.parent_name,callback:function(t){e.$set(e.temp,"parent_name",t)},expression:"temp.parent_name"}},[n("el-option",{key:"null",attrs:{label:"Null",value:""}}),e._v(" "),e._l(e.menuNameList,function(e){return n("el-option",{key:e,attrs:{label:e,value:e}})})],2)],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.component"),prop:"component"}},[n("el-input",{model:{value:e.temp.component,callback:function(t){e.$set(e.temp,"component",t)},expression:"temp.component"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.sort"),prop:"sort"}},[n("el-input",{model:{value:e.temp.sort,callback:function(t){e.$set(e.temp,"sort",t)},expression:"temp.sort"}})],1),e._v(" "),n("el-form-item",{attrs:{label:e.$t("table.icon"),prop:"icon"}},[n("el-select",{staticClass:"filter-item",attrs:{placeholder:"Please select"},model:{value:e.temp.meta.icon,callback:function(t){e.$set(e.temp.meta,"icon",t)},expression:"temp.meta.icon"}},[n("el-option",{key:"null",attrs:{label:"Null",value:""}}),e._v(" "),e._l(e.svgIcons,function(e){return n("el-option",{key:e,attrs:{label:e,value:e}})})],2)],1)],1),e._v(" "),n("div",{staticClass:"dialog-footer",attrs:{slot:"footer"},slot:"footer"},[n("el-button",{on:{click:function(t){e.dialogFormVisible=!1}}},[e._v("\n "+e._s(e.$t("table.cancel"))+"\n ")]),e._v(" "),n("el-button",{attrs:{type:"primary"},on:{click:function(t){"create"===e.dialogStatus?e.createData():e.updateData()}}},[e._v("\n "+e._s(e.$t("table.confirm"))+"\n ")])],1)],1),e._v(" "),n("el-dialog",{attrs:{visible:e.dialogViewMenuVisible,title:"预览菜单"},on:{"update:visible":function(t){e.dialogViewMenuVisible=t}}},[n("el-form",{attrs:{"label-width":"80px","label-position":"left"}},[n("el-tree",{ref:"tree",staticClass:"permission-tree",attrs:{data:e.routesData,props:e.defaultProps,"node-key":"path","default-expand-all":!0}})],1),e._v(" "),n("div",{staticStyle:{"text-align":"right"}},[n("el-button",{attrs:{type:"danger"},on:{click:function(t){e.dialogViewMenuVisible=!1}}},[e._v("\n "+e._s(e.$t("table.close"))+"\n ")])],1)],1)],1)},i=[],l=n("cebc"),o=n("75fc"),r=n("5d73"),s=n.n(r),c=(n("55dd"),n("7f7f"),n("ac6a"),n("5176")),u=n.n(c),d=(n("96cf"),n("3b8d")),p=n("1f27"),m=n("6724"),f=n("333d"),h=n("df7c"),v=n.n(h),b=n("9923"),g=(n("4917"),n("51ff")),y=function(e){return e.keys()},w=/\.\/(.*)\.svg/,_=y(g).map(function(e){return e.match(w)[1]}),k=_,$={name:"ComplexTable",components:{Pagination:f["a"]},directives:{waves:m["a"]},filters:{statusFilter:function(e){var t={published:"success",draft:"info",deleted:"danger"};return t[e]}},data:function(){return{list:null,total:0,listLoading:!0,listQuery:{page:1,limit:10,name:void 0,sort:"+id"},showReviewer:!1,temp:{name:"",path:"",component:"",redirect:"",parent_name:"",sort:0,hidden:!1,alwaysShow:!1,meta:{title:"",noCache:!1,icon:""}},dialogFormVisible:!1,dialogStatus:"",textMap:{update:"Edit",create:"Create"},rules:{},tofOptions:[{key:1,label:"是",value:!0},{key:0,label:"否",value:!1}],menuNameList:[],routes:[],dialogViewMenuVisible:!1,defaultProps:{children:"children",label:"title"},svgIcons:k}},computed:{routesData:function(){return this.routes}},created:function(){this.getList()},methods:{getRoutes:function(){var e=Object(d["a"])(regeneratorRuntime.mark(function e(){var t,n;return regeneratorRuntime.wrap(function(e){while(1)switch(e.prev=e.next){case 0:return e.next=2,Object(p["d"])();case 2:t=e.sent,this.serviceRoutes=t.data,n=this.generateRoutes(t.data),this.routes=this.i18n(n);case 6:case"end":return e.stop()}},e,this)}));function t(){return e.apply(this,arguments)}return t}(),i18n:function(e){var t=this,n=e.map(function(e){return e.title=b["a"].t("route.".concat(e.title)),e.children&&(e.children=t.i18n(e.children)),e});return n},getList:function(){var e=this;this.listLoading=!0,Object(p["c"])(this.listQuery).then(function(t){e.list=t.data.items,e.total=t.data.total,setTimeout(function(){e.listLoading=!1},500)})},handleFilter:function(){this.listQuery.page=1,this.getList()},handleModifyStatus:function(e,t){"deleted"===t&&this.handleDelete(e)},resetTemp:function(){this.temp={name:"",path:"",component:"",redirect:"",parent_name:"",sort:0,hidden:!1,alwaysShow:!1,meta:{title:"",noCache:!1,icon:""}}},handleCreate:function(){var e=this;this.resetTemp(),this.dialogStatus="create",this.dialogFormVisible=!0,this.$nextTick(function(){e.$refs["dataForm"].clearValidate()})},createData:function(){var e=this;this.$refs["dataForm"].validate(function(t){t&&(e.temp.author="vue-element-admin",Object(p["a"])(e.temp).then(function(){e.dialogFormVisible=!1,e.getList(),e.$notify({title:"成功",message:"创建成功",type:"success",duration:2e3})}))})},handleUpdate:function(e){var t=this;this.temp=u()({},e),this.menuNameList=[],this.list.forEach(function(n){n.name!==e.name&&t.menuNameList.push(n.name)}),this.dialogStatus="update",this.dialogFormVisible=!0,this.$nextTick(function(){t.$refs["dataForm"].clearValidate()})},updateData:function(){var e=this;this.$refs["dataForm"].validate(function(t){if(t){var n=u()({},e.temp);Object(p["e"])(n).then(function(){e.dialogFormVisible=!1,e.getList(),e.$notify({title:"成功",message:"更新成功",type:"success",duration:2e3})})}})},handleDelete:function(e){var t=this;this.$confirm("是否删除?","确认信息",{distinguishCancelAndClose:!0,confirmButtonText:"删除",cancelButtonText:"取消"}).then(function(){Object(p["b"])({name:e.name}).then(function(){t.getList(),t.$notify({title:"成功",message:"删除成功",type:"success",duration:2e3})})})},setIcon:function(e){return e},viewMenu:function(){var e=this;this.getRoutes(),this.dialogViewMenuVisible=!0,this.checkStrictly=!0,this.$nextTick(function(){var t=e.generateRoutes(e.routes);e.$refs.tree.setCheckedNodes(e.generateArr(t)),e.checkStrictly=!1})},generateRoutes:function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"/",n=[];e.sort(function(e,t){return e.sort-t.sort});var a=!0,i=!1,l=void 0;try{for(var o,r=s()(e);!(a=(o=r.next()).done);a=!0){var c=o.value;if(!c.hidden){var u=this.onlyOneShowingChild(c.children,c);c.children&&u&&!c.alwaysShow&&(c=u);var d={path:v.a.resolve(t,c.path),title:c.meta&&c.meta.title};c.children&&(c.children.sort(function(e,t){return e.sort-t.sort}),d.children=this.generateRoutes(c.children,d.path)),n.push(d)}}}catch(p){i=!0,l=p}finally{try{a||null==r.return||r.return()}finally{if(i)throw l}}return n},generateArr:function(e){var t=this,n=[];return e.forEach(function(e){if(n.push(e),e.children){var a=t.generateArr(e.children);a.length>0&&(n=[].concat(Object(o["a"])(n),Object(o["a"])(a)))}}),n},onlyOneShowingChild:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:[],t=arguments.length>1?arguments[1]:void 0,n=null;if(null==e)return!1;var a=e.filter(function(e){return!e.hidden});return 1===a.length?(n=a[0],n.path=v.a.resolve(t.path,n.path),n):0===a.length&&(n=Object(l["a"])({},t,{path:"",noShowingChildren:!0}),n)}}},S=$,x=(n("78d1"),n("2877")),C=Object(x["a"])(S,a,i,!1,null,"0c8289ae",null);t["default"]=C.exports},"8d41":function(e,t,n){}}]);
--------------------------------------------------------------------------------
/docfile/swagger.yaml:
--------------------------------------------------------------------------------
1 | swagger: '2.0'
2 | info:
3 | version: 0.0.2
4 | title: gadmin 接口文档
5 | description: |
6 | 更新时间:2019年5月24日 16:23:58
7 | schemes:
8 | - http
9 | host: localhost:8199
10 | basePath: /v1
11 |
12 | #请求路径
13 | paths:
14 | ##登录相关
15 | /loginkey:
16 | get:
17 | summary: 获取登录密码加密密钥
18 | description: |
19 | 请求一个加密密钥,返回的内容包含密钥id(kid)、加密类型(cryptotype)、加密密钥(key)。
20 | ```js
21 | {
22 | "code": 20000,
23 | "data": {
24 | "kid": "BU06PZLJPUNK90L44T",
25 | "cryptotype": "RSA-PKCS1v1.5",
26 | "key": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsAj30qPj3YT7n4bm2uyr\nglOugXyvv34k/kwHkrS/KlLNsvbbGbmAv8fMakuPxm64LKXjX/16+P5IQgNuqWjg\nqoqllB+9Ex3fftEa+YE9hxIlkfBVrhV3SFxJe1bR2QbdgN/tNmnrmwjxCpgeyrCM\nKE/ifAkImgNfC6KCavY7idklRMv/Xji53H1TUoarN2kHFfde5NGfd/Z+9GoB633U\nWi6zJ6vMhinlCaPVQlBHHwIRqMlzC3CWXR3Tx42o4GgPktkZjWK0+DqUUhF7amXC\n/diypzSBsVmCEn68U52byW9vSHiWlRA0N9/stHCZ5M3NcnnZF9JV6XcYjlgHj3ZD\nEwIDAQAB\n-----END PUBLIC KEY-----\n",
27 | "timestamp": 1557542458
28 | },
29 | "message": "success"
30 | }
31 | tags:
32 | - Login
33 | parameters:
34 | responses:
35 | 200:
36 | $ref: '#/responses/LoginKey'
37 | /login:
38 | post:
39 | summary: 登录
40 | description: |
41 | 登录需要先 get 请求/loginkey 获取 RSA 的加密公钥(单次有效,并密钥有时效),将密码使用 RSA-PKCS1v1.5 方式加密并使用 base64 编码
42 |
43 | 使用 forge.js 进行加密数据
44 |
45 | https://raw.githubusercontent.com/loveiset/RSAForPostman/master/forge.js
46 |
47 | var publicKey = forge.pki.publicKeyFromPem(公钥);
48 |
49 | var encryptedText = forge.util.encode64(publicKey.encrypt(真实密码));
50 |
51 | 最终提交的格式
52 |
53 | ```
54 | Content-Type: application/json
55 | POST
56 | {
57 | "username":"admin",
58 | "password":encryptedText,
59 | "kid":"BTNK5IF7DYC8287814"//公钥的 id
60 | }
61 | ```
62 |
63 | tags:
64 | - Login
65 | parameters:
66 | - name: body
67 | in: body
68 | description: 登录数据
69 | schema:
70 | required:
71 | - kid
72 | - password
73 | - username
74 | properties:
75 | kid:
76 | type: string
77 | password:
78 | type: string
79 | username:
80 | type: string
81 | responses:
82 | 200:
83 | $ref: '#/responses/Login'
84 | /refresh_token:
85 | get:
86 | summary: 刷新token
87 | description: t
88 | tags:
89 | - Login
90 | security:
91 | - Authorization: []
92 | responses:
93 | 200:
94 | $ref: '#/responses/Login'
95 | /logout:
96 | get:
97 | summary: 退出登录
98 | description: t
99 | tags:
100 | - Login
101 | security:
102 | - Authorization: []
103 | responses:
104 | 200:
105 | $ref: '#/responses/Success'
106 | ##用户相关
107 | /user/info:
108 | get:
109 | summary: 获取用户信息
110 | description: t
111 | tags:
112 | - User
113 | security:
114 | - Authorization: []
115 | responses:
116 | 200:
117 | $ref: '#/responses/UserInfo'
118 | /user:
119 | get:
120 | summary: 获取用户列表
121 | description: 获取用户列表
122 | tags:
123 | - User
124 | security:
125 | - Authorization: []
126 | parameters:
127 | - $ref: "#/parameters/page"
128 | - $ref: "#/parameters/limit"
129 | responses:
130 | 200:
131 | $ref: '#/responses/UserList'
132 | post:
133 | summary: 添加用户
134 | description: 添加用户
135 | tags:
136 | - User
137 | security:
138 | - Authorization: []
139 | parameters:
140 | - name: body
141 | in: body
142 | schema:
143 | $ref: "#/parameters/UserPost"
144 | responses:
145 | 200:
146 | $ref: '#/responses/Success'
147 | put:
148 | summary: 修改用户
149 | description: 修改用户
150 | tags:
151 | - User
152 | security:
153 | - Authorization: []
154 | parameters:
155 | - name: body
156 | in: body
157 | schema:
158 | $ref: "#/parameters/UserPut"
159 | responses:
160 | 200:
161 | $ref: '#/responses/Login'
162 | delete:
163 | summary: 删除用户
164 | description: 删除用户
165 | tags:
166 | - User
167 | security:
168 | - Authorization: []
169 | parameters:
170 | - name: body
171 | in: body
172 | schema:
173 | required:
174 | - id
175 | properties:
176 | id:
177 | type: integer
178 | responses:
179 | 200:
180 | $ref: '#/responses/Success'
181 | ##角色相关
182 | /role:
183 | get:
184 | summary: 获取角色列表
185 | description: 获取角色列表
186 | tags:
187 | - Role
188 | security:
189 | - Authorization: []
190 | parameters:
191 | - $ref: "#/parameters/page"
192 | - $ref: "#/parameters/limit"
193 | - name: username
194 | in: query
195 | description: 用户名(编辑用户角色的时候使用这个参数,不使用分页参数)
196 | type: string
197 | responses:
198 | 200:
199 | $ref: '#/responses/RoleList'
200 | post:
201 | summary: 添加角色
202 | description: 添加角色
203 | tags:
204 | - Role
205 | security:
206 | - Authorization: []
207 | parameters:
208 | - name: body
209 | in: body
210 | schema:
211 | $ref: "#/definitions/Role"
212 | responses:
213 | 200:
214 | $ref: '#/responses/Success'
215 | put:
216 | summary: 修改角色
217 | description: 修改角色
218 | tags:
219 | - Role
220 | security:
221 | - Authorization: []
222 | parameters:
223 | - name: body
224 | in: body
225 | schema:
226 | $ref: "#/definitions/Role"
227 | responses:
228 | 200:
229 | $ref: '#/responses/Login'
230 | delete:
231 | summary: 删除角色
232 | description: 删除角色
233 | tags:
234 | - Role
235 | security:
236 | - Authorization: []
237 | parameters:
238 | - name: body
239 | in: body
240 | schema:
241 | $ref: "#/definitions/Role"
242 | responses:
243 | 200:
244 | $ref: '#/responses/Success'
245 | /role/byuser:
246 | put:
247 | summary: 获取角色权限
248 | description: 获取角色权限
249 | tags:
250 | - Role
251 | security:
252 | - Authorization: []
253 | parameters:
254 | - name: body
255 | in: body
256 | schema:
257 | $ref: "#/parameters/UserRolePut"
258 | responses:
259 | 200:
260 | $ref: '#/responses/Success'
261 | /role/menu:
262 | put:
263 | summary: 修改角色菜单
264 | description: 修改角色菜单
265 | tags:
266 | - Role
267 | security:
268 | - Authorization: []
269 | parameters:
270 | - name: body
271 | in: body
272 | schema:
273 | $ref: "#/parameters/RoleMenuPut"
274 | responses:
275 | 200:
276 | $ref: '#/responses/Success'
277 | ##权限相关
278 | /policy:
279 | get:
280 | summary: 获取用户列表
281 | description: 获取用户列表
282 | tags:
283 | - Policy
284 | security:
285 | - Authorization: []
286 | parameters:
287 | - $ref: "#/parameters/page"
288 | - $ref: "#/parameters/limit"
289 | responses:
290 | 200:
291 | $ref: '#/responses/PolicyList'
292 | put:
293 | summary: 修改用户
294 | description: 修改用户
295 | tags:
296 | - Policy
297 | security:
298 | - Authorization: []
299 | parameters:
300 | - name: body
301 | in: body
302 | schema:
303 | $ref: "#/definitions/Policy"
304 | responses:
305 | 200:
306 | $ref: '#/responses/Success'
307 | /policy/byrole:
308 | get:
309 | summary: 获取角色权限
310 | description: 获取角色权限
311 | tags:
312 | - Policy
313 | security:
314 | - Authorization: []
315 | parameters:
316 | - name: role
317 | in: query
318 | description: 角色名
319 | type: string
320 | responses:
321 | 200:
322 | $ref: '#/responses/RolePolicyList'
323 | put:
324 | summary: 设置角色权限
325 | description: 设置角色权限
326 | tags:
327 | - Policy
328 | security:
329 | - Authorization: []
330 | parameters:
331 | - name: body
332 | in: body
333 | schema:
334 | $ref: "#/parameters/RolePolicyPut"
335 | responses:
336 | 200:
337 | $ref: '#/responses/Success'
338 | ##菜单相关
339 | /menu:
340 | get:
341 | summary: 获取菜单列表
342 | description: 获取菜单列表
343 | tags:
344 | - Menu
345 | security:
346 | - Authorization: []
347 | parameters:
348 | - $ref: "#/parameters/page"
349 | - $ref: "#/parameters/limit"
350 | responses:
351 | 200:
352 | $ref: '#/responses/MenuList'
353 | post:
354 | summary: 添加菜单
355 | description: 添加菜单
356 | tags:
357 | - Menu
358 | security:
359 | - Authorization: []
360 | parameters:
361 | - name: body
362 | in: body
363 | schema:
364 | $ref: "#/parameters/MenuPost"
365 | responses:
366 | 200:
367 | $ref: '#/responses/Success'
368 | put:
369 | summary: 修改菜单
370 | description: 修改菜单
371 | tags:
372 | - Menu
373 | security:
374 | - Authorization: []
375 | parameters:
376 | - name: body
377 | in: body
378 | schema:
379 | $ref: "#/parameters/MenuPut"
380 | responses:
381 | 200:
382 | $ref: '#/responses/Login'
383 | delete:
384 | summary: 删除菜单
385 | description: 删除菜单
386 | tags:
387 | - Menu
388 | security:
389 | - Authorization: []
390 | parameters:
391 | - name: body
392 | in: body
393 | schema:
394 | required:
395 | - id
396 | properties:
397 | id:
398 | type: integer
399 | responses:
400 | 200:
401 | $ref: '#/responses/Success'
402 |
403 | #自定义结构
404 | definitions:
405 | #基础返回
406 | Result:
407 | properties:
408 | code:
409 | type: integer
410 | format: int
411 | default: 2000
412 | message:
413 | type: string
414 | data:
415 | type: object
416 | Success:
417 | allOf:
418 | - $ref: '#/definitions/Result'
419 | - type: object
420 | Error:
421 | allOf:
422 | - $ref: '#/definitions/Result'
423 | - type: object
424 | ##User
425 | UserBase:
426 | properties:
427 | nick_name:
428 | type: string
429 | email:
430 | type: string
431 | phone:
432 | type: string
433 | User:
434 | allOf:
435 | - $ref: '#/definitions/UserBase'
436 | - type: object
437 | properties:
438 | id:
439 | type: integer
440 | readOnly: true
441 | user_name:
442 | type: string
443 | Introduction:
444 | type: string
445 | status:
446 | type: integer
447 | age:
448 | type: integer
449 | add_user_id:
450 | type: integer
451 | readOnly: true
452 | add_time:
453 | type: string
454 | format: date-time
455 | readOnly: true
456 | update_time:
457 | type: string
458 | format: date-time
459 | readOnly: true
460 | Users:
461 | type: array
462 | items:
463 | $ref: "#/definitions/User"
464 | ##Role
465 | Role:
466 | properties:
467 | name:
468 | type: string
469 | role:
470 | type: string
471 | Roles:
472 | type: array
473 | items:
474 | $ref: "#/definitions/Role"
475 | ##Policy
476 | Policy:
477 | properties:
478 | name:
479 | type: string
480 | policy:
481 | type: string
482 | Policys:
483 | type: array
484 | items:
485 | $ref: "#/definitions/Policy"
486 | ##Menu
487 | Meta:
488 | properties:
489 | noCache:
490 | type: boolean
491 | icon:
492 | type: string
493 | title:
494 | type: string
495 | Menu:
496 | properties:
497 | alwaysShow:
498 | type: boolean
499 | component:
500 | type: string
501 | hidden:
502 | type: boolean
503 | name:
504 | type: string
505 | parent_name:
506 | type: string
507 | path:
508 | type: string
509 | redirect:
510 | type: string
511 | sort:
512 | type: integer
513 | meta:
514 | $ref: "#/definitions/Meta"
515 | children:
516 | $ref: "#/definitions/Menus"
517 | Menus:
518 | type: array
519 | items:
520 | $ref: "#/definitions/Menu"
521 |
522 | #请求参数
523 | parameters:
524 | page:
525 | name: page
526 | in: query
527 | description: Page number
528 | type: integer
529 | limit:
530 | name: limit
531 | in: query
532 | description: limit
533 | type: integer
534 | UserPost:
535 | allOf:
536 | - $ref: '#/parameters/UserPut'
537 | - type: object
538 | properties:
539 | user_name:
540 | type: string
541 | UserPut:
542 | allOf:
543 | - $ref: '#/definitions/UserBase'
544 | - type: object
545 | properties:
546 | password:
547 | description: 添加时必填,修改时选填。
548 | type: string
549 | format: password
550 | passwordconfirm:
551 | description: 添加时必填,修改时选填。
552 | type: string
553 | format: password
554 | UserRolePut:
555 | properties:
556 | roles:
557 | type: array
558 | items:
559 | type: string
560 | username:
561 | type: string
562 | RolePolicyPut:
563 | properties:
564 | policys:
565 | type: array
566 | items:
567 | type: string
568 | role:
569 | type: string
570 | RoleMenuPut:
571 | properties:
572 | menus:
573 | type: array
574 | items:
575 | type: string
576 | role:
577 | type: string
578 | MenuPost:
579 | allOf:
580 | - $ref: '#/definitions/Menu'
581 | - type: object
582 | MenuPut:
583 | allOf:
584 | - $ref: '#/definitions/Menu'
585 | - type: object
586 |
587 | #响应
588 | responses:
589 | Success:
590 | description: Seccess
591 | schema:
592 | $ref: '#/definitions/Success'
593 | Error500:
594 | description: An unexpected error occured.
595 | schema:
596 | $ref: '#/definitions/Error'
597 | ##Login
598 | LoginKey:
599 | allOf:
600 | - $ref: '#/definitions/Result'
601 | - type: object
602 | properties:
603 | data:
604 | type: object
605 | properties:
606 | cryptotype:
607 | type: string
608 | key:
609 | type: string
610 | kid:
611 | type: string
612 | timestamp:
613 | type: string
614 | Login:
615 | allOf:
616 | - $ref: '#/definitions/Result'
617 | - type: object
618 | properties:
619 | data:
620 | type: object
621 | properties:
622 | expire:
623 | type: string
624 | token:
625 | type: string
626 | ##User
627 | UserInfo:
628 | allOf:
629 | - $ref: '#/definitions/Result'
630 | - type: object
631 | properties:
632 | data:
633 | type: object
634 | properties:
635 | avatar:
636 | type: string
637 | introduction:
638 | type: string
639 | name:
640 | type: string
641 | roles:
642 | type: array
643 | items:
644 | type: string
645 | UserList:
646 | allOf:
647 | - $ref: '#/definitions/Result'
648 | - type: object
649 | properties:
650 | data:
651 | type: object
652 | properties:
653 | total:
654 | type: integer
655 | items:
656 | $ref: "#/definitions/Users"
657 | ##Role
658 | RoleList:
659 | allOf:
660 | - $ref: '#/definitions/Result'
661 | - type: object
662 | properties:
663 | data:
664 | type: object
665 | properties:
666 | total:
667 | type: integer
668 | items:
669 | $ref: "#/definitions/Roles"
670 | role_items:
671 | $ref: "#/definitions/Roles"
672 | RolePolicyList:
673 | allOf:
674 | - $ref: '#/definitions/Result'
675 | - type: object
676 | properties:
677 | data:
678 | type: object
679 | properties:
680 | total:
681 | type: integer
682 | all_policy_items:
683 | $ref: "#/definitions/Policys"
684 | role_policy_items:
685 | $ref: "#/definitions/Policys"
686 | ##Policy
687 | PolicyList:
688 | allOf:
689 | - $ref: '#/definitions/Result'
690 | - type: object
691 | properties:
692 | data:
693 | type: object
694 | properties:
695 | total:
696 | type: integer
697 | items:
698 | $ref: "#/definitions/Policys"
699 | ##Menu
700 | MenuList:
701 | allOf:
702 | - $ref: '#/definitions/Result'
703 | - type: object
704 | properties:
705 | data:
706 | type: object
707 | properties:
708 | total:
709 | type: integer
710 | items:
711 | $ref: "#/definitions/Menus"
712 |
713 | #标签
714 | tags:
715 | - name: Login
716 | description: 登录相关
717 | - name: User
718 | description: 用户相关
719 | - name: Role
720 | description: 角色相关
721 | - name: Policy
722 | description: 权限相关
723 | - name: Menu
724 | description: 菜单相关
725 |
726 | #API鉴权
727 | securityDefinitions:
728 | Authorization:
729 | name: Authorization
730 | type: apiKey
731 | in: header
732 |
--------------------------------------------------------------------------------