Przeglądaj źródła

Merge remote-tracking branch 'origin/master'

pixel 4 lat temu
rodzic
commit
b630738bf0

+ 19 - 19
.docker-compose/docker-entrypoint-initdb.d/init.sql

@@ -29,7 +29,7 @@ CREATE TABLE `casbin_rule` (
   `v3` varchar(100) DEFAULT NULL,
   `v4` varchar(100) DEFAULT NULL,
   `v5` varchar(100) DEFAULT NULL
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of casbin_rule
@@ -189,7 +189,7 @@ CREATE TABLE `exa_customers` (
   `sys_user_authority_id` varchar(191) DEFAULT NULL COMMENT '''管理角色ID''',
   PRIMARY KEY (`id`),
   KEY `idx_exa_customers_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of exa_customers
@@ -212,7 +212,7 @@ CREATE TABLE `exa_file_chunks` (
   `file_chunk_path` varchar(191) DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `idx_exa_file_chunks_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Table structure for exa_file_upload_and_downloads
@@ -229,7 +229,7 @@ CREATE TABLE `exa_file_upload_and_downloads` (
   `key` varchar(191) DEFAULT NULL COMMENT '''编号''',
   PRIMARY KEY (`id`),
   KEY `idx_exa_file_upload_and_downloads_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of exa_file_upload_and_downloads
@@ -255,7 +255,7 @@ CREATE TABLE `exa_files` (
   `is_finish` tinyint(1) DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `idx_exa_files_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Table structure for exa_simple_uploaders
@@ -271,7 +271,7 @@ CREATE TABLE `exa_simple_uploaders` (
   `total_chunks` varchar(191) DEFAULT NULL COMMENT '''切片总数''',
   `is_done` tinyint(1) DEFAULT NULL COMMENT '''是否上传完成''',
   `file_path` varchar(191) DEFAULT NULL COMMENT '''文件本地路径'''
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Table structure for jwt_blacklists
@@ -285,7 +285,7 @@ CREATE TABLE `jwt_blacklists` (
   `jwt` text COMMENT '''jwt''',
   PRIMARY KEY (`id`),
   KEY `idx_jwt_blacklists_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Table structure for sys_apis
@@ -302,7 +302,7 @@ CREATE TABLE `sys_apis` (
   `method` varchar(191) DEFAULT 'POST',
   PRIMARY KEY (`id`),
   KEY `idx_sys_apis_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=66 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of sys_apis
@@ -387,7 +387,7 @@ CREATE TABLE `sys_authorities` (
   `parent_id` varchar(191) DEFAULT NULL COMMENT '''父角色ID''',
   PRIMARY KEY (`authority_id`),
   UNIQUE KEY `authority_id` (`authority_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of sys_authorities
@@ -406,7 +406,7 @@ CREATE TABLE `sys_authority_menus` (
   `sys_base_menu_id` bigint unsigned NOT NULL,
   `sys_authority_authority_id` varchar(90) NOT NULL COMMENT '''角色ID''',
   PRIMARY KEY (`sys_base_menu_id`,`sys_authority_authority_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of sys_authority_menus
@@ -481,7 +481,7 @@ CREATE TABLE `sys_base_menu_parameters` (
   `value` varchar(191) DEFAULT NULL,
   PRIMARY KEY (`id`),
   KEY `idx_sys_base_menu_parameters_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Table structure for sys_base_menus
@@ -505,7 +505,7 @@ CREATE TABLE `sys_base_menus` (
   `icon` varchar(191) DEFAULT NULL COMMENT '''附加属性''',
   PRIMARY KEY (`id`),
   KEY `idx_sys_base_menus_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=27 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of sys_base_menus
@@ -547,7 +547,7 @@ CREATE TABLE `sys_data_authority_ids` (
   `sys_authority_authority_id` varchar(90) NOT NULL COMMENT '''角色ID''',
   `data_authority_id_authority_id` varchar(90) NOT NULL COMMENT '''角色ID''',
   PRIMARY KEY (`sys_authority_authority_id`,`data_authority_id_authority_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of sys_data_authority_ids
@@ -575,7 +575,7 @@ CREATE TABLE `sys_dictionaries` (
   `desc` varchar(191) DEFAULT NULL COMMENT '''描述''',
   PRIMARY KEY (`id`),
   KEY `idx_sys_dictionaries_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of sys_dictionaries
@@ -605,7 +605,7 @@ CREATE TABLE `sys_dictionary_details` (
   `sys_dictionary_id` bigint unsigned DEFAULT NULL COMMENT '''关联标记''',
   PRIMARY KEY (`id`),
   KEY `idx_sys_dictionary_details_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=24 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of sys_dictionary_details
@@ -657,7 +657,7 @@ CREATE TABLE `sys_operation_records` (
   `user_id` bigint unsigned DEFAULT NULL COMMENT '''''',
   PRIMARY KEY (`id`),
   KEY `idx_sys_operation_records_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Table structure for sys_users
@@ -676,7 +676,7 @@ CREATE TABLE `sys_users` (
   `authority_id` varchar(191) DEFAULT '888' COMMENT '''用户角色ID''',
   PRIMARY KEY (`id`),
   KEY `idx_sys_users_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Records of sys_users
@@ -703,7 +703,7 @@ CREATE TABLE `sys_workflow_step_infos` (
   `is_end` tinyint(1) DEFAULT NULL COMMENT '''是否是完结流节点''',
   PRIMARY KEY (`id`),
   KEY `idx_sys_workflow_step_infos_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- Table structure for sys_workflows
@@ -719,7 +719,7 @@ CREATE TABLE `sys_workflows` (
   `workflow_description` varchar(191) DEFAULT NULL COMMENT '''工作流描述''',
   PRIMARY KEY (`id`),
   KEY `idx_sys_workflows_deleted_at` (`deleted_at`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
 
 -- ----------------------------
 -- View structure for authority_menu

+ 13 - 13
.docker-compose/shell/server-handle.sh

@@ -69,25 +69,25 @@ captcha:
 # zap logger configuration
 zap:
   # 可使用 "debug", "info", "warn", "error", "dpanic", "panic", "fatal",
-  level: 'debug'
+  level: 'info'
   # console: 控制台, json: json格式输出
   format: 'console'
   prefix: '[GIN-VUE-ADMIN]'
   director: 'log'
-  link_name: 'latest_log'
-  show_line: true
+  link-name: 'latest_log'
+  show-line: true
   # LowercaseLevelEncoder:小写, LowercaseColorLevelEncoder:小写带颜色,CapitalLevelEncoder: 大写, CapitalColorLevelEncoder: 大写带颜色,
-  encode_level: 'LowercaseColorLevelEncoder'
-  stacktrace_key: 'stacktrace'
-  log_in_console: true
+  encode-level: 'LowercaseColorLevelEncoder'
+  stacktrace-key: 'stacktrace'
+  log-in-console: true
 
 email:
-  email_from: '[email protected]'
-  email_nick_name: 'test'
-  email_secret: 'xxx'
-  email_to: '[email protected]'
-  email_host: 'smtp.163.com'
-  email_port: 465
-  email_isSSL: true
+  email-from: '[email protected]'
+  email-nickname: 'test'
+  email-secret: 'xxx'
+  email-to: '[email protected]'
+  email-host: 'smtp.163.com'
+  email-port: 465
+  email-isSSL: true
 EOF
 

+ 51 - 6
README-en.md

@@ -133,6 +133,14 @@ We are excited that you are interested in contributing to gin-vue-admin. Before
 
     - If the subnet is modified, the ipv4_address of each service needs to be modified, and the ip of the server on line 20 of [.docker-compose/nginx/conf.d/my.conf](.docker-compose/nginx/conf.d/my.conf) also needs to be modified
 
+> <font color=red>**Use docker-compose to deploy this project need attention**</font>
+
+- For mysql database, please use a local database installed on the server disk.
+	- Avoid using mysql in the docker container, there may be write problems, io is lower than the host machine, docker's persistence mechanism problem
+- [init.sql](.docker-compose/docker-entrypoint-initdb.d/init.sql) is for docker-compose ==experience this project==, prohibit the use of [init.sql](.docker-compose/docker-entrypoint-initdb.d/init.sql) to initialize project data, Database initialization[Please use this method](https://www.gin-vue-admin.com/docs/help#step1%EF%BC%9A%E6%95%B0%E6%8D%AE%E5%BA%93%E5%88%9D%E5%A7%8B%E5%8C%96)
+	- Use [init.sql](.docker-compose/docker-entrypoint-initdb.d/init.sql) to initialize all problems, please bear it yourself, and have nothing to do with this project
+- When deploying using docker-compose of this project,Please modify the [nginx configuration](.docker-compose/nginx/conf.d/my.conf), mysql configuration, networks configuration, redis configuration corresponding to [docker-compose.yaml](./docker-compose.yaml), and make changes as needed.
+
 ### 2.1 Web
 
 ```bash
@@ -161,6 +169,47 @@ go list (go mod tidy)
 go build
 ```
 
+> Zap log library usage guide && configuration guide
+
+The configuration of the Zap log library selects zap under [config.yaml](./server/config.yaml)
+
+```yaml
+# zap logger configuration
+zap:
+  level: 'debug'
+  format: 'console'
+  prefix: '[GIN-VUE-ADMIN]'
+  director: 'log'
+  link_name: 'latest_log'
+  show_line: true
+  encode_level: 'LowercaseColorLevelEncoder'
+  stacktrace_key: 'stacktrace'
+  log_in_console: true
+```
+
+| Configuration Name | Type Of Configuration | Description                                                  |
+| ------------------ | --------------------- | ------------------------------------------------------------ |
+| level              | string                | For a detailed description of the level mode, please see the official [zap documentation](https://pkg.go.dev/go.uber.org/zap?tab=doc#pkg-constants) <br />info: info mode, stack information without errors, only output information<br />debug: debug mode, stack details with errors<br />warn:warn mode<br />error: error mode, stack details with error<br />dpanic: dpanic mode<br />panic: panic mode<br />fatal: fatal mode<br /> |
+| format             | string                | console: Output log in console format<br />json: json format output log |
+| prefix             | string                | Log prefix                                                   |
+| director           | string                | The folder to store the log can be modified, no need to create it manually |
+| link_name          | string                | [A soft connection file](https://baike.baidu.com/item/%E8%BD%AF%E9%93%BE%E6%8E%A5) of link_name will be generated in the server directory, and the link is the latest log file of the director configuration item |
+| show_line          | bool                  | Display the line number, the default is true, it is not recommended to modify |
+| encode_level       | string                | LowercaseLevelEncoder: lowercase<br /> LowercaseColorLevelEncoder: lowercase with color<br />CapitalLevelEncoder: uppercase<br />CapitalColorLevelEncoder: uppercase with color |
+| stacktrace_key     | string                | The name of the stack, that is, the key of josn when outputting the log in json format |
+| log_in_console     | bool                  | Whether to output to the console, the default is true        |
+
+- Development environment || Debug environment configuration recommendations
+	- `level:debug`
+	- `format:console`
+	- `encode_level:LowercaseColorLevelEncoder`或者`encode_leve:CapitalColorLevelEncoder`
+- Deployment environment configuration recommendations
+	- `level:error`
+	- `format:json` 
+	- `encode_level: LowercaseLevelEncoder `或者 `encode_level:CapitalLevelEncoder`
+	- `log_in_console: false` 
+- <font color=red>Suggestions are only suggestions, you can proceed according to your own needs, and suggestions are for reference only</font>
+
 ### 2.3 API docs auto-generation using swagger
 
 #### 2.3.1 install swagger 
@@ -175,7 +224,6 @@ go get -u github.com/swaggo/swag/cmd/swag
 In mainland China, access to go.org/x is prohibited,we recommend [goproxy.io](https://goproxy.io/zh/)
 
 ````bash
-
 If you are using Go version 1.13 and above (recommended)
 # Enable Go Modules function
 go env -w GO111MODULE=on 
@@ -185,11 +233,8 @@ If you are using Go version 1.12 and below
 go env -w GO111MODULE=on
 go env -w GOPROXY=https://goproxy.io
 
-# get swag
-go get -g -v github.com/swaggo/swag/cmd/swag
-
-# cd GOPATH/src/github.com/swaggo/swag/cmd/swag
-go install
+# Use the following command to download swag
+go get -u github.com/swaggo/swag/cmd/swag
 ````
 
 #### 2.3.2 API docs generation

+ 51 - 5
README.md

@@ -129,6 +129,14 @@ Gin-vue-admin 的成长离不开大家的支持,如果你愿意为 gin-vue-adm
 
 	- 如果修改了子网,对应的每个service的ipv4_address都需要修改,还有[.docker-compose/nginx/conf.d/my.conf](./.docker-compose/nginx/conf.d/my.conf)的第20行的server的ip也需要修改
 
+> <font color=red>**使用docker-compose进行部署本项目需注意的问题**</font>
+
+- mysql数据库请使用装在服务器磁盘的本地数据库.
+	- 避免使用docker容器内的mysql,可能会出现写入的问题, io比宿主机低  docker的持久化机制问题
+- [init.sql](.docker-compose/docker-entrypoint-initdb.d/init.sql)是给docker-compose进行<font color=red>体验本项目</font>的, 禁止[init.sql](.docker-compose/docker-entrypoint-initdb.d/init.sql)使用进行项目数据的初始化, 数据库初始化[请使用此方法](https://www.gin-vue-admin.com/docs/help#step1%EF%BC%9A%E6%95%B0%E6%8D%AE%E5%BA%93%E5%88%9D%E5%A7%8B%E5%8C%96)
+	- 使用[init.sql](.docker-compose/docker-entrypoint-initdb.d/init.sql)进行初始化出现的所有问题,请自行承担,与本项目无关
+- 使用本项目的docker-compose进行部署时,请修改[docker-compose.yaml](./docker-compose.yaml)对应的[nginx配置](.docker-compose/nginx/conf.d/my.conf),mysql配置,networks配置,redis配置,按需自行更改.
+
 ### 2.1 web端
 
 ```bash
@@ -157,6 +165,47 @@ go list (go mod tidy)
 go build
 ```
 
+> Zap日志库使用指南&&配置指南
+
+Zap日志库的配置选择在[config.yaml](./server/config.yaml)下的zap
+
+```yaml
+# zap logger configuration
+zap:
+  level: 'debug'
+  format: 'console'
+  prefix: '[GIN-VUE-ADMIN]'
+  director: 'log'
+  link_name: 'latest_log'
+  show_line: true
+  encode_level: 'LowercaseColorLevelEncoder'
+  stacktrace_key: 'stacktrace'
+  log_in_console: true
+```
+
+| 配置名         | 配置的类型 | 说明                                                         |
+| -------------- | ---------- | ------------------------------------------------------------ |
+| level          | string     | level的模式的详细说明,请看[zap官方文档](https://pkg.go.dev/go.uber.org/zap?tab=doc#pkg-constants) <br />info: info模式,无错误的堆栈信息,只输出信息<br />debug:debug模式,有错误的堆栈详细信息<br />warn:warn模式<br />error: error模式,有错误的堆栈详细信息<br />dpanic: dpanic模式<br />panic: panic模式<br />fatal: fatal模式<br /> |
+| format         | string     | console: 控制台形式输出日志<br />json: json格式输出日志      |
+| prefix         | string     | 日志的前缀                                                   |
+| director       | string     | 存放日志的文件夹,修改即可,不需要手动创建                     |
+| link_name      | string     | 在server目录下会生成一个link_name的[软连接文件](https://baike.baidu.com/item/%E8%BD%AF%E9%93%BE%E6%8E%A5),链接的是director配置项的最新日志文件 |
+| show_line      | bool       | 显示行号, 默认为true,不建议修改                              |
+| encode_level   | string     | LowercaseLevelEncoder:小写<br /> LowercaseColorLevelEncoder:小写带颜色<br />CapitalLevelEncoder: 大写<br />CapitalColorLevelEncoder: 大写带颜色 |
+| stacktrace_key | string     | 堆栈的名称,即在json格式输出日志时的josn的key                 |
+| log_in_console | bool       | 是否输出到控制台,默认为true                                  |
+
+- 开发环境 || 调试环境配置建议
+	- `level:debug`
+	- `format:console`
+	- `encode_level:LowercaseColorLevelEncoder`或者`encode_leve:CapitalColorLevelEncoder`
+- 部署环境配置建议
+	- `level:error`
+	- `format:json` 
+	- `encode_level: LowercaseLevelEncoder `或者 `encode_level:CapitalLevelEncoder`
+	- `log_in_console: false` 
+- <font color=red>建议只是建议,按照自己的需求进行即可,给出建议仅供参考</font>
+
 ### 2.3 swagger自动化API文档
 
 #### 2.3.1 安装 swagger
@@ -177,11 +226,8 @@ go env -w GO111MODULE=on
 # 配置 GOPROXY 环境变量
 go env -w GOPROXY=https://goproxy.io,direct
 
-# 执行
-go get -g -v github.com/swaggo/swag/cmd/swag
-
-# 到GOPATH的/src/github.com/swaggo/swag/cmd/swag路径下执行
-go install
+# 使用如下命令下载swag
+go get -u github.com/swaggo/swag/cmd/swag
 ```
 
 #### 2.3.2 生成API文档

+ 13 - 20
server/config.yaml

@@ -84,33 +84,26 @@ captcha:
   img-width: 240
   img-height: 80
 
-# logger configuration
-log:
-  prefix: '[GIN-VUE-ADMIN]'
-  log-file: true
-  stdout: 'DEBUG'
-  file: 'DEBUG'
-
 # zap logger configuration
 zap:
   # 可使用 "debug", "info", "warn", "error", "dpanic", "panic", "fatal",
-  level: 'debug'
+  level: 'info'
   # console: 控制台, json: json格式输出
   format: 'console'
   prefix: '[GIN-VUE-ADMIN]'
   director: 'log'
-  link_name: 'latest_log'
-  show_line: true
+  link-name: 'latest_log'
+  show-line: true
   # LowercaseLevelEncoder:小写, LowercaseColorLevelEncoder:小写带颜色,CapitalLevelEncoder: 大写, CapitalColorLevelEncoder: 大写带颜色,
-  encode_level: 'LowercaseColorLevelEncoder'
-  stacktrace_key: 'stacktrace'
-  log_in_console: true
+  encode-level: 'LowercaseColorLevelEncoder'
+  stacktrace-key: 'stacktrace'
+  log-in-console: true
 
 email:
-  email_from: '[email protected]'
-  email_nick_name: 'test'
-  email_secret: 'xxx'
-  email_to: '[email protected]'
-  email_host: 'smtp.163.com'
-  email_port: 465
-  email_isSSL: true
+  email-from: '[email protected]'
+  email-nickname: 'test'
+  email-secret: 'xxx'
+  email-to: '[email protected]'
+  email-host: 'smtp.163.com'
+  email-port: 465
+  email-isSSL: true

+ 14 - 14
server/config/config.go

@@ -79,8 +79,8 @@ type Redis struct {
 }
 
 type LocalUpload struct {
-	Local      bool   `mapstructure:"local" json:"local" yaml:"local"`
-	FilePath   string `mapstructure:"file-path" json:"filePath" yaml:"file-path"`
+	Local    bool   `mapstructure:"local" json:"local" yaml:"local"`
+	FilePath string `mapstructure:"file-path" json:"filePath" yaml:"file-path"`
 }
 
 type Qiniu struct {
@@ -101,19 +101,19 @@ type Zap struct {
 	Format        string `mapstructure:"format" json:"format" yaml:"format"`
 	Prefix        string `mapstructure:"prefix" json:"prefix" yaml:"prefix"`
 	Director      string `mapstructure:"director" json:"director"  yaml:"director"`
-	LinkName      string `mapstructure:"link_name" json:"linkName" yaml:"link_name"`
-	ShowLine      bool   `mapstructure:"show_line" json:"showLine" yaml:"showLine"`
-	EncodeLevel   string `mapstructure:"encode_level" json:"encodeLevel" yaml:"encode_level"`
-	StacktraceKey string `mapstructure:"stacktrace_key" json:"stacktraceKey" yaml:"stacktrace_key"`
-	LogInConsole  bool   `mapstructure:"log_in_console" json:"logInConsole" yaml:"log_in_console"`
+	LinkName      string `mapstructure:"link-name" json:"linkName" yaml:"link-name"`
+	ShowLine      bool   `mapstructure:"show-line" json:"showLine" yaml:"showLine"`
+	EncodeLevel   string `mapstructure:"encode-level" json:"encodeLevel" yaml:"encode-level"`
+	StacktraceKey string `mapstructure:"stacktrace-key" json:"stacktraceKey" yaml:"stacktrace-key"`
+	LogInConsole  bool   `mapstructure:"log-in-console" json:"logInConsole" yaml:"log-in-console"`
 }
 
 type Email struct {
-	EmailFrom         string `mapstructure:"email_from" json:"emailFrom" yaml:"email_from"`
-	EmailNickName         string `mapstructure:"email_nick_name" json:"emailNickName" yaml:"email_nick_name"`
-	EmailSecret         string `mapstructure:"email_secret" json:"emailSecret" yaml:"email_secret"`
-	EmailTo         string `mapstructure:"email_to" json:"emailTo" yaml:"email_to"`
-	EmailHost         string `mapstructure:"email_host" json:"emailHost" yaml:"email_host"`
-	EmailPort         int `mapstructure:"email_port" json:"emailPort" yaml:"email_port"`
-	EmailIsSSL         bool `mapstructure:"email_isSSL" json:"emailIsSSL" yaml:"email_isSSL"`
+	EmailFrom     string `mapstructure:"email-from" json:"emailFrom" yaml:"email-from"`
+	EmailNickname string `mapstructure:"email-nickname" json:"emailNickname" yaml:"email-nickname"`
+	EmailSecret   string `mapstructure:"email-secret" json:"emailSecret" yaml:"email-secret"`
+	EmailTo       string `mapstructure:"email-to" json:"emailTo" yaml:"email-to"`
+	EmailHost     string `mapstructure:"email-host" json:"emailHost" yaml:"email-host"`
+	EmailPort     int    `mapstructure:"email-port" json:"emailPort" yaml:"email-port"`
+	EmailIsSSL    bool   `mapstructure:"email-is-ssl" json:"emailIsSSL" yaml:"email-is-ssl"`
 }

+ 15 - 1
server/core/config.go

@@ -6,13 +6,27 @@ import (
 	_ "gin-vue-admin/packfile"
 	"github.com/fsnotify/fsnotify"
 	"github.com/spf13/viper"
+	"github.com/spf13/pflag"
 )
 
 const defaultConfigFile = "config.yaml"
 
 func init() {
+	pflag.StringP("configFile","c", "", "choose config file.")
+	pflag.Parse()
+
+	// 优先级: 命令行 > 环境变量 > 默认值
 	v := viper.New()
-	v.SetConfigFile(defaultConfigFile)
+	v.BindPFlags(pflag.CommandLine)
+	v.SetEnvPrefix("gva")
+	v.BindEnv("configFile") // GVA_CONFIGFILE
+
+	configFile := v.GetString("configFile")
+	if configFile == ""{
+		configFile = defaultConfigFile
+	}
+
+	v.SetConfigFile(configFile)
 	err := v.ReadInConfig()
 	if err != nil {
 		panic(fmt.Errorf("Fatal error config file: %s \n", err))

+ 1 - 1
server/core/server.go

@@ -25,7 +25,7 @@ func RunWindowsServer() {
 	// 保证文本顺序输出
 	// In order to ensure that the text order output can be deleted
 	time.Sleep(10 * time.Microsecond)
-	global.GVA_LOG.Debug("server run success on ", zap.String("address", address))
+	global.GVA_LOG.Info("server run success on ", zap.String("address", address))
 
 	fmt.Printf(`欢迎使用 Gin-Vue-Admin
 	默认自动化文档地址:http://127.0.0.1%s/swagger/index.html

+ 5 - 15
server/core/zap.go

@@ -82,30 +82,20 @@ func getEncoderConfig() (config zapcore.EncoderConfig) {
 		CallerKey:      "caller",
 		StacktraceKey:  global.GVA_CONFIG.Zap.StacktraceKey,
 		LineEnding:     zapcore.DefaultLineEnding,
-		EncodeLevel:    zapcore.CapitalLevelEncoder,
+		EncodeLevel:    zapcore.LowercaseLevelEncoder,
 		EncodeTime:     CustomTimeEncoder,
 		EncodeDuration: zapcore.SecondsDurationEncoder,
 		EncodeCaller:   zapcore.FullCallerEncoder,
 	}
 	switch  {
-	case global.GVA_CONFIG.Zap.EncodeLevel == "LowercaseLevelEncoder" && global.GVA_CONFIG.Zap.Format == "console" : // console小写编码器
+	case global.GVA_CONFIG.Zap.EncodeLevel == "LowercaseLevelEncoder": // 小写编码器(默认)
 		config.EncodeLevel = zapcore.LowercaseLevelEncoder
-	case global.GVA_CONFIG.Zap.EncodeLevel == "LowercaseLevelEncoder" && global.GVA_CONFIG.Zap.Format == "json" : // json小写编码器
-		config.EncodeLevel = zapcore.LowercaseLevelEncoder
-	case global.GVA_CONFIG.Zap.EncodeLevel == "LowercaseColorLevelEncoder" && global.GVA_CONFIG.Zap.Format == "console": // console小写编码器带颜色
-		config.EncodeLevel = zapcore.LowercaseColorLevelEncoder
-	case global.GVA_CONFIG.Zap.EncodeLevel == "LowercaseColorLevelEncoder" && global.GVA_CONFIG.Zap.Format == "json": // json小写编码器带颜色
+	case global.GVA_CONFIG.Zap.EncodeLevel == "LowercaseColorLevelEncoder": // 小写编码器带颜色
 		config.EncodeLevel = zapcore.LowercaseColorLevelEncoder
-	case global.GVA_CONFIG.Zap.EncodeLevel == "CapitalLevelEncoder" && global.GVA_CONFIG.Zap.Format == "console": // console大写编码器
-		config.EncodeLevel = zapcore.CapitalLevelEncoder
-	case global.GVA_CONFIG.Zap.EncodeLevel == "CapitalLevelEncoder" && global.GVA_CONFIG.Zap.Format == "json": // json大写编码器
+	case global.GVA_CONFIG.Zap.EncodeLevel == "CapitalLevelEncoder": // 大写编码器
 		config.EncodeLevel = zapcore.CapitalLevelEncoder
-	case global.GVA_CONFIG.Zap.EncodeLevel == "CapitalColorLevelEncoder" && global.GVA_CONFIG.Zap.Format == "console": // console 大写编码器带颜色
+	case global.GVA_CONFIG.Zap.EncodeLevel == "CapitalColorLevelEncoder": // 大写编码器带颜色
 		config.EncodeLevel = zapcore.CapitalColorLevelEncoder
-	case global.GVA_CONFIG.Zap.EncodeLevel == "CapitalColorLevelEncoder" && global.GVA_CONFIG.Zap.Format == "json": // json 大写编码器带颜色
-		config.EncodeLevel = zapcore.CapitalColorLevelEncoder
-	default:
-		config.EncodeLevel = zapcore.LowercaseLevelEncoder
 	}
 	return config
 }

+ 1 - 1
server/go.mod

@@ -35,7 +35,7 @@ require (
 	github.com/spf13/afero v1.2.2 // indirect
 	github.com/spf13/cast v1.3.1 // indirect
 	github.com/spf13/jwalterweatherman v1.1.0 // indirect
-	github.com/spf13/pflag v1.0.5 // indirect
+	github.com/spf13/pflag v1.0.5
 	github.com/spf13/viper v1.6.2
 	github.com/swaggo/gin-swagger v1.2.0
 	github.com/swaggo/swag v1.6.7

+ 1 - 1
server/gva/init_data/init_data.go

@@ -481,5 +481,5 @@ func InitData() {
 	if err != nil {
 		global.GVA_LOG.Error("initialize data failed", zap.Any("err", err))
 	}
-	global.GVA_LOG.Debug("initialize data success")
+	global.GVA_LOG.Info("initialize data success")
 }

+ 1 - 1
server/initialize/gorm.go

@@ -52,7 +52,7 @@ func GormDBTables(db *gorm.DB) {
 		global.GVA_LOG.Error("register table failed", zap.Any("err", err))
 		os.Exit(0)
 	}
-	global.GVA_LOG.Debug("register table success")
+	global.GVA_LOG.Info("register table success")
 }
 
 // GormMysql 初始化Mysql数据库

+ 3 - 3
server/initialize/router.go

@@ -18,12 +18,12 @@ func Routers() *gin.Engine {
 	// 为用户头像和文件提供静态地址
 	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")
+	global.GVA_LOG.Info("use middleware logger")
 	// 跨域
 	Router.Use(middleware.Cors())
-	global.GVA_LOG.Debug("use middleware cors")
+	global.GVA_LOG.Info("use middleware cors")
 	Router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler))
-	global.GVA_LOG.Debug("register swagger handler")
+	global.GVA_LOG.Info("register swagger handler")
 	// 方便统一添加路由组前缀 多服务器上线使用
 	ApiGroup := Router.Group("")
 	router.InitUserRouter(ApiGroup)                  // 注册用户路由

+ 2 - 1
server/middleware/cors.go

@@ -9,7 +9,8 @@ import (
 func Cors() gin.HandlerFunc {
 	return func(c *gin.Context) {
 		method := c.Request.Method
-		c.Header("Access-Control-Allow-Origin", "*")
+		origin := c.Request.Header.Get("Origin")
+		c.Header("Access-Control-Allow-Origin", origin)
 		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")

+ 5 - 5
server/model/exa_customer.go

@@ -6,9 +6,9 @@ import (
 
 type ExaCustomer struct {
 	gorm.Model
-	CustomerName       string  `json:"customerName" form:"customerName" gorm:"comment:'客户名'"`
-	CustomerPhoneData  string  `json:"customerPhoneData" form:"customerPhoneData" gorm:"comment:'客户手机号'"`
-	SysUserID          uint    `json:"sysUserId" form:"sysUserId" gorm:"comment:'管理ID'"`
-	SysUserAuthorityID string  `json:"sysUserAuthorityID" form:"sysUserAuthorityID" gorm:"comment:'管理角色ID'"`
-	SysUser            SysUser `json:"sysUser" form:"sysUser" gorm:"comment:'管理详情'"`
+	CustomerName       string  `json:"customerName" form:"customerName" gorm:"comment:客户名"`
+	CustomerPhoneData  string  `json:"customerPhoneData" form:"customerPhoneData" gorm:"comment:客户手机号"`
+	SysUserID          uint    `json:"sysUserId" form:"sysUserId" gorm:"comment:管理ID"`
+	SysUserAuthorityID string  `json:"sysUserAuthorityID" form:"sysUserAuthorityID" gorm:"comment:管理角色ID"`
+	SysUser            SysUser `json:"sysUser" form:"sysUser" gorm:"comment:管理详情"`
 }

+ 4 - 4
server/model/exa_file_upload_download.go

@@ -6,8 +6,8 @@ import (
 
 type ExaFileUploadAndDownload struct {
 	gorm.Model
-	Name string `json:"name" gorm:"comment:'文件名'"`
-	Url  string `json:"url" gorm:"comment:'文件地址'"`
-	Tag  string `json:"tag" gorm:"comment:'文件标签'"`
-	Key  string `json:"key" gorm:"comment:'编号'"`
+	Name string `json:"name" gorm:"comment:文件名"`
+	Url  string `json:"url" gorm:"comment:文件地址"`
+	Tag  string `json:"tag" gorm:"comment:文件标签"`
+	Key  string `json:"key" gorm:"comment:编号"`
 }

+ 9 - 9
server/model/exa_simple_uploader.go

@@ -1,13 +1,13 @@
 package model
 
 type ExaSimpleUploader struct {
-	ChunkNumber      string `json:"chunkNumber" gorm:"comment:'当前切片标记'"`
-	CurrentChunkSize string `json:"currentChunkSize" gorm:"comment:'当前切片容量'"`
-	CurrentChunkPath string `json:"currentChunkPath" gorm:"comment:'切片本地路径'"`
-	TotalSize        string `json:"totalSize" gorm:"comment:'总容量'"`
-	Identifier       string `json:"identifier" gorm:"comment:'文件标识(md5)'"`
-	Filename         string `json:"filename" gorm:"comment:'文件名'"`
-	TotalChunks      string `json:"totalChunks" gorm:"comment:'切片总数'"`
-	IsDone           bool   `json:"isDone" gorm:"comment:'是否上传完成'"`
-	FilePath         string `json:"filePath" gorm:"comment:'文件本地路径'"`
+	ChunkNumber      string `json:"chunkNumber" gorm:"comment:当前切片标记"`
+	CurrentChunkSize string `json:"currentChunkSize" gorm:"comment:当前切片容量"`
+	CurrentChunkPath string `json:"currentChunkPath" gorm:"comment:切片本地路径"`
+	TotalSize        string `json:"totalSize" gorm:"comment:总容量"`
+	Identifier       string `json:"identifier" gorm:"comment:文件标识(md5)"`
+	Filename         string `json:"filename" gorm:"comment:文件名"`
+	TotalChunks      string `json:"totalChunks" gorm:"comment:切片总数"`
+	IsDone           bool   `json:"isDone" gorm:"comment:是否上传完成"`
+	FilePath         string `json:"filePath" gorm:"comment:文件本地路径"`
 }

+ 4 - 4
server/model/sys_api.go

@@ -6,8 +6,8 @@ import (
 
 type SysApi struct {
 	gorm.Model
-	Path        string `json:"path" gorm:"comment:'api路径'"`
-	Description string `json:"description" gorm:"comment:'api中文描述'"`
-	ApiGroup    string `json:"apiGroup" gorm:"comment:'api组'"`
-	Method      string `json:"method" gorm:"default:'POST'" gorm:"comment:'方法'"`
+	Path        string `json:"path" gorm:"comment:api路径"`
+	Description string `json:"description" gorm:"comment:api中文描述"`
+	ApiGroup    string `json:"apiGroup" gorm:"comment:api组"`
+	Method      string `json:"method" gorm:"default:POST" gorm:"comment:方法"`
 }

+ 3 - 3
server/model/sys_authority.go

@@ -8,9 +8,9 @@ type SysAuthority struct {
 	CreatedAt       time.Time
 	UpdatedAt       time.Time
 	DeletedAt       *time.Time     `sql:"index"`
-	AuthorityId     string         `json:"authorityId" gorm:"not null;unique;primary_key;comment:'角色ID';size:90"`
-	AuthorityName   string         `json:"authorityName" gorm:"comment:'角色名'"`
-	ParentId        string         `json:"parentId" gorm:"comment:'父角色ID'"`
+	AuthorityId     string         `json:"authorityId" gorm:"not null;unique;primary_key;comment:角色ID;size:90"`
+	AuthorityName   string         `json:"authorityName" gorm:"comment:角色名"`
+	ParentId        string         `json:"parentId" gorm:"comment:父角色ID"`
 	DataAuthorityId []SysAuthority `json:"dataAuthorityId" gorm:"many2many:sys_data_authority_id"`
 	Children        []SysAuthority `json:"children" gorm:"-"`
 	SysBaseMenus    []SysBaseMenu  `json:"menus" gorm:"many2many:sys_authority_menus;"`

+ 2 - 2
server/model/sys_authority_menu.go

@@ -2,8 +2,8 @@ package model
 
 type SysMenu struct {
 	SysBaseMenu
-	MenuId      string                 `json:"menuId" gorm:"comment:'菜单ID'"`
-	AuthorityId string                 `json:"-" gorm:"comment:'角色ID'"`
+	MenuId      string                 `json:"menuId" gorm:"comment:菜单ID"`
+	AuthorityId string                 `json:"-" gorm:"comment:角色ID"`
 	Children    []SysMenu              `json:"children" gorm:"-"`
 	Parameters  []SysBaseMenuParameter `json:"parameters" gorm:"foreignKey:SysBaseMenuID;references:MenuId"`
 }

+ 11 - 11
server/model/sys_base_menu.go

@@ -7,23 +7,23 @@ import (
 type SysBaseMenu struct {
 	gorm.Model
 	MenuLevel     uint   `json:"-"`
-	ParentId      string `json:"parentId" gorm:"comment:'父菜单ID'"`
-	Path          string `json:"path" gorm:"comment:'路由path'"`
-	Name          string `json:"name" gorm:"comment:'路由name'"`
-	Hidden        bool   `json:"hidden" gorm:"comment:'是否在列表隐藏'"`
-	Component     string `json:"component" gorm:"comment:'对应前端文件路径'"`
-	Sort          int    `json:"sort" gorm:"comment:'排序标记'"`
-	Meta          `json:"meta" gorm:"comment:'附加属性'"`
+	ParentId      string `json:"parentId" gorm:"comment:父菜单ID"`
+	Path          string `json:"path" gorm:"comment:路由path"`
+	Name          string `json:"name" gorm:"comment:路由name"`
+	Hidden        bool   `json:"hidden" gorm:"comment:是否在列表隐藏"`
+	Component     string `json:"component" gorm:"comment:对应前端文件路径"`
+	Sort          int    `json:"sort" gorm:"comment:排序标记"`
+	Meta          `json:"meta" gorm:"comment:附加属性"`
 	SysAuthoritys []SysAuthority         `json:"authoritys" gorm:"many2many:sys_authority_menus;"`
 	Children      []SysBaseMenu          `json:"children" gorm:"-"`
 	Parameters    []SysBaseMenuParameter `json:"parameters"`
 }
 
 type Meta struct {
-	KeepAlive   bool   `json:"keepAlive" gorm:"comment:'是否缓存'"`
-	DefaultMenu bool   `json:"defaultMenu" gorm:"comment:'是否是基础路由(开发中)'"`
-	Title       string `json:"title" gorm:"comment:'菜单名'"`
-	Icon        string `json:"icon" gorm:"comment:'菜单图标'"`
+	KeepAlive   bool   `json:"keepAlive" gorm:"comment:是否缓存"`
+	DefaultMenu bool   `json:"defaultMenu" gorm:"comment:是否是基础路由(开发中)"`
+	Title       string `json:"title" gorm:"comment:菜单名"`
+	Icon        string `json:"icon" gorm:"comment:菜单图标"`
 }
 
 type SysBaseMenuParameter struct {

+ 4 - 4
server/model/sys_dictionary.go

@@ -8,9 +8,9 @@ import (
 // 如果含有time.Time 请自行import time包
 type SysDictionary struct {
 	gorm.Model
-	Name                 string                `json:"name" form:"name" gorm:"column:name;comment:'字典名(中)'"`
-	Type                 string                `json:"type" form:"type" gorm:"column:type;comment:'字典名(英)'"`
-	Status               *bool                 `json:"status" form:"status" gorm:"column:status;comment:'状态'"`
-	Desc                 string                `json:"desc" form:"desc" gorm:"column:desc;comment:'描述'"`
+	Name                 string                `json:"name" form:"name" gorm:"column:name;comment:字典名(中)"`
+	Type                 string                `json:"type" form:"type" gorm:"column:type;comment:字典名(英)"`
+	Status               *bool                 `json:"status" form:"status" gorm:"column:status;comment:状态"`
+	Desc                 string                `json:"desc" form:"desc" gorm:"column:desc;comment:描述"`
 	SysDictionaryDetails []SysDictionaryDetail `json:"sysDictionaryDetails" form:"sysDictionaryDetails"`
 }

+ 5 - 5
server/model/sys_dictionary_detail.go

@@ -8,9 +8,9 @@ import (
 // 如果含有time.Time 请自行import time包
 type SysDictionaryDetail struct {
 	gorm.Model
-	Label           string `json:"label" form:"label" gorm:"column:label;comment:'展示值'"`
-	Value           int    `json:"value" form:"value" gorm:"column:value;comment:'字典值'"`
-	Status          *bool  `json:"status" form:"status" gorm:"column:status;comment:'启用状态'"`
-	Sort            int    `json:"sort" form:"sort" gorm:"column:sort;comment:'排序标记'"`
-	SysDictionaryID int    `json:"sysDictionaryID" form:"sysDictionaryID" gorm:"column:sys_dictionary_id;comment:'关联标记'"`
+	Label           string `json:"label" form:"label" gorm:"column:label;comment:展示值"`
+	Value           int    `json:"value" form:"value" gorm:"column:value;comment:字典值"`
+	Status          *bool  `json:"status" form:"status" gorm:"column:status;comment:启用状态"`
+	Sort            int    `json:"sort" form:"sort" gorm:"column:sort;comment:排序标记"`
+	SysDictionaryID int    `json:"sysDictionaryID" form:"sysDictionaryID" gorm:"column:sys_dictionary_id;comment:关联标记"`
 }

+ 1 - 1
server/model/sys_jwt_blacklist.go

@@ -6,5 +6,5 @@ import (
 
 type JwtBlacklist struct {
 	gorm.Model
-	Jwt string `gorm:"type:text;comment:'jwt'"`
+	Jwt string `gorm:"type:text;comment:jwt"`
 }

+ 10 - 10
server/model/sys_operation_record.go

@@ -9,15 +9,15 @@ import (
 // 如果含有time.Time 请自行import time包
 type SysOperationRecord struct {
 	gorm.Model
-	Ip           string        `json:"ip" form:"ip" gorm:"column:ip;comment:'请求ip'"`
-	Method       string        `json:"method" form:"method" gorm:"column:method;comment:''"`
-	Path         string        `json:"path" form:"path" gorm:"column:path;comment:''"`
-	Status       int           `json:"status" form:"status" gorm:"column:status;comment:''"`
-	Latency      time.Duration `json:"latency" form:"latency" gorm:"column:latency;comment:''"`
-	Agent        string        `json:"agent" form:"agent" gorm:"column:agent;comment:''"`
-	ErrorMessage string        `json:"error_message" form:"error_message" gorm:"column:error_message;comment:''"`
-	Body         string        `json:"body" form:"body" gorm:"column:body;comment:'请求Body'"`
-	Resp         string        `json:"resp" form:"resp" gorm:"type:longtext;column:resp;comment:'响应Body'"`
-	UserID       int           `json:"user_id" form:"user_id" gorm:"column:user_id;comment:''"`
+	Ip           string        `json:"ip" form:"ip" gorm:"column:ip;comment:请求ip"`
+	Method       string        `json:"method" form:"method" gorm:"column:method;comment:请求方法"`
+	Path         string        `json:"path" form:"path" gorm:"column:path;comment:请求路径"`
+	Status       int           `json:"status" form:"status" gorm:"column:status;comment:请求状态"`
+	Latency      time.Duration `json:"latency" form:"latency" gorm:"column:latency;comment:延迟"`
+	Agent        string        `json:"agent" form:"agent" gorm:"column:agent;comment:代理"`
+	ErrorMessage string        `json:"error_message" form:"error_message" gorm:"column:error_message;comment:错误信息"`
+	Body         string        `json:"body" form:"body" gorm:"column:body;comment:请求Body"`
+	Resp         string        `json:"resp" form:"resp" gorm:"type:longtext;column:resp;comment:响应Body"`
+	UserID       int           `json:"user_id" form:"user_id" gorm:"column:user_id;comment:用户id"`
 	User         SysUser       `json:"user"`
 }

+ 7 - 7
server/model/sys_user.go

@@ -7,11 +7,11 @@ import (
 
 type SysUser struct {
 	gorm.Model
-	UUID        uuid.UUID    `json:"uuid" gorm:"comment:'用户UUID'"`
-	Username    string       `json:"userName" gorm:"comment:'用户登录名'"`
-	Password    string       `json:"-"  gorm:"comment:'用户登录密码'"`
-	NickName    string       `json:"nickName" gorm:"default:'系统用户';comment:'用户昵称'" `
-	HeaderImg   string       `json:"headerImg" gorm:"default:'http://qmplusimg.henrongyi.top/head.png';comment:'用户头像'"`
-	Authority   SysAuthority `json:"authority" gorm:"foreignKey:AuthorityId;references:AuthorityId;comment:'用户角色'"`
-	AuthorityId string       `json:"authorityId" gorm:"default:888;comment:'用户角色ID'"`
+	UUID        uuid.UUID    `json:"uuid" gorm:"comment:用户UUID"`
+	Username    string       `json:"userName" gorm:"comment:用户登录名"`
+	Password    string       `json:"-"  gorm:"comment:用户登录密码"`
+	NickName    string       `json:"nickName" gorm:"default:系统用户;comment:用户昵称" `
+	HeaderImg   string       `json:"headerImg" gorm:"default:http://qmplusimg.henrongyi.top/head.png;comment:用户头像"`
+	Authority   SysAuthority `json:"authority" gorm:"foreignKey:AuthorityId;references:AuthorityId;comment:用户角色"`
+	AuthorityId string       `json:"authorityId" gorm:"default:888;comment:用户角色ID"`
 }

+ 10 - 10
server/model/sys_workflow.go

@@ -7,19 +7,19 @@ import (
 // 工作流属性表
 type SysWorkflow struct {
 	gorm.Model
-	WorkflowNickName    string                `json:"workflowNickName" gorm:"comment:'工作流中文名称'"`  // 工作流名称
-	WorkflowName        string                `json:"workflowName" gorm:"comment:'工作流英文名称'"`      // 工作流英文id
-	WorkflowDescription string                `json:"workflowDescription" gorm:"comment:'工作流描述'"` // 工作流描述
-	WorkflowStepInfo    []SysWorkflowStepInfo `json:"workflowStep" gorm:"comment:'工作流步骤'"`        // 工作流步骤
+	WorkflowNickName    string                `json:"workflowNickName" gorm:"comment:工作流中文名称"`  // 工作流名称
+	WorkflowName        string                `json:"workflowName" gorm:"comment:工作流英文名称"`      // 工作流英文id
+	WorkflowDescription string                `json:"workflowDescription" gorm:"comment:工作流描述"` // 工作流描述
+	WorkflowStepInfo    []SysWorkflowStepInfo `json:"workflowStep" gorm:"comment:工作流步骤"`        // 工作流步骤
 }
 
 // 工作流状态表
 type SysWorkflowStepInfo struct {
 	gorm.Model
-	SysWorkflowID   uint    `json:"workflowID" gorm:"comment:'所属工作流ID'"`      // 所属工作流ID
-	IsStrat         bool    `json:"isStrat" gorm:"comment:'是否是开始流节点'"`        // 是否是开始流节点
-	StepName        string  `json:"stepName" gorm:"comment:'工作流节点名称'"`        // 工作流名称
-	StepNo          float64 `json:"stepNo" gorm:"comment:'步骤id (第几步)'"`       // 步骤id (第几步)
-	StepAuthorityID string  `json:"stepAuthorityID" gorm:"comment:'操作者级别id'"` // 操作者级别id
-	IsEnd           bool    `json:"isEnd" gorm:"comment:'是否是完结流节点'"`          // 是否是完结流节点
+	SysWorkflowID   uint    `json:"workflowID" gorm:"comment:所属工作流ID"`      // 所属工作流ID
+	IsStart         bool    `json:"isStart" gorm:"comment:是否是开始流节点"`        // 是否是开始流节点
+	StepName        string  `json:"stepName" gorm:"comment:工作流节点名称"`        // 工作流名称
+	StepNo          float64 `json:"stepNo" gorm:"comment:步骤id (第几步)"`       // 步骤id (第几步)
+	StepAuthorityID string  `json:"stepAuthorityID" gorm:"comment:操作者级别id"` // 操作者级别id
+	IsEnd           bool    `json:"isEnd" gorm:"comment:是否是完结流节点"`          // 是否是完结流节点
 }

+ 6 - 6
server/model/sys_workflow_process.go

@@ -5,10 +5,10 @@ import "gorm.io/gorm"
 // 工作流流转表
 type SysWorkFlowProcess struct {
 	gorm.Model
-	ApplicationID  uint   `json:"applicationID" gorm:"comment:'当前工作流所属申请的ID'"` // 当前工作流所属申请的ID
-	CurrentNode    string `json:"currentNode" gorm:"comment:'当前进度节点'"`         // 当前进度节点
-	HistoricalNode string `json:"historicalNode" gorm:"comment:'上一个进度节点'"`     // 上一个进度节点
-	CurrentUser    string `json:"currentUser" gorm:"comment:'当前进度操作人'"`        // 当前进度操作人
-	HistoricalUser string `json:"historicalUser" gorm:"comment:'上一个进度的操作人'"`   // 上一个进度的操作人
-	State          bool   `json:"state" gorm:"comment:'状态 是否是正在进行的状态'"`        // 状态 是否是正在进行的状态
+	ApplicationID  uint   `json:"applicationID" gorm:"comment:当前工作流所属申请的ID"` // 当前工作流所属申请的ID
+	CurrentNode    string `json:"currentNode" gorm:"comment:当前进度节点"`         // 当前进度节点
+	HistoricalNode string `json:"historicalNode" gorm:"comment:上一个进度节点"`     // 上一个进度节点
+	CurrentUser    string `json:"currentUser" gorm:"comment:当前进度操作人"`        // 当前进度操作人
+	HistoricalUser string `json:"historicalUser" gorm:"comment:上一个进度的操作人"`   // 上一个进度的操作人
+	State          bool   `json:"state" gorm:"comment:是否是正在进行的状态"`           // 状态 是否是正在进行的状态
 }

+ 2 - 2
server/resource/template/te/model.go.tpl

@@ -9,9 +9,9 @@ import (
 type {{.StructName}} struct {
       gorm.Model {{- range .Fields}}
             {{- if eq .FieldType "bool" }}
-      {{.FieldName}}  *{{.FieldType}} `json:"{{.FieldJson}}" form:"{{.FieldJson}}" gorm:"column:{{.ColumnName}};comment:'{{.Comment}}'{{- if .DataType -}};type:{{.DataType}}{{- if .DataTypeLong -}}({{.DataTypeLong}}){{- end -}};{{- if .DataTypeLong -}}size:{{.DataTypeLong}};{{- end -}}{{- end -}}"`
+      {{.FieldName}}  *{{.FieldType}} `json:"{{.FieldJson}}" form:"{{.FieldJson}}" gorm:"column:{{.ColumnName}};comment:{{.Comment}}{{- if .DataType -}};type:{{.DataType}}{{- if .DataTypeLong -}}({{.DataTypeLong}}){{- end -}};{{- if .DataTypeLong -}}size:{{.DataTypeLong}};{{- end -}}{{- end -}}"`
             {{- else }}
-      {{.FieldName}}  {{.FieldType}} `json:"{{.FieldJson}}" form:"{{.FieldJson}}" gorm:"column:{{.ColumnName}};comment:'{{.Comment}}'{{- if .DataType -}};type:{{.DataType}}{{- if .DataTypeLong -}}({{.DataTypeLong}}){{- end -}};{{- if .DataTypeLong -}}size:{{.DataTypeLong}};{{- end -}}{{- end -}}"`
+      {{.FieldName}}  {{.FieldType}} `json:"{{.FieldJson}}" form:"{{.FieldJson}}" gorm:"column:{{.ColumnName}};comment:{{.Comment}}{{- if .DataType -}};type:{{.DataType}}{{- if .DataTypeLong -}}({{.DataTypeLong}}){{- end -}};{{- if .DataTypeLong -}}size:{{.DataTypeLong}};{{- end -}}{{- end -}}"`
             {{- end }}  {{- end }} 
 }
 

+ 7 - 16
server/service/sys_casbin.go

@@ -21,6 +21,7 @@ import (
 
 func UpdateCasbin(authorityId string, casbinInfos []request.CasbinInfo) error {
 	ClearCasbin(0, authorityId)
+	rules := [][]string{}
 	for _, v := range casbinInfos {
 		cm := model.CasbinModel{
 			Ptype:       "p",
@@ -28,24 +29,14 @@ func UpdateCasbin(authorityId string, casbinInfos []request.CasbinInfo) error {
 			Path:        v.Path,
 			Method:      v.Method,
 		}
-		addflag := AddCasbin(cm)
-		if addflag == false {
-			return errors.New("存在相同api,添加失败,请联系管理员")
-		}
+		rules = append(rules, []string{cm.AuthorityId, cm.Path, cm.Method})
 	}
-	return nil
-}
-
-// @title    AddCasbin
-// @description   add casbin authority, 添加权限
-// @auth                     (2020/04/05  20:22)
-// @param     cm              model.CasbinModel
-// @return                    bool
-
-func AddCasbin(cm model.CasbinModel) bool {
 	e := Casbin()
-	success, _ := e.AddPolicy(cm.AuthorityId, cm.Path, cm.Method)
-	return success
+	success, _ := e.AddPolicies(rules)
+	if success == false {
+		return errors.New("存在相同api,添加失败,请联系管理员")
+	}
+	return nil
 }
 
 // @title    UpdateCasbinApi

+ 3 - 3
server/utils/email.go

@@ -23,7 +23,7 @@ func EmailTest(subject string, body string) error {
 
 func send(to []string, subject string, body string) error {
 	from := global.GVA_CONFIG.Email.EmailFrom
-	nickName := global.GVA_CONFIG.Email.EmailNickName
+	nickname := global.GVA_CONFIG.Email.EmailNickname
 	secret := global.GVA_CONFIG.Email.EmailSecret
 	host := global.GVA_CONFIG.Email.EmailHost
 	port := global.GVA_CONFIG.Email.EmailPort
@@ -31,8 +31,8 @@ func send(to []string, subject string, body string) error {
 
 	auth := smtp.PlainAuth("", from, secret, host)
 	e := email.NewEmail()
-	if nickName != "" {
-		e.From = fmt.Sprintf("%s <%s>", nickName, from)
+	if nickname != "" {
+		e.From = fmt.Sprintf("%s <%s>", nickname, from)
 	} else {
 		e.From = from
 	}

+ 1 - 1
web/babel.config.js

@@ -1,5 +1,5 @@
 module.exports = {
   presets: [
-    '@vue/app'
+    '@vue/cli-plugin-babel/preset'
   ]
 }

Plik diff jest za duży
+ 926 - 104
web/package-lock.json


+ 7 - 7
web/package.json

@@ -10,7 +10,7 @@
   "dependencies": {
     "@moefe/vue-aplayer": "^2.0.0-beta.5",
     "axios": "^0.19.0",
-    "core-js": "^2.6.5",
+    "core-js": "^3.6.5",
     "echarts": "^4.7.0",
     "element-ui": "^2.12.0",
     "mavon-editor": "^2.7.7",
@@ -33,12 +33,12 @@
     "vuex-persist": "^2.1.0"
   },
   "devDependencies": {
-    "@vue/cli-plugin-babel": "^3.11.0",
-    "@vue/cli-plugin-eslint": "^3.11.0",
-    "@vue/cli-service": "^3.11.0",
-    "babel-eslint": "^10.0.1",
-    "eslint": "^5.16.0",
-    "eslint-plugin-vue": "^5.0.0",
+    "@vue/cli-plugin-babel": "^4.5.6",
+    "@vue/cli-plugin-eslint": "^4.5.6",
+    "@vue/cli-service": "^4.5.6",
+    "babel-eslint": "^10.1.0",
+    "eslint": "^6.7.2",
+    "eslint-plugin-vue": "^6.2.2",
     "vue-template-compiler": "^2.6.10"
   },
   "eslintConfig": {

+ 2 - 2
web/src/store/module/user.js

@@ -37,9 +37,9 @@ export const user = {
     actions: {
         async LoginIn({ commit }, loginInfo) {
             const res = await login(loginInfo)
-            commit('setUserInfo', res.data.user)
-            commit('setToken', res.data.token)
             if (res.code == 0) {
+                commit('setUserInfo', res.data.user)
+                commit('setToken', res.data.token)
                 const redirect = router.history.current.query.redirect
                 if (redirect) {
                     router.push({ path: redirect })

+ 219 - 139
web/src/view/systemTools/system/system.vue

@@ -1,138 +1,218 @@
 <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="本地或七牛云">
-					<el-checkbox v-model="config.localUpload.local">本地</el-checkbox>
-				</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>
-			<h2>邮箱配置</h2>
-			<el-form-item label="emailFrom">
-				<el-input v-model="config.email.emailFrom"></el-input>
-			</el-form-item>
-			<el-form-item label="emailNickName">
-				<el-input v-model="config.email.emailNickName"></el-input>
-			</el-form-item>
-			<el-form-item label="emailSecret">
-				<el-input v-model="config.email.emailSecret"></el-input>
-			</el-form-item>
-			<el-form-item label="emailTo">
-				<el-input v-model="config.email.emailTo" placeholder="可多个,以逗号分隔"></el-input>
-			</el-form-item>
-			<el-form-item label="emailHost">
-				<el-input v-model="config.email.emailHost"></el-input>
-			</el-form-item>
-			<el-form-item label="emailPort">
-				<el-input v-model.number="config.email.emailPort"></el-input>
-			</el-form-item>
-			<el-form-item label="emailIsSSL">
-				<el-checkbox v-model="config.email.emailIsSSL"></el-checkbox>
-			</el-form-item>
-			<el-form-item label="测试邮件">
-				<el-button @click="email">测试邮件</el-button>
-			</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-option value="postgresql"></el-option>
+          <el-option value="sqlserver"></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-if="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-if="config.system.dbType == 'postgresql'">
+        <h2>postgresql 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="dbName">
+          <el-input v-model="config.mysql.dbName"></el-input>
+        </el-form-item>
+        <el-form-item label="port">
+          <el-input v-model="config.mysql.port"></el-input>
+        </el-form-item>
+        <el-form-item label="config">
+          <el-input v-model="config.mysql.config"></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="logger">
+          <el-checkbox v-model="config.mysql.logger"></el-checkbox>
+        </el-form-item>
+        <el-form-item label="prefer-simple-protocol">
+          <el-checkbox v-model="config.mysql.preferSimpleProtocol"></el-checkbox>
+        </el-form-item>
+      </template>
+      <template v-if="config.system.dbType == 'sqlite'">
+        <h2>sqlite admin数据库配置</h2>
+        <el-form-item label="path">
+          <el-input v-model="config.mysql.path"></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="logger">
+          <el-checkbox v-model="config.mysql.logger"></el-checkbox>
+        </el-form-item>
+      </template>
+      <template v-if="config.system.dbType == 'sqlserver'">
+        <h2>sqlserver admin数据库配置</h2>
+        <el-form-item label="username">
+          <el-input v-model="config.sqlserver.username"></el-input>
+        </el-form-item>
+        <el-form-item label="password">
+          <el-input v-model="config.sqlserver.password"></el-input>
+        </el-form-item>
+        <el-form-item label="path">
+          <el-input v-model="config.sqlserver.path"></el-input>
+        </el-form-item>
+        <el-form-item label="dbname">
+          <el-input v-model="config.sqlserver.dbname"></el-input>
+        </el-form-item>
+        <el-form-item label="maxIdleConns">
+          <el-input v-model.number="config.sqlserver.maxIdleConns"></el-input>
+        </el-form-item>
+        <el-form-item label="maxOpenConns">
+          <el-input v-model.number="config.sqlserver.maxOpenConns"></el-input>
+        </el-form-item>
+        <el-form-item label="logger">
+          <el-checkbox v-model="config.sqlserver.logger"></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.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="level">
+        <el-input v-model.number="config.zap.level"></el-input>
+      </el-form-item>
+      <el-form-item label="format">
+        <el-input v-model="config.zap.format"></el-input>
+      </el-form-item>
+      <el-form-item label="prefix">
+        <el-input v-model="config.zap.prefix"></el-input>
+      </el-form-item>
+      <el-form-item label="director">
+        <el-input v-model="config.zap.director"></el-input>
+      </el-form-item>
+      <el-form-item label="link-name">
+        <el-input v-model="config.zap.linkName"></el-input>
+      </el-form-item>
+      <el-form-item label="encode-level">
+        <el-input v-model="config.zap.encodeLevel"></el-input>
+      </el-form-item>
+      <el-form-item label="stacktrace-key">
+        <el-input v-model="config.zap.stacktraceKey"></el-input>
+      </el-form-item>
+      <el-form-item label="show-line">
+        <el-checkbox v-model="config.zap.showLine"></el-checkbox>
+      </el-form-item>
+      <el-form-item label="log-in-console">
+        <el-checkbox v-model="config.zap.logInConsole"></el-checkbox>
+      </el-form-item>
+      <h2>邮箱配置</h2>
+      <el-form-item label="emailFrom">
+        <el-input v-model="config.email.emailFrom"></el-input>
+      </el-form-item>
+      <el-form-item label="emailNickName">
+        <el-input v-model="config.email.emailNickName"></el-input>
+      </el-form-item>
+      <el-form-item label="emailSecret">
+        <el-input v-model="config.email.emailSecret"></el-input>
+      </el-form-item>
+      <el-form-item label="emailTo">
+        <el-input v-model="config.email.emailTo" placeholder="可多个,以逗号分隔"></el-input>
+      </el-form-item>
+      <el-form-item label="emailHost">
+        <el-input v-model="config.email.emailHost"></el-input>
+      </el-form-item>
+      <el-form-item label="emailPort">
+        <el-input v-model.number="config.email.emailPort"></el-input>
+      </el-form-item>
+      <el-form-item label="emailIsSSL">
+        <el-checkbox v-model="config.email.emailIsSSL"></el-checkbox>
+      </el-form-item>
+      <el-form-item label="测试邮件">
+        <el-button @click="email">测试邮件</el-button>
+      </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>
@@ -151,9 +231,9 @@ export default {
         redis: {},
         qiniu: {},
         captcha: {},
-		log: {},
-		localUpload: {},
-		email: {},
+        log: {},
+        localUpload: {},
+        email: {}
       }
     };
   },
@@ -187,11 +267,11 @@ export default {
         });
         await this.initForm();
       } else {
-		this.$message({
+        this.$message({
           type: "error",
           message: "邮件发送失败"
         });
-	  }
+      }
     }
   }
 };

+ 5 - 5
web/vue.config.js

@@ -51,10 +51,10 @@ module.exports = {
             })
             .end()
         config
-            // https://webpack.js.org/configuration/devtool/#development
+        // https://webpack.js.org/configuration/devtool/#development
             .when(process.env.NODE_ENV === 'development',
-                config => config.devtool('cheap-source-map')
-            )
+            config => config.devtool('cheap-source-map')
+        )
 
         config
             .when(process.env.NODE_ENV !== 'development',
@@ -64,7 +64,7 @@ module.exports = {
                         .after('html')
                         .use('script-ext-html-webpack-plugin', [{
                             // `runtime` must same as runtimeChunk name. default is `runtime`
-                            inline: /runtime\..*\.js$/
+                            inline: /single\..*\.js$/
                         }])
                         .end()
                     config
@@ -95,4 +95,4 @@ module.exports = {
                 }
             )
     }
-}
+}

Niektóre pliki nie zostały wyświetlone z powodu dużej ilości zmienionych plików