Browse Source

Merge pull request #189 from azunia/own_dev

修改了头像组件 增加了本地上传功能
奇淼(piexlmax 4 years ago
parent
commit
0659feb91c

+ 3 - 3
README-zh_CN.md

@@ -13,9 +13,9 @@
 [English](./README.md) | 简体中文
 
 # 项目文档
-[在线文档](http://doc.henrongyi.top/)
+[在线文档](https://www.gin-vue-admin.com/)
 
-[开发教学](http://doc.henrongyi.top/help/) (贡献者:  <a href="https://github.com/LLemonGreen">LLemonGreen</a> And <a href="https://github.com/fkk0509">Fann</a>)
+[开发教学](https://www.gin-vue-admin.com/docs/help) (贡献者:  <a href="https://github.com/LLemonGreen">LLemonGreen</a> And <a href="https://github.com/fkk0509">Fann</a>)
 - 前端UI框架:[element-ui](https://github.com/ElemeFE/element) 
 - 后台框架:[gin](https://github.com/gin-gonic/gin) 
 
@@ -306,7 +306,7 @@ swag init
 
 ## 9. 捐赠
 
-如果你觉得这个项目对你有帮助,你可以请作者喝饮料 :tropical_drink: [点我](http://doc.henrongyi.top/more/coffee.html)
+如果你觉得这个项目对你有帮助,你可以请作者喝饮料 :tropical_drink: [点我](https://www.gin-vue-admin.com/docs/coffee)
 
 ## 10. 商用注意事项
 

+ 3 - 3
README.md

@@ -13,9 +13,9 @@
 English | [简体中文](./README-zh_CN.md)
 
 # Project Guidelines
-[Online Documentation](http://doc.henrongyi.top/)
+[Online Documentation](https://www.gin-vue-admin.com/)
 
-[Development Steps](http://doc.henrongyi.top/help/) (Contributor:  <a href="https://github.com/LLemonGreen">LLemonGreen</a> And <a href="https://github.com/fkk0509">Fann</a>)
+[Development Steps](https://www.gin-vue-admin.com/docs/help) (Contributor:  <a href="https://github.com/LLemonGreen">LLemonGreen</a> And <a href="https://github.com/fkk0509">Fann</a>)
 - Web UI Framework:[element-ui](https://github.com/ElemeFE/element)  
 - Server Framework:[gin](https://github.com/gin-gonic/gin) 
 
@@ -315,7 +315,7 @@ backend code file: model\dnModel\api.go
 
 ## 9. Donate
 
-If you find this project useful, you can buy author a glass of juice :tropical_drink: [here](http://doc.henrongyi.top/more/coffee.html)
+If you find this project useful, you can buy author a glass of juice :tropical_drink: [here](https://www.gin-vue-admin.com/docs/coffee)
 
 ## 10. Commercial considerations
 

+ 12 - 2
server/api/v1/exa_file_upload_download.go

@@ -2,6 +2,7 @@ package v1
 
 import (
 	"fmt"
+	"gin-vue-admin/global"
 	"gin-vue-admin/global/response"
 	"gin-vue-admin/model"
 	"gin-vue-admin/model/request"
@@ -27,8 +28,17 @@ func UploadFile(c *gin.Context) {
 		response.FailWithMessage(fmt.Sprintf("上传文件失败,%v", err), c)
 	} else {
 		// 文件上传后拿到文件路径
-		err, filePath, key := utils.Upload(header)
-		if err != nil {
+		var uploadErr error
+		var filePath string
+		var key string
+		if global.GVA_CONFIG.LocalUpload.Local {
+			// 本地上传
+			uploadErr, filePath, key = utils.UploadFileLocal(header)
+		} else {
+			// 七牛云上传
+			uploadErr, filePath, key = utils.UploadRemote(header)
+		}
+		if uploadErr != nil {
 			response.FailWithMessage(fmt.Sprintf("接收返回值失败,%v", err), c)
 		} else {
 			// 修改数据库后得到修改后的user并且返回供前端使用

+ 2 - 2
server/api/v1/exa_simple_uploader.go

@@ -52,7 +52,7 @@ func SimpleUploaderUpload(c *gin.Context) {
 // @Security ApiKeyAuth
 
 // @Produce  application/json
-// @Param params md5 get "测试文件是否已经存在和判断已经上传过的切片"
+// @Param md5 query string true "测试文件是否已经存在和判断已经上传过的切片"
 // @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
 // @Router /simpleUploader/checkFileMd5 [get]
 func CheckFileMd5(c *gin.Context) {
@@ -72,7 +72,7 @@ func CheckFileMd5(c *gin.Context) {
 // @Summary 合并文件
 // @Security ApiKeyAuth
 // @Produce  application/json
-// @Param params md5 get "合并文件"
+// @Param md5 query string true "合并文件"
 // @Success 200 {string} string "{"success":true,"data":{},"msg":"合并成功"}"
 // @Router /simpleUploader/mergeFileMd5 [get]
 func MergeFileMd5(c *gin.Context) {

+ 15 - 7
server/api/v1/sys_user.go

@@ -88,10 +88,12 @@ func tokenNext(c *gin.Context, user model.SysUser) {
 		UUID:        user.UUID,
 		ID:          user.ID,
 		NickName:    user.NickName,
+		Username:    user.Username,
 		AuthorityId: user.AuthorityId,
+		BufferTime:  60*60*24, // 缓冲时间1天 缓冲时间内会获得新的token刷新令牌 此时一个用户会存在两个有效令牌 但是前端只留一个 另一个会丢失
 		StandardClaims: jwt.StandardClaims{
 			NotBefore: time.Now().Unix() - 1000,       // 签名生效时间
-			ExpiresAt: time.Now().Unix() + 60*60*24*7, // 过期时间 一周
+			ExpiresAt: time.Now().Unix() + 60*60*24*7, // 过期时间 7天
 			Issuer:    "qmPlus",                       // 签名的发行者
 		},
 	}
@@ -108,11 +110,9 @@ func tokenNext(c *gin.Context, user model.SysUser) {
 		}, c)
 		return
 	}
-	var loginJwt model.JwtBlacklist
-	loginJwt.Jwt = token
 	err, jwtStr := service.GetRedisJWT(user.Username)
 	if err == redis.Nil {
-		if err := service.SetRedisJWT(loginJwt, user.Username); err != nil {
+		if err := service.SetRedisJWT(token, user.Username); err != nil {
 			response.FailWithMessage("设置登录状态失败", c)
 			return
 		}
@@ -130,7 +130,7 @@ func tokenNext(c *gin.Context, user model.SysUser) {
 			response.FailWithMessage("jwt作废失败", c)
 			return
 		}
-		if err := service.SetRedisJWT(loginJwt, user.Username); err != nil {
+		if err := service.SetRedisJWT(jwtStr, user.Username); err != nil {
 			response.FailWithMessage("设置登录状态失败", c)
 			return
 		}
@@ -195,8 +195,16 @@ func UploadHeaderImg(c *gin.Context) {
 		response.FailWithMessage(fmt.Sprintf("上传文件失败,%v", err), c)
 	} else {
 		// 文件上传后拿到文件路径
-		err, filePath, _ := utils.Upload(header)
-		if err != nil {
+		var uploadErr error
+		var filePath string
+		if global.GVA_CONFIG.LocalUpload.Local {
+			// 本地上传
+			uploadErr, filePath, _ = utils.UploadAvatarLocal(header)
+		} else {
+			// 七牛云上传
+			uploadErr, filePath, _ = utils.UploadRemote(header)
+		}
+		if uploadErr != nil {
 			response.FailWithMessage(fmt.Sprintf("接收返回值失败,%v", err), c)
 		} else {
 			// 修改数据库后得到修改后的user并且返回供前端使用

+ 37 - 31
server/config.yaml

@@ -2,60 +2,66 @@
 
 # casbin configuration
 casbin:
-    model-path: './resource/rbac_model.conf'
+  model-path: './resource/rbac_model.conf'
 
 # jwt configuration
 jwt:
-    signing-key: 'qmPlus'
+  signing-key: 'qmPlus'
 
 # mysql connect configuration
 mysql:
-    username: root
-    password: 'Aa@6447985'
-    path: '127.0.0.1:3306'
-    db-name: 'qmPlus'
-    config: 'charset=utf8&parseTime=True&loc=Local'
-    max-idle-conns: 10
-    max-open-conns: 10
-    log-mode: false
+  username: root
+  password: 'Aa@6447985'
+  path: '127.0.0.1:3306'
+  db-name: 'qmPlus'
+  config: 'charset=utf8mb4&parseTime=True&loc=Local'
+  max-idle-conns: 10
+  max-open-conns: 10
+  log-mode: false
 
 #sqlite 配置
 sqlite:
-    path: db.db
-    log-mode: true
-    config: 'loc=Asia/Shanghai'
+  path: db.db
+  log-mode: true
+  config: 'loc=Asia/Shanghai'
 
 # oss configuration
 
+# 切换本地与七牛云上传,分配头像和文件路径
+localupload:
+  local: true
+  avatar-path: uploads/avatar
+  file-path: uploads/file
+
 # 请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址
 qiniu:
-    access-key: '25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ'
-    secret-key: 'pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY'
-    bucket: 'qm-plus-img'
-    img-path: 'http://qmplusimg.henrongyi.top'
+  access-key: '25j8dYBZ2wuiy0yhwShytjZDTX662b8xiFguwxzZ'
+  secret-key: 'pgdbqEsf7ooZh7W3xokP833h3dZ_VecFXPDeG5JY'
+  bucket: 'qm-plus-img'
+  img-path: 'http://qmplusimg.henrongyi.top'
 
 # redis configuration
 redis:
-    addr: '127.0.0.1:6379'
-    password: ''
-    db: 0
+  addr: '127.0.0.1:6379'
+  password: ''
+  db: 0
 
 # system configuration
 system:
-    use-multipoint: false
-    env: 'public'  # Change to "develop" to skip authentication for development mode
-    addr: 8888
-    db-type: "mysql"  # support mysql/sqlite
+  use-multipoint: false
+  env: 'public'  # Change to "develop" to skip authentication for development mode
+  addr: 8888
+  db-type: "mysql"  # support mysql/sqlite
 
 # captcha configuration
 captcha:
-    key-long: 6
-    img-width: 240
-    img-height: 80
+  key-long: 6
+  img-width: 240
+  img-height: 80
 
 # logger configuration
 log:
-    prefix: '[GIN-VUE-ADMIN]'
-    log-file: true
-    stdout: 'DEBUG'
-    file: 'DEBUG'
+  prefix: '[GIN-VUE-ADMIN]'
+  log-file: true
+  stdout: 'DEBUG'
+  file: 'DEBUG'

+ 8 - 0
server/config/config.go

@@ -10,6 +10,7 @@ type Server struct {
 	JWT       JWT       `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
 	Captcha   Captcha   `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
 	Log       Log       `mapstructure:"log" json:"log" yaml:"log"`
+	LocalUpload LocalUpload `mapstructure:"localUpload" json:"localUpload" yaml:"localUpload"`
 }
 
 type System struct {
@@ -43,6 +44,13 @@ type Redis struct {
 	Password string `mapstructure:"password" json:"password" yaml:"password"`
 	DB       int    `mapstructure:"db" json:"db" yaml:"db"`
 }
+
+type LocalUpload struct {
+	Local bool `mapstructure:"local" json:"local" yaml:"local"`
+	AvatarPath string `mapstructure:"avatar-path" json:"avatarPath" yaml:"avatar-path"`
+	FilePath string `mapstructure:"file-path" json:"filePath" yaml:"file-path"`
+}
+
 type Qiniu struct {
 	AccessKey string `mapstructure:"access-key" json:"accessKey" yaml:"access-key"`
 	SecretKey string `mapstructure:"secret-key" json:"secretKey" yaml:"secret-key"`

+ 59 - 59
server/db/qmplus.sql

@@ -22,14 +22,14 @@ SET FOREIGN_KEY_CHECKS = 0;
 -- ----------------------------
 DROP TABLE IF EXISTS `casbin_rule`;
 CREATE TABLE `casbin_rule`  (
-  `p_type` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
-  `v0` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
-  `v1` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
-  `v2` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
-  `v3` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
-  `v4` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL,
-  `v5` varchar(100) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+  `p_type` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
+  `v0` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
+  `v1` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
+  `v2` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
+  `v3` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
+  `v4` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
+  `v5` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of casbin_rule
@@ -190,12 +190,12 @@ CREATE TABLE `exa_customers`  (
   `updated_at` timestamp(0) NULL DEFAULT NULL,
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
   `customer_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '客户名',
-  `customer_phone_data` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '客户电话',
+  `customer_phone_data` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '客户电话',
   `sys_user_id` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '负责员工id',
-  `sys_user_authority_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '负责员工角色',
+  `sys_user_authority_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '负责员工角色',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_exa_customers_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of exa_customers
@@ -212,11 +212,11 @@ CREATE TABLE `exa_file_chunks`  (
   `updated_at` timestamp(0) NULL DEFAULT NULL,
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
   `exa_file_id` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '文件id',
-  `file_chunk_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '切片路径',
+  `file_chunk_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '切片路径',
   `file_chunk_number` int(11) NULL DEFAULT NULL COMMENT '切片标号',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_exa_file_chunks_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Table structure for exa_file_upload_and_downloads
@@ -227,14 +227,14 @@ CREATE TABLE `exa_file_upload_and_downloads`  (
   `created_at` timestamp(0) NULL DEFAULT NULL,
   `updated_at` timestamp(0) NULL DEFAULT NULL,
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
-  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名',
-  `url` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件URL',
-  `tag` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件类型',
-  `key` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '标记',
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '文件名',
+  `url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '文件URL',
+  `tag` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '文件类型',
+  `key` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '标记',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_file_upload_and_downloads_deleted_at`(`deleted_at`) USING BTREE,
   INDEX `idx_exa_file_upload_and_downloads_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 20 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of exa_file_upload_and_downloads
@@ -251,14 +251,14 @@ CREATE TABLE `exa_files`  (
   `created_at` timestamp(0) NULL DEFAULT NULL,
   `updated_at` timestamp(0) NULL DEFAULT NULL,
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
-  `file_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件名',
-  `file_md5` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件md5',
-  `file_path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '文件路径',
+  `file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '文件名',
+  `file_md5` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '文件md5',
+  `file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '文件路径',
   `chunk_total` int(11) NULL DEFAULT NULL COMMENT '切片总数',
   `is_finish` tinyint(1) NULL DEFAULT NULL COMMENT '是否完整',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_exa_files_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Table structure for exa_simple_uploaders
@@ -274,7 +274,7 @@ CREATE TABLE `exa_simple_uploaders`  (
   `total_chunks` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '切片总数',
   `is_done` tinyint(1) NULL DEFAULT NULL COMMENT '是否上传完成',
   `file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '文件本地路径'
-) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Compact;
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Table structure for jwt_blacklists
@@ -285,10 +285,10 @@ CREATE TABLE `jwt_blacklists`  (
   `created_at` timestamp(0) NULL DEFAULT NULL,
   `updated_at` timestamp(0) NULL DEFAULT NULL,
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
-  `jwt` text CHARACTER SET utf8 COLLATE utf8_general_ci NULL COMMENT 'jwt',
+  `jwt` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT 'jwt',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_jwt_blacklists_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Table structure for sys_apis
@@ -300,14 +300,14 @@ CREATE TABLE `sys_apis`  (
   `updated_at` timestamp(0) NULL DEFAULT NULL,
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
   `authority_id` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '角色id',
-  `path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路由path',
-  `description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路由描述',
-  `api_group` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '路由分组',
-  `method` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'POST' COMMENT '请求方法',
+  `path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '路由path',
+  `description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '路由描述',
+  `api_group` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '路由分组',
+  `method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT 'POST' COMMENT '请求方法',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_apis_deleted_at`(`deleted_at`) USING BTREE,
   INDEX `idx_sys_apis_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 103 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 103 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of sys_apis
@@ -385,15 +385,15 @@ INSERT INTO `sys_apis` VALUES (102, '2020-08-15 22:28:04', '2020-08-15 22:28:04'
 DROP TABLE IF EXISTS `sys_authorities`;
 CREATE TABLE `sys_authorities`  (
   `authority_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '角色id',
-  `authority_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '角色名',
-  `parent_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '父角色',
+  `authority_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '角色名',
+  `parent_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '父角色',
   `created_at` datetime(0) NULL DEFAULT NULL,
   `updated_at` datetime(0) NULL DEFAULT NULL,
   `deleted_at` datetime(0) NULL DEFAULT NULL,
   PRIMARY KEY (`authority_id`) USING BTREE,
   UNIQUE INDEX `authority_id`(`authority_id`) USING BTREE,
   INDEX `idx_sys_authorities_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of sys_authorities
@@ -483,7 +483,7 @@ CREATE TABLE `sys_base_menu_parameters`  (
   `value` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_sys_base_menu_parameters_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 9 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Table structure for sys_base_menus
@@ -496,20 +496,20 @@ CREATE TABLE `sys_base_menus`  (
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
   `menu_level` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '菜单等级(暂未使用)',
   `parent_id` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '父菜单id',
-  `path` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单path(路由path)',
-  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单name(路由name)',
+  `path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '菜单path(路由path)',
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '菜单name(路由name)',
   `hidden` tinyint(1) NULL DEFAULT NULL COMMENT '是否在列表隐藏',
-  `component` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '组件位置',
-  `title` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '显示名字',
-  `icon` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '显示图标',
-  `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '菜单别名',
+  `component` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '组件位置',
+  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '显示名字',
+  `icon` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '显示图标',
+  `nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '菜单别名',
   `sort` int(255) NULL DEFAULT NULL COMMENT '排序',
   `keep_alive` tinyint(1) NULL DEFAULT NULL COMMENT '是否缓存菜单内容',
   `default_menu` tinyint(1) NULL DEFAULT NULL COMMENT '默认菜单(暂未使用)',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_base_menus_deleted_at`(`deleted_at`) USING BTREE,
   INDEX `idx_sys_base_menus_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 54 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 54 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of sys_base_menus
@@ -576,13 +576,13 @@ CREATE TABLE `sys_dictionaries`  (
   `created_at` datetime(0) NULL DEFAULT NULL,
   `updated_at` datetime(0) NULL DEFAULT NULL,
   `deleted_at` datetime(0) NULL DEFAULT NULL,
-  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字典名(中)',
-  `type` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '字典名(英)',
+  `name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '字典名(中)',
+  `type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '字典名(英)',
   `status` tinyint(1) NULL DEFAULT NULL COMMENT '状态',
-  `desc` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '描述',
+  `desc` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '描述',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_sys_dictionaries_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 8 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of sys_dictionaries
@@ -603,14 +603,14 @@ CREATE TABLE `sys_dictionary_details`  (
   `created_at` datetime(0) NULL DEFAULT NULL,
   `updated_at` datetime(0) NULL DEFAULT NULL,
   `deleted_at` datetime(0) NULL DEFAULT NULL,
-  `label` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '展示值',
+  `label` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '展示值',
   `value` int(11) NULL DEFAULT NULL COMMENT '字典值',
   `status` tinyint(1) NULL DEFAULT NULL COMMENT '启用状态',
   `sort` int(11) NULL DEFAULT NULL COMMENT '排序标记',
   `sys_dictionary_id` int(11) NULL DEFAULT NULL COMMENT '关联标记',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_sys_dictionary_details_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 38 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 38 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of sys_dictionary_details
@@ -672,15 +672,15 @@ CREATE TABLE `sys_users`  (
   `updated_at` timestamp(0) NULL DEFAULT NULL,
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
   `uuid` varbinary(255) NULL DEFAULT NULL COMMENT 'uuid',
-  `nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'QMPlusUser' COMMENT '用户昵称',
-  `header_img` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT 'http://www.henrongyi.top/avatar/lufu.jpg' COMMENT '用户头像',
+  `nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT 'QMPlusUser' COMMENT '用户昵称',
+  `header_img` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT 'http://www.henrongyi.top/avatar/lufu.jpg' COMMENT '用户头像',
   `authority_id` double NULL DEFAULT 888 COMMENT '用户角色',
-  `username` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登录用户名',
-  `password` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '登录密码',
+  `username` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '登录用户名',
+  `password` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '登录密码',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_users_deleted_at`(`deleted_at`) USING BTREE,
   INDEX `idx_sys_users_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 12 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Records of sys_users
@@ -699,15 +699,15 @@ CREATE TABLE `sys_workflow_step_infos`  (
   `deleted_at` timestamp(0) NULL DEFAULT NULL,
   `workflow_id` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '节点id',
   `is_strat` tinyint(1) NULL DEFAULT NULL COMMENT '是否是开始节点',
-  `step_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '步骤name',
+  `step_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '步骤name',
   `step_no` double NULL DEFAULT NULL COMMENT '第几步',
-  `step_authority_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '可操作者角色',
+  `step_authority_id` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '可操作者角色',
   `is_end` tinyint(1) NULL DEFAULT NULL COMMENT '是否是结尾',
   `sys_workflow_id` int(10) UNSIGNED NULL DEFAULT NULL COMMENT '关联工作流id',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_workflow_step_infos_deleted_at`(`deleted_at`) USING BTREE,
   INDEX `idx_sys_workflow_step_infos_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- Table structure for sys_workflows
@@ -718,12 +718,12 @@ CREATE TABLE `sys_workflows`  (
   `created_at` datetime(0) NULL DEFAULT NULL,
   `updated_at` datetime(0) NULL DEFAULT NULL,
   `deleted_at` datetime(0) NULL DEFAULT NULL,
-  `workflow_nick_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '工作流中文名称',
-  `workflow_name` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '工作流英文名称',
-  `workflow_description` varchar(255) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '工作流描述',
+  `workflow_nick_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '工作流中文名称',
+  `workflow_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '工作流英文名称',
+  `workflow_description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '工作流描述',
   PRIMARY KEY (`id`) USING BTREE,
   INDEX `idx_sys_workflows_deleted_at`(`deleted_at`) USING BTREE
-) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Compact;
+) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin  ROW_FORMAT = Compact;
 
 -- ----------------------------
 -- View structure for authority_menu

+ 170 - 1
server/docs/docs.go

@@ -1,6 +1,6 @@
 // GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
 // This file was generated by swaggo/swag at
-// 2020-07-07 10:12:31.2264113 +0800 CST m=+0.088765101
+// 2020-08-20 11:59:55.622609 +0800 CST m=+0.106561201
 
 package docs
 
@@ -1534,6 +1534,99 @@ var doc = `{
                 }
             }
         },
+        "/simpleUploader/checkFileMd5": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "测试文件是否已经存在和判断已经上传过的切片",
+                        "name": "md5",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/simpleUploader/mergeFileMd5": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SimpleUploader"
+                ],
+                "summary": "合并文件",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "合并文件",
+                        "name": "md5",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"success\":true,\"data\":{},\"msg\":\"合并成功\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/simpleUploader/upload": {
+            "post": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "consumes": [
+                    "multipart/form-data"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SimpleUploader"
+                ],
+                "summary": "断点续传插件版示例",
+                "parameters": [
+                    {
+                        "type": "file",
+                        "description": "断点续传插件版示例",
+                        "name": "file",
+                        "in": "formData",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"success\":true,\"data\":{},\"msg\":\"上传成功\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
         "/sysDictionary/createSysDictionary": {
             "post": {
                 "security": [
@@ -2002,6 +2095,45 @@ var doc = `{
                 }
             }
         },
+        "/sysOperationRecord/deleteSysOperationRecordByIds": {
+            "delete": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SysOperationRecord"
+                ],
+                "summary": "批量删除SysOperationRecord",
+                "parameters": [
+                    {
+                        "description": "批量删除SysOperationRecord",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/request.IdsReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
         "/sysOperationRecord/findSysOperationRecord": {
             "get": {
                 "security": [
@@ -2711,6 +2843,9 @@ var doc = `{
                 "dataTypeLong": {
                     "type": "string"
                 },
+                "dictType": {
+                    "type": "string"
+                },
                 "fieldDesc": {
                     "type": "string"
                 },
@@ -2819,6 +2954,12 @@ var doc = `{
                 "name": {
                     "type": "string"
                 },
+                "parameters": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/model.SysBaseMenuParameter"
+                    }
+                },
                 "parentId": {
                     "type": "string"
                 },
@@ -2833,6 +2974,23 @@ var doc = `{
                 }
             }
         },
+        "model.SysBaseMenuParameter": {
+            "type": "object",
+            "properties": {
+                "key": {
+                    "type": "string"
+                },
+                "sysBaseMenuId": {
+                    "type": "integer"
+                },
+                "type": {
+                    "type": "string"
+                },
+                "value": {
+                    "type": "string"
+                }
+            }
+        },
         "model.SysDictionary": {
             "type": "object",
             "properties": {
@@ -3070,6 +3228,17 @@ var doc = `{
                 }
             }
         },
+        "request.IdsReq": {
+            "type": "object",
+            "properties": {
+                "ids": {
+                    "type": "array",
+                    "items": {
+                        "type": "integer"
+                    }
+                }
+            }
+        },
         "request.PageInfo": {
             "type": "object",
             "properties": {

+ 169 - 0
server/docs/swagger.json

@@ -1517,6 +1517,99 @@
                 }
             }
         },
+        "/simpleUploader/checkFileMd5": {
+            "get": {
+                "produces": [
+                    "application/json"
+                ],
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "测试文件是否已经存在和判断已经上传过的切片",
+                        "name": "md5",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"success\":true,\"data\":{},\"msg\":\"查询成功\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/simpleUploader/mergeFileMd5": {
+            "get": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SimpleUploader"
+                ],
+                "summary": "合并文件",
+                "parameters": [
+                    {
+                        "type": "string",
+                        "description": "合并文件",
+                        "name": "md5",
+                        "in": "query",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"success\":true,\"data\":{},\"msg\":\"合并成功\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
+        "/simpleUploader/upload": {
+            "post": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "consumes": [
+                    "multipart/form-data"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SimpleUploader"
+                ],
+                "summary": "断点续传插件版示例",
+                "parameters": [
+                    {
+                        "type": "file",
+                        "description": "断点续传插件版示例",
+                        "name": "file",
+                        "in": "formData",
+                        "required": true
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"success\":true,\"data\":{},\"msg\":\"上传成功\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
         "/sysDictionary/createSysDictionary": {
             "post": {
                 "security": [
@@ -1985,6 +2078,45 @@
                 }
             }
         },
+        "/sysOperationRecord/deleteSysOperationRecordByIds": {
+            "delete": {
+                "security": [
+                    {
+                        "ApiKeyAuth": []
+                    }
+                ],
+                "consumes": [
+                    "application/json"
+                ],
+                "produces": [
+                    "application/json"
+                ],
+                "tags": [
+                    "SysOperationRecord"
+                ],
+                "summary": "批量删除SysOperationRecord",
+                "parameters": [
+                    {
+                        "description": "批量删除SysOperationRecord",
+                        "name": "data",
+                        "in": "body",
+                        "required": true,
+                        "schema": {
+                            "type": "object",
+                            "$ref": "#/definitions/request.IdsReq"
+                        }
+                    }
+                ],
+                "responses": {
+                    "200": {
+                        "description": "{\"success\":true,\"data\":{},\"msg\":\"删除成功\"}",
+                        "schema": {
+                            "type": "string"
+                        }
+                    }
+                }
+            }
+        },
         "/sysOperationRecord/findSysOperationRecord": {
             "get": {
                 "security": [
@@ -2694,6 +2826,9 @@
                 "dataTypeLong": {
                     "type": "string"
                 },
+                "dictType": {
+                    "type": "string"
+                },
                 "fieldDesc": {
                     "type": "string"
                 },
@@ -2802,6 +2937,12 @@
                 "name": {
                     "type": "string"
                 },
+                "parameters": {
+                    "type": "array",
+                    "items": {
+                        "$ref": "#/definitions/model.SysBaseMenuParameter"
+                    }
+                },
                 "parentId": {
                     "type": "string"
                 },
@@ -2816,6 +2957,23 @@
                 }
             }
         },
+        "model.SysBaseMenuParameter": {
+            "type": "object",
+            "properties": {
+                "key": {
+                    "type": "string"
+                },
+                "sysBaseMenuId": {
+                    "type": "integer"
+                },
+                "type": {
+                    "type": "string"
+                },
+                "value": {
+                    "type": "string"
+                }
+            }
+        },
         "model.SysDictionary": {
             "type": "object",
             "properties": {
@@ -3053,6 +3211,17 @@
                 }
             }
         },
+        "request.IdsReq": {
+            "type": "object",
+            "properties": {
+                "ids": {
+                    "type": "array",
+                    "items": {
+                        "type": "integer"
+                    }
+                }
+            }
+        },
         "request.PageInfo": {
             "type": "object",
             "properties": {

+ 105 - 0
server/docs/swagger.yaml

@@ -177,6 +177,8 @@ definitions:
         type: string
       dataTypeLong:
         type: string
+      dictType:
+        type: string
       fieldDesc:
         type: string
       fieldJson:
@@ -248,6 +250,10 @@ definitions:
         type: boolean
       name:
         type: string
+      parameters:
+        items:
+          $ref: '#/definitions/model.SysBaseMenuParameter'
+        type: array
       parentId:
         type: string
       path:
@@ -257,6 +263,17 @@ definitions:
       title:
         type: string
     type: object
+  model.SysBaseMenuParameter:
+    properties:
+      key:
+        type: string
+      sysBaseMenuId:
+        type: integer
+      type:
+        type: string
+      value:
+        type: string
+    type: object
   model.SysDictionary:
     properties:
       desc:
@@ -415,6 +432,13 @@ definitions:
       id:
         type: number
     type: object
+  request.IdsReq:
+    properties:
+      ids:
+        items:
+          type: integer
+        type: array
+    type: object
   request.PageInfo:
     properties:
       page:
@@ -1467,6 +1491,63 @@ paths:
       summary: 更新菜单
       tags:
       - menu
+  /simpleUploader/checkFileMd5:
+    get:
+      parameters:
+      - description: 测试文件是否已经存在和判断已经上传过的切片
+        in: query
+        name: md5
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"success":true,"data":{},"msg":"查询成功"}'
+          schema:
+            type: string
+  /simpleUploader/mergeFileMd5:
+    get:
+      parameters:
+      - description: 合并文件
+        in: query
+        name: md5
+        required: true
+        type: string
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"success":true,"data":{},"msg":"合并成功"}'
+          schema:
+            type: string
+      security:
+      - ApiKeyAuth: []
+      summary: 合并文件
+      tags:
+      - SimpleUploader
+  /simpleUploader/upload:
+    post:
+      consumes:
+      - multipart/form-data
+      parameters:
+      - description: 断点续传插件版示例
+        in: formData
+        name: file
+        required: true
+        type: file
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"success":true,"data":{},"msg":"上传成功"}'
+          schema:
+            type: string
+      security:
+      - ApiKeyAuth: []
+      summary: 断点续传插件版示例
+      tags:
+      - SimpleUploader
   /sysDictionary/createSysDictionary:
     post:
       consumes:
@@ -1755,6 +1836,30 @@ paths:
       summary: 删除SysOperationRecord
       tags:
       - SysOperationRecord
+  /sysOperationRecord/deleteSysOperationRecordByIds:
+    delete:
+      consumes:
+      - application/json
+      parameters:
+      - description: 批量删除SysOperationRecord
+        in: body
+        name: data
+        required: true
+        schema:
+          $ref: '#/definitions/request.IdsReq'
+          type: object
+      produces:
+      - application/json
+      responses:
+        "200":
+          description: '{"success":true,"data":{},"msg":"删除成功"}'
+          schema:
+            type: string
+      security:
+      - ApiKeyAuth: []
+      summary: 批量删除SysOperationRecord
+      tags:
+      - SysOperationRecord
   /sysOperationRecord/findSysOperationRecord:
     get:
       consumes:

+ 4 - 0
server/initialize/router.go

@@ -8,12 +8,16 @@ import (
 	"github.com/gin-gonic/gin"
 	"github.com/swaggo/gin-swagger"
 	"github.com/swaggo/gin-swagger/swaggerFiles"
+	"net/http"
 )
 
 // 初始化总路由
 
 func Routers() *gin.Engine {
 	var Router = gin.Default()
+	// 为用户头像和文件提供静态地址
+	Router.StaticFS(global.GVA_CONFIG.LocalUpload.AvatarPath, http.Dir(global.GVA_CONFIG.LocalUpload.AvatarPath))
+	Router.StaticFS(global.GVA_CONFIG.LocalUpload.FilePath, http.Dir(global.GVA_CONFIG.LocalUpload.FilePath))
 	// Router.Use(middleware.LoadTls())  // 打开就能玩https了
 	global.GVA_LOG.Debug("use middleware logger")
 	// 跨域

+ 2 - 2
server/middleware/cors.go

@@ -10,8 +10,8 @@ func Cors() gin.HandlerFunc {
 	return func(c *gin.Context) {
 		method := c.Request.Method
 		c.Header("Access-Control-Allow-Origin", "*")
-		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token")
-		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
+		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,X-Token,X-User-Id\"")
+		c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS,DELETE,PUT")
 		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
 		c.Header("Access-Control-Allow-Credentials", "true")
 

+ 37 - 21
server/middleware/jwt.go

@@ -9,6 +9,7 @@ import (
 	"gin-vue-admin/service"
 	"github.com/dgrijalva/jwt-go"
 	"github.com/gin-gonic/gin"
+	"strconv"
 	"time"
 )
 
@@ -16,9 +17,6 @@ func JWTAuth() gin.HandlerFunc {
 	return func(c *gin.Context) {
 		// 我们这里jwt鉴权取头部信息 x-token 登录时回返回token信息 这里前端需要把token存储到cookie或者本地localSstorage中 不过需要跟后端协商过期时间 可以约定刷新令牌或者重新登录
 		token := c.Request.Header.Get("x-token")
-		modelToken := model.JwtBlacklist{
-			Jwt: token,
-		}
 		if token == "" {
 			response.Result(response.ERROR, gin.H{
 				"reload": true,
@@ -26,7 +24,7 @@ func JWTAuth() gin.HandlerFunc {
 			c.Abort()
 			return
 		}
-		if service.IsBlacklist(token, modelToken) {
+		if service.IsBlacklist(token) {
 			response.Result(response.ERROR, gin.H{
 				"reload": true,
 			}, "您的帐户异地登陆或令牌失效", c)
@@ -50,6 +48,24 @@ func JWTAuth() gin.HandlerFunc {
 			c.Abort()
 			return
 		}
+		if claims.ExpiresAt - time.Now().Unix()<claims.BufferTime {
+			claims.ExpiresAt = time.Now().Unix() + 60*60*24*7
+			newToken,_ := j.CreateToken(*claims)
+			newClaims,_ := j.ParseToken(newToken)
+			c.Header("new-token",newToken)
+			c.Header("new-expires-at",strconv.FormatInt(newClaims.ExpiresAt,10))
+			if global.GVA_CONFIG.System.UseMultipoint {
+				err,RedisJwtToken := service.GetRedisJWT(newClaims.Username)
+				if err!=nil {
+					global.GVA_LOG.Error(err)
+				}else{
+					service.JsonInBlacklist(model.JwtBlacklist{Jwt: RedisJwtToken})
+					//当之前的取成功时才进行拉黑操作
+				}
+				// 无论如何都要记录当前的活跃状态
+				_ = service.SetRedisJWT(newToken,newClaims.Username)
+			}
+		}
 		c.Set("claims", claims)
 		c.Next()
 	}
@@ -111,20 +127,20 @@ func (j *JWT) ParseToken(tokenString string) (*request.CustomClaims, error) {
 }
 
 // 更新token
-func (j *JWT) RefreshToken(tokenString string) (string, error) {
-	jwt.TimeFunc = func() time.Time {
-		return time.Unix(0, 0)
-	}
-	token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
-		return j.SigningKey, nil
-	})
-	if err != nil {
-		return "", err
-	}
-	if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid {
-		jwt.TimeFunc = time.Now
-		claims.StandardClaims.ExpiresAt = time.Now().Add(1 * time.Hour).Unix()
-		return j.CreateToken(*claims)
-	}
-	return "", TokenInvalid
-}
+//func (j *JWT) RefreshToken(tokenString string) (string, error) {
+//	jwt.TimeFunc = func() time.Time {
+//		return time.Unix(0, 0)
+//	}
+//	token, err := jwt.ParseWithClaims(tokenString, &request.CustomClaims{}, func(token *jwt.Token) (interface{}, error) {
+//		return j.SigningKey, nil
+//	})
+//	if err != nil {
+//		return "", err
+//	}
+//	if claims, ok := token.Claims.(*request.CustomClaims); ok && token.Valid {
+//		jwt.TimeFunc = time.Now
+//		claims.StandardClaims.ExpiresAt = time.Now().Unix() + 60*60*24*7
+//		return j.CreateToken(*claims)
+//	}
+//	return "", TokenInvalid
+//}

+ 2 - 0
server/model/request/jwt.go

@@ -9,7 +9,9 @@ import (
 type CustomClaims struct {
 	UUID        uuid.UUID
 	ID          uint
+	Username    string
 	NickName    string
 	AuthorityId string
+	BufferTime  int64
 	jwt.StandardClaims
 }

+ 4 - 0
server/service/exa_simple_uploader.go

@@ -55,6 +55,10 @@ func MergeFileMd5(md5 string, fileName string) (err error) {
 	//删除切片信息
 	err = tx.Delete(&model.ExaSimpleUploader{}, "identifier = ? AND is_done = ?", md5, false).Error
 	// 添加文件信息
+	if err != nil {
+		fmt.Println(err)
+		tx.Rollback()
+	}
 	err = tx.Create(&model.ExaSimpleUploader{
 		Identifier: md5,
 		IsDone:     true,

+ 7 - 4
server/service/jwt_black_list.go

@@ -3,6 +3,7 @@ package service
 import (
 	"gin-vue-admin/global"
 	"gin-vue-admin/model"
+	"time"
 )
 
 // @title    JsonInBlacklist
@@ -23,8 +24,8 @@ func JsonInBlacklist(jwtList model.JwtBlacklist) (err error) {
 // @param     jwtList         model.JwtBlacklist
 // @return    err             error
 
-func IsBlacklist(jwt string, jwtList model.JwtBlacklist) bool {
-	isNotFound := global.GVA_DB.Where("jwt = ?", jwt).First(&jwtList).RecordNotFound()
+func IsBlacklist(jwt string) bool {
+	isNotFound := global.GVA_DB.Where("jwt = ?", jwt).First(&model.JwtBlacklist{}).RecordNotFound()
 	return !isNotFound
 }
 
@@ -47,7 +48,9 @@ func GetRedisJWT(userName string) (err error, redisJWT string) {
 // @param     userName        string
 // @return    err             error
 
-func SetRedisJWT(jwtList model.JwtBlacklist, userName string) (err error) {
-	err = global.GVA_REDIS.Set(userName, jwtList.Jwt, 1000*1000*1000*60*60*24*7).Err()
+func SetRedisJWT(jwt string, userName string) (err error) {
+	// 此处过期时间等于jwt过期时间
+	timer := 60*60*24*7*time.Second
+	err = global.GVA_REDIS.Set(userName, jwt, timer).Err()
 	return err
 }

+ 1 - 1
server/service/sys_menu.go

@@ -158,7 +158,7 @@ func AddMenuAuthority(menus []model.SysBaseMenu, authorityId string) (err error)
 
 func GetMenuAuthority(authorityId string) (err error, menus []model.SysMenu) {
 	//sql := "SELECT authority_menu.keep_alive,authority_menu.default_menu,authority_menu.created_at,authority_menu.updated_at,authority_menu.deleted_at,authority_menu.menu_level,authority_menu.parent_id,authority_menu.path,authority_menu.`name`,authority_menu.hidden,authority_menu.component,authority_menu.title,authority_menu.icon,authority_menu.sort,authority_menu.menu_id,authority_menu.authority_id FROM authority_menu WHERE authority_menu.authority_id = ? ORDER BY authority_menu.sort ASC"
-	err = global.GVA_DB.Order("sort", true).Find(&menus).Error
+	err = global.GVA_DB.Where("authority_id = ? ", authorityId).Order("sort", true).Find(&menus).Error
 	//err = global.GVA_DB.Raw(sql, authorityId).Scan(&menus).Error
 	return err, menus
 }

+ 53 - 0
server/utils/upload_avatar_local.go

@@ -0,0 +1,53 @@
+package utils
+
+import (
+	"gin-vue-admin/global"
+	"io"
+	"mime/multipart"
+	"os"
+	"path"
+	"strings"
+	"time"
+)
+
+func UploadAvatarLocal(file *multipart.FileHeader) (err error, localPath string, key string) {
+	// 读取文件后缀
+	ext := path.Ext(file.Filename)
+	// 读取文件名并加密
+	fileName := strings.TrimSuffix(file.Filename, ext)
+	fileName = MD5V([]byte(fileName))
+	// 拼接新文件名
+	lastName := fileName + "_" + time.Now().Format("20060102150405") + ext
+	// 读取全局变量的定义路径
+	savePath := global.GVA_CONFIG.LocalUpload.AvatarPath
+	// 尝试创建此路径
+	err = os.MkdirAll(savePath, os.ModePerm)
+	if err != nil{
+		global.GVA_LOG.Error("upload local file fail:", err)
+		return err, "", ""
+	}
+	// 拼接路径和文件名
+	dst := savePath + "/" + lastName
+	// 下面为上传逻辑
+	// 打开文件 defer 关闭
+	src, err := file.Open()
+	if err != nil {
+		global.GVA_LOG.Error("upload local file fail:", err)
+		return err, "", ""
+	}
+	defer src.Close()
+	// 创建文件 defer 关闭
+	out, err := os.Create(dst)
+	if err != nil {
+		global.GVA_LOG.Error("upload local file fail:", err)
+		return err, "", ""
+	}
+	defer out.Close()
+	// 传输(拷贝)文件
+	_, err = io.Copy(out, src)
+	if err != nil {
+		global.GVA_LOG.Error("upload local file fail:", err)
+		return err, "", ""
+	}
+	return nil, dst, lastName
+}

+ 53 - 0
server/utils/upload_file_local.go

@@ -0,0 +1,53 @@
+package utils
+
+import (
+	"gin-vue-admin/global"
+	"io"
+	"mime/multipart"
+	"os"
+	"path"
+	"strings"
+	"time"
+)
+
+func UploadFileLocal(file *multipart.FileHeader) (err error, localPath string, key string) {
+	// 读取文件后缀
+	ext := path.Ext(file.Filename)
+	// 读取文件名并加密
+	fileName := strings.TrimSuffix(file.Filename, ext)
+	fileName = MD5V([]byte(fileName))
+	// 拼接新文件名
+	lastName := fileName + "_" + time.Now().Format("20060102150405") + ext
+	// 读取全局变量的定义路径
+	savePath := global.GVA_CONFIG.LocalUpload.FilePath
+	// 尝试创建此路径
+	err = os.MkdirAll(savePath, os.ModePerm)
+	if err != nil{
+		global.GVA_LOG.Error("upload local file fail:", err)
+		return err, "", ""
+	}
+	// 拼接路径和文件名
+	dst := savePath + "/" + lastName
+	// 下面为上传逻辑
+	// 打开文件 defer 关闭
+	src, err := file.Open()
+	if err != nil {
+		global.GVA_LOG.Error("upload local file fail:", err)
+		return err, "", ""
+	}
+	defer src.Close()
+	// 创建文件 defer 关闭
+	out, err := os.Create(dst)
+	if err != nil {
+		global.GVA_LOG.Error("upload local file fail:", err)
+		return err, "", ""
+	}
+	defer out.Close()
+	// 传输(拷贝)文件
+	_, err = io.Copy(out, src)
+	if err != nil {
+		global.GVA_LOG.Error("upload local file fail:", err)
+		return err, "", ""
+	}
+	return nil, dst, lastName
+}

+ 1 - 1
server/utils/upload.go → server/utils/upload_remote.go

@@ -11,7 +11,7 @@ import (
 )
 
 // 接收两个参数 一个文件流 一个 bucket 你的七牛云标准空间的名字
-func Upload(file *multipart.FileHeader) (err error, path string, key string) {
+func UploadRemote(file *multipart.FileHeader) (err error, path string, key string) {
 	putPolicy := storage.PutPolicy{
 		Scope: global.GVA_CONFIG.Qiniu.Bucket,
 	}

File diff suppressed because it is too large
+ 168 - 211
web/package-lock.json


+ 1 - 1
web/package.json

@@ -14,7 +14,7 @@
     "echarts": "^4.7.0",
     "element-ui": "^2.12.0",
     "mavon-editor": "^2.7.7",
-    "node-sass": "^4.12.0",
+    "node-sass": "^4.14.1",
     "path": "^0.12.7",
     "qs": "^6.8.0",
     "quill": "^1.3.7",

BIN
web/src/assets/noBody.png


+ 75 - 0
web/src/components/customPic/index.vue

@@ -0,0 +1,75 @@
+<template>
+    <span class="headerAvatar">
+        <template v-if="picType === 'avatar'">
+            <el-avatar :size="30" :src="avatar" v-if="userInfo.headerImg"></el-avatar>
+            <el-avatar :size="30" :src="require('@/assets/noBody.png')" v-else></el-avatar>
+        </template>
+        <template v-if="picType === 'img'">
+            <img :src="avatar" class="avatar" v-if="userInfo.headerImg" />
+            <img :src="require('@/assets/noBody.png')" class="avatar" v-else/>
+        </template>
+        <template v-if="picType === 'file'">
+            <img :src="file" class="file"/>
+        </template>
+    </span>
+</template>
+
+<script>
+import { mapGetters } from 'vuex'
+const path = process.env.VUE_APP_BASE_API
+export default {
+    name: "customPic",
+    props: {
+        picType: {
+            type: String,
+            required: false,
+            default: "avatar"
+        },
+        picSrc: {
+            type: String,
+            required: false,
+            default: ""
+        }
+    },
+    data(){
+        return{
+            path: path,
+        }
+    },
+    computed:{
+        ...mapGetters('user', ['userInfo']),
+        avatar(){
+            if(this.picSrc === ''){
+                if(this.userInfo.headerImg !== '' && this.userInfo.headerImg.slice(0, 4) === "http"){
+                    return this.userInfo.headerImg
+                }
+                return this.path + this.userInfo.headerImg
+            }else{
+                if(this.picSrc !== '' && this.picSrc.slice(0, 4) === "http"){
+                    return this.picSrc
+                }
+                return this.path + this.picSrc
+            }
+        },
+        file(){
+            if(this.picSrc && this.picSrc.slice(0, 4) !== "http"){
+                return this.path + this.picSrc
+            }
+            return this.picSrc
+        }
+    }
+}
+</script>
+
+<style scoped>
+.headerAvatar{
+    display: flex;
+    justify-content: center;
+    align-items: center;
+}
+.file{
+    width: 80px;
+    height: 80px;
+    position: relative;
+}
+</style>

+ 0 - 8
web/src/permission.js

@@ -7,14 +7,6 @@ const whiteList = ['login', 'register']
 
 router.beforeEach(async(to, from, next) => {
     const token = store.getters['user/token']
-        // if (token) {
-        //     const expiresAt = store.getters['user/expiresAt']
-        //     const nowUnix = new Date().getTime()
-        //     const hasExpires = (expiresAt - nowUnix) < 0
-        //     if (hasExpires) {
-        //         store.dispatch['user/claerAll']
-        //     }
-        // }
         // 在白名单中的判断情况
     if (whiteList.indexOf(to.name) > -1) {
         if (token) {

+ 1 - 10
web/src/store/module/user.js

@@ -11,7 +11,6 @@ export const user = {
             authority: "",
         },
         token: "",
-        expiresAt: ""
     },
     mutations: {
         setUserInfo(state, userInfo) {
@@ -22,14 +21,9 @@ export const user = {
             // 这里的 `state` 对象是模块的局部状态
             state.token = token
         },
-        setExpiresAt(state, expiresAt) {
-            // 这里的 `state` 对象是模块的局部状态
-            state.expiresAt = expiresAt
-        },
         LoginOut(state) {
             state.userInfo = {}
             state.token = ""
-            state.expiresAt = ""
             router.push({ name: 'login', replace: true })
             sessionStorage.clear()
             window.location.reload()
@@ -45,7 +39,6 @@ export const user = {
             const res = await login(loginInfo)
             commit('setUserInfo', res.data.user)
             commit('setToken', res.data.token)
-            commit('setExpiresAt', res.data.expiresAt)
             if (res.code == 0) {
                 const redirect = router.history.current.query.redirect
                 if (redirect) {
@@ -69,8 +62,6 @@ export const user = {
         token(state) {
             return state.token
         },
-        expiresAt(state) {
-            return state.expiresAt
-        }
+
     }
 }

+ 10 - 7
web/src/utils/request.js

@@ -21,13 +21,13 @@ const showLoading = () => {
 }
 
 const closeLoading = () => {
-    acitveAxios--
-    if (acitveAxios <= 0) {
-        clearTimeout(timer)
-        loadingInstance && loadingInstance.close()
+        acitveAxios--
+        if (acitveAxios <= 0) {
+            clearTimeout(timer)
+            loadingInstance && loadingInstance.close()
+        }
     }
-}
-//http request 拦截器
+    //http request 拦截器
 service.interceptors.request.use(
     config => {
         showLoading()
@@ -37,7 +37,7 @@ service.interceptors.request.use(
         config.headers = {
             'Content-Type': 'application/json',
             'x-token': token,
-            'x-user-id':user.ID
+            'x-user-id': user.ID
         }
         return config;
     },
@@ -57,6 +57,9 @@ service.interceptors.request.use(
 service.interceptors.response.use(
     response => {
         closeLoading()
+        if (response.headers["new-token"]) {
+            store.commit('user/setToken', response.headers["new-token"])
+        }
         if (response.data.code == 0 || response.headers.success === "true") {
             return response.data
         } else {

+ 5 - 6
web/src/view/example/upload/upload.vue

@@ -17,12 +17,7 @@
       <el-table :data="tableData" border stripe>
         <el-table-column label="预览" width="100">
           <template slot-scope="scope">
-            <img
-              :alt="scope.row.alt"
-              :src="scope.row.url"
-              height="80"
-              width="80"
-            />
+            <CustomPic picType="file" :picSrc="scope.row.url"/>
           </template>
         </el-table-column>
         <el-table-column label="日期" prop="UpdatedAt" width="180">
@@ -77,9 +72,13 @@ import infoList from "@/components/mixins/infoList";
 import { getFileList, deleteFile } from "@/api/fileUploadAndDownload";
 import { downloadImage } from "@/utils/downloadImg";
 import { formatTimeToStr } from "@/utils/data";
+import CustomPic from '@/components/customPic'
 export default {
   name: "Upload",
   mixins: [infoList],
+  components: {
+		CustomPic
+	},
   data() {
     return {
       fullscreenLoading: false,

+ 11 - 4
web/src/view/layout/index.vue

@@ -31,9 +31,9 @@
                 <Search />
                 <Screenfull class="screenfull"></Screenfull>
                 <el-dropdown>
-                  <span class="el-dropdown-link">
-                    <img :src="userInfo.headerImg" height="30" width="30" />
-                    {{userInfo.title}}
+                  <span class="header-avatar">
+                    欢迎您,<CustomPic/>
+                    <span style="margin-left: 5px">{{userInfo.nickName}}</span>
                     <i class="el-icon-arrow-down"></i>
                   </span>
                   <el-dropdown-menu class="dropdown-group" slot="dropdown">
@@ -95,6 +95,7 @@ import Search from '@/view/layout/search/search'
 import BottomInfo from '@/view/layout/bottomInfo/bottomInfo'
 import { mapGetters, mapActions } from 'vuex'
 import { changePassword } from '@/api/user'
+import CustomPic from '@/components/customPic'
 export default {
   name: 'Layout',
   data() {
@@ -138,7 +139,8 @@ export default {
     HistoryComponent,
     Screenfull,
     Search,
-    BottomInfo
+    BottomInfo,
+    CustomPic
   },
   methods: {
     ...mapActions('user', ['LoginOut']),
@@ -374,4 +376,9 @@ $mainHight: 100vh;
 .screenfull {
   display: inline-block;
 }
+.header-avatar{
+	display: flex;
+	justify-content: center;
+	align-items: center;
+}
 </style>

+ 5 - 2
web/src/view/person/person.vue

@@ -9,8 +9,7 @@
         class="avatar-uploader"
         name="headerImg"
       >
-        <img :src="userInfo.headerImg" class="avatar" v-if="userInfo.headerImg" />
-        <i class="el-icon-plus avatar-uploader-icon" v-else></i>
+        <CustomPic picType="img"/>
       </el-upload>
 
       <!-- <el-avatar :size="120" :src="userInfo.headerImg" shape="square"></el-avatar> -->
@@ -23,6 +22,7 @@
   </div>
 </template>
 <script>
+import CustomPic from '@/components/customPic'
 import { mapGetters, mapMutations } from 'vuex'
 const path = process.env.VUE_APP_BASE_API
 export default {
@@ -32,6 +32,9 @@ export default {
       path:path
     }
   },
+  components: {
+		CustomPic
+	},
   computed: {
     ...mapGetters('user', ['userInfo', 'token'])
   },

+ 5 - 1
web/src/view/superAdmin/user/user.vue

@@ -7,7 +7,7 @@
       <el-table-column label="头像" min-width="50">
         <template slot-scope="scope">
           <div :style="{'textAlign':'center'}">
-            <img :src="scope.row.headerImg" height="35" width="35" />
+            <CustomPic :picSrc="scope.row.headerImg"/>
           </div>
         </template>
       </el-table-column>
@@ -106,9 +106,13 @@ import {
 import { getAuthorityList } from "@/api/authority";
 import infoList from "@/components/mixins/infoList";
 import { mapGetters } from "vuex";
+import CustomPic from '@/components/customPic'
 export default {
   name: "Api",
   mixins: [infoList],
+  components: {
+		CustomPic
+	},
   data() {
     return {
       listApi: getUserList,

+ 114 - 103
web/src/view/systemTools/system/system.vue

@@ -1,106 +1,116 @@
 <template>
-  <div class="system">
-    <el-form :model="config" label-width="100px" ref="form" class="system">
-      <h2>系统配置</h2>
-      <el-form-item label="多点登录拦截">
-        <el-checkbox v-model="config.system.useMultipoint">开启</el-checkbox>
-      </el-form-item>
-      <el-form-item label="环境值">
-        <el-input v-model="config.system.env"></el-input>
-      </el-form-item>
-      <el-form-item label="端口值">
-        <el-input v-model.number="config.system.addr"></el-input>
-      </el-form-item>
-      <el-form-item label="数据库类型">
-        <el-select v-model="config.system.dbType">
-          <el-option value="sqlite"></el-option>
-          <el-option value="mysql"></el-option>
-        </el-select>
-      </el-form-item>
-      <h2>jwt签名</h2>
-      <el-form-item label="jwt签名">
-        <el-input v-model="config.jwt.signingKey"></el-input>
-      </el-form-item>
-      <h2>casbin配置</h2>
-      <el-form-item label="模型地址">
-        <el-input v-model="config.casbin.modelPath"></el-input>
-      </el-form-item>
-      <template v-show="config.system.dbType == 'mysql'">
-        <h2>mysql admin数据库配置</h2>
-        <el-form-item label="username">
-          <el-input v-model="config.mysql.username"></el-input>
-        </el-form-item>
-        <el-form-item label="password">
-          <el-input v-model="config.mysql.password"></el-input>
-        </el-form-item>
-        <el-form-item label="path">
-          <el-input v-model="config.mysql.path"></el-input>
-        </el-form-item>
-        <el-form-item label="dbname">
-          <el-input v-model="config.mysql.dbname"></el-input>
-        </el-form-item>
-        <el-form-item label="maxIdleConns">
-          <el-input v-model.number="config.mysql.maxIdleConns"></el-input>
-        </el-form-item>
-        <el-form-item label="maxOpenConns">
-          <el-input v-model.number="config.mysql.maxOpenConns"></el-input>
-        </el-form-item>
-        <el-form-item label="logMode">
-          <el-checkbox v-model="config.mysql.logMode"></el-checkbox>
-        </el-form-item>
-      </template>
-      <template v-show="config.system.dbType == 'sqlite'">
-        <h2>sqlite admin数据库配置</h2>
-        <el-form-item label="path">
-          <el-input v-model="config.sqlite.path"></el-input>
-        </el-form-item>
-        <el-form-item label="config">
-          <el-input v-model="config.sqlite.config"></el-input>
-        </el-form-item>
-        <el-form-item label="logMode">
-          <el-checkbox v-model="config.sqlite.logMode"></el-checkbox>
-        </el-form-item>
-      </template>
-      <h2>Redis admin数据库配置</h2>
-      <el-form-item label="addr">
-        <el-input v-model="config.redis.addr"></el-input>
-      </el-form-item>
-      <el-form-item label="password">
-        <el-input v-model="config.redis.password"></el-input>
-      </el-form-item>
-      <el-form-item label="db">
-        <el-input v-model="config.redis.db"></el-input>
-      </el-form-item>
-      <h2>七牛密钥配置</h2>
-      <el-form-item label="accessKey">
-        <el-input v-model="config.qiniu.accessKey"></el-input>
-      </el-form-item>
-      <el-form-item label="secretKey">
-        <el-input v-model="config.qiniu.secretKey"></el-input>
-      </el-form-item>
-      <h2>验证码配置</h2>
-      <el-form-item label="keyLong">
-        <el-input v-model.number="config.captcha.keyLong"></el-input>
-      </el-form-item>
-      <el-form-item label="imgWidth">
-        <el-input v-model.number="config.captcha.imgWidth"></el-input>
-      </el-form-item>
-      <el-form-item label="imgHeight">
-        <el-input v-model.number="config.captcha.imgHeight"></el-input>
-      </el-form-item>
-      <h2>日志配置</h2>
-      <el-form-item label="prefix">
-        <el-input v-model.number="config.log.prefix"></el-input>
-      </el-form-item>
-      <el-form-item label="logFile">
-        <el-checkbox v-model="config.log.logFile"></el-checkbox>
-      </el-form-item>
-      <el-form-item>
-        <el-button @click="update" type="primary">立即更新</el-button>
-        <el-button @click="reload" type="primary">重启服务(开发中)</el-button>
-      </el-form-item>
-    </el-form>
-  </div>
+	<div class="system">
+		<el-form :model="config" label-width="100px" ref="form" class="system">
+			<h2>系统配置</h2>
+			<el-form-item label="多点登录拦截">
+				<el-checkbox v-model="config.system.useMultipoint">开启</el-checkbox>
+			</el-form-item>
+			<el-form-item label="环境值">
+				<el-input v-model="config.system.env"></el-input>
+			</el-form-item>
+			<el-form-item label="端口值">
+				<el-input v-model.number="config.system.addr"></el-input>
+			</el-form-item>
+			<el-form-item label="数据库类型">
+				<el-select v-model="config.system.dbType">
+					<el-option value="sqlite"></el-option>
+					<el-option value="mysql"></el-option>
+				</el-select>
+			</el-form-item>
+			<h2>jwt签名</h2>
+			<el-form-item label="jwt签名">
+				<el-input v-model="config.jwt.signingKey"></el-input>
+			</el-form-item>
+			<h2>casbin配置</h2>
+			<el-form-item label="模型地址">
+				<el-input v-model="config.casbin.modelPath"></el-input>
+			</el-form-item>
+			<template v-show="config.system.dbType == 'mysql'">
+				<h2>mysql admin数据库配置</h2>
+				<el-form-item label="username">
+					<el-input v-model="config.mysql.username"></el-input>
+				</el-form-item>
+				<el-form-item label="password">
+					<el-input v-model="config.mysql.password"></el-input>
+				</el-form-item>
+				<el-form-item label="path">
+					<el-input v-model="config.mysql.path"></el-input>
+				</el-form-item>
+				<el-form-item label="dbname">
+					<el-input v-model="config.mysql.dbname"></el-input>
+				</el-form-item>
+				<el-form-item label="maxIdleConns">
+					<el-input v-model.number="config.mysql.maxIdleConns"></el-input>
+				</el-form-item>
+				<el-form-item label="maxOpenConns">
+					<el-input v-model.number="config.mysql.maxOpenConns"></el-input>
+				</el-form-item>
+				<el-form-item label="logMode">
+					<el-checkbox v-model="config.mysql.logMode"></el-checkbox>
+				</el-form-item>
+			</template>
+			<template v-show="config.system.dbType == 'sqlite'">
+				<h2>sqlite admin数据库配置</h2>
+				<el-form-item label="path">
+					<el-input v-model="config.sqlite.path"></el-input>
+				</el-form-item>
+				<el-form-item label="config">
+					<el-input v-model="config.sqlite.config"></el-input>
+				</el-form-item>
+				<el-form-item label="logMode">
+					<el-checkbox v-model="config.sqlite.logMode"></el-checkbox>
+				</el-form-item>
+			</template>
+			<h2>Redis admin数据库配置</h2>
+			<el-form-item label="addr">
+				<el-input v-model="config.redis.addr"></el-input>
+			</el-form-item>
+			<el-form-item label="password">
+				<el-input v-model="config.redis.password"></el-input>
+			</el-form-item>
+			<el-form-item label="db">
+				<el-input v-model="config.redis.db"></el-input>
+			</el-form-item>
+			<h2>上传配置</h2>
+				<el-form-item label="本地或七牛云">
+					<el-checkbox v-model="config.localUpload.local">本地</el-checkbox>
+				</el-form-item>
+				<el-form-item label="本地头像路径">
+					<el-input v-model="config.localUpload.avatarPath"></el-input>
+				</el-form-item>
+				<el-form-item label="本地文件路径">
+					<el-input v-model="config.localUpload.filePath"></el-input>
+				</el-form-item>
+			<h2>七牛密钥配置</h2>
+			<el-form-item label="accessKey">
+				<el-input v-model="config.qiniu.accessKey"></el-input>
+			</el-form-item>
+			<el-form-item label="secretKey">
+				<el-input v-model="config.qiniu.secretKey"></el-input>
+			</el-form-item>
+			<h2>验证码配置</h2>
+			<el-form-item label="keyLong">
+				<el-input v-model.number="config.captcha.keyLong"></el-input>
+			</el-form-item>
+			<el-form-item label="imgWidth">
+				<el-input v-model.number="config.captcha.imgWidth"></el-input>
+			</el-form-item>
+			<el-form-item label="imgHeight">
+				<el-input v-model.number="config.captcha.imgHeight"></el-input>
+			</el-form-item>
+			<h2>日志配置</h2>
+			<el-form-item label="prefix">
+				<el-input v-model.number="config.log.prefix"></el-input>
+			</el-form-item>
+			<el-form-item label="logFile">
+				<el-checkbox v-model="config.log.logFile"></el-checkbox>
+			</el-form-item>
+			<el-form-item>
+				<el-button @click="update" type="primary">立即更新</el-button>
+				<el-button @click="reload" type="primary">重启服务(开发中)</el-button>
+			</el-form-item>
+		</el-form>
+	</div>
 </template>
 
 <script>
@@ -118,7 +128,8 @@ export default {
         redis: {},
         qiniu: {},
         captcha: {},
-        log: {}
+		log: {},
+		localUpload: {}
       }
     };
   },

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