提交 1d44c230 编写于 作者: Mr.奇淼('s avatar Mr.奇淼(

Merge branch 'gin-vue-admin_v2_dev' of https://github.com/piexlmax/QMPlus into gin-vue-admin_v2_dev

......@@ -145,7 +145,7 @@ swag init
## 4. 项目架构
### 4.1 系统架构图
![系统架构图](./docs/gin-vue-admin.png)
![系统架构图](http://qmplusimg.henrongyi.top/gva/gin-vue-admin.png)
### 4.2 前端详细设计图 (提供者:<a href="https://github.com/baobeisuper">baobeisuper</a>)
......
......@@ -146,7 +146,7 @@ After executing the above command,`docs` will show in `server/`,then open yo
### 4.1 Architecture Diagram
![Architecture diagram](./docs/gin-vue-admin.png)
![Architecture diagram](http://qmplusimg.henrongyi.top/gva/gin-vue-admin.png)
### 4.2 Front-end Detailed Design Diagram (Contributor: <a href="https://github.com/baobeisuper">baobeisuper</a>)
......
......@@ -2,6 +2,7 @@ package v1
import (
"fmt"
"gin-vue-admin/global"
"gin-vue-admin/global/response"
"gin-vue-admin/model"
"gin-vue-admin/service"
......@@ -34,7 +35,7 @@ func CreateTemp(c *gin.Context) {
return
}
if a.AutoCreateApiToSql {
apiList := [5]model.SysApi{
apiList := [6]model.SysApi{
{
Path: "/" + a.Abbreviation + "/" + "create" + a.StructName,
Description: "新增" + a.Description,
......@@ -47,6 +48,12 @@ func CreateTemp(c *gin.Context) {
ApiGroup: a.Abbreviation,
Method: "DELETE",
},
{
Path: "/" + a.Abbreviation + "/" + "delete" + a.StructName+"ByIds",
Description: "批量删除" + a.Description,
ApiGroup: a.Abbreviation,
Method: "DELETE",
},
{
Path: "/" + a.Abbreviation + "/" + "update" + a.StructName,
Description: "更新" + a.Description,
......@@ -87,3 +94,61 @@ func CreateTemp(c *gin.Context) {
os.Remove("./ginvueadmin.zip")
}
}
// @Tags SysApi
// @Summary 获取当前数据库所有表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /autoCode/getTables [get]
func GetTables(c *gin.Context) {
dbName := c.DefaultQuery("dbName", global.GVA_CONFIG.Mysql.Dbname)
err, tables := service.GetTables(dbName)
if err != nil {
response.FailWithMessage(fmt.Sprintf("查询table失败,%v", err), c)
} else {
response.OkWithData(gin.H{
"tables": tables,
}, c)
}
}
// @Tags SysApi
// @Summary 获取当前所有数据库
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /autoCode/getDatabase [get]
func GetDB(c *gin.Context) {
err, dbs := service.GetDB()
if err != nil {
response.FailWithMessage(fmt.Sprintf("查询table失败,%v", err), c)
} else {
response.OkWithData(gin.H{
"dbs": dbs,
}, c)
}
}
// @Tags SysApi
// @Summary 获取当前表所有字段
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {string} string "{"success":true,"data":{},"msg":"创建成功"}"
// @Router /autoCode/getDatabase [get]
func GetColume(c *gin.Context) {
dbName := c.DefaultQuery("dbName", global.GVA_CONFIG.Mysql.Dbname)
tableName := c.Query("tableName")
err, columes := service.GetColume(tableName, dbName)
if err != nil {
response.FailWithMessage(fmt.Sprintf("查询table失败,%v", err), c)
} else {
response.OkWithData(gin.H{
"columes": columes,
}, c)
}
}
package v1
import (
"fmt"
"gin-vue-admin/global"
"gin-vue-admin/global/response"
resp "gin-vue-admin/model/response"
"gin-vue-admin/utils"
"github.com/dchest/captcha"
"github.com/gin-gonic/gin"
"github.com/mojocn/base64Captcha"
)
var store = base64Captcha.DefaultMemStore
// @Tags base
// @Summary 生成验证码
// @Security ApiKeyAuth
......@@ -17,20 +19,17 @@ import (
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /base/captcha [post]
func Captcha(c *gin.Context) {
captchaId := captcha.NewLen(global.GVA_CONFIG.Captcha.KeyLong)
response.OkDetailed(resp.SysCaptchaResponse{
CaptchaId: captchaId,
PicPath: "/base/captcha/" + captchaId + ".png",
}, "验证码获取成功", c)
}
// @Tags base
// @Summary 生成验证码图片路径
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /base/captcha/:captchaId [get]
func CaptchaImg(c *gin.Context) {
utils.GinCaptchaServeHTTP(c.Writer, c.Request)
//字符,公式,验证码配置
// 生成默认数字的driver
driver := base64Captcha.NewDriverDigit(global.GVA_CONFIG.Captcha.ImgHeight, global.GVA_CONFIG.Captcha.ImgWidth, global.GVA_CONFIG.Captcha.KeyLong, 0.7, 80)
cp := base64Captcha.NewCaptcha(driver, store)
id, b64s, err := cp.Generate()
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
} else {
response.OkDetailed(resp.SysCaptchaResponse{
CaptchaId: id,
PicPath: b64s,
}, "验证码获取成功", c)
}
}
package v1
import (
"fmt"
"gin-vue-admin/global/response"
"gin-vue-admin/model"
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"github.com/gin-gonic/gin"
)
// @Tags SysDictionary
// @Summary 创建SysDictionary
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysDictionary true "创建SysDictionary"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /sysDictionary/createSysDictionary [post]
func CreateSysDictionary(c *gin.Context) {
var sysDictionary model.SysDictionary
_ = c.ShouldBindJSON(&sysDictionary)
err := service.CreateSysDictionary(sysDictionary)
if err != nil {
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
} else {
response.OkWithMessage("创建成功", c)
}
}
// @Tags SysDictionary
// @Summary 删除SysDictionary
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysDictionary true "删除SysDictionary"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /sysDictionary/deleteSysDictionary [delete]
func DeleteSysDictionary(c *gin.Context) {
var sysDictionary model.SysDictionary
_ = c.ShouldBindJSON(&sysDictionary)
err := service.DeleteSysDictionary(sysDictionary)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
} else {
response.OkWithMessage("删除成功", c)
}
}
// @Tags SysDictionary
// @Summary 更新SysDictionary
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysDictionary true "更新SysDictionary"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /sysDictionary/updateSysDictionary [put]
func UpdateSysDictionary(c *gin.Context) {
var sysDictionary model.SysDictionary
_ = c.ShouldBindJSON(&sysDictionary)
err := service.UpdateSysDictionary(&sysDictionary)
if err != nil {
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
} else {
response.OkWithMessage("更新成功", c)
}
}
// @Tags SysDictionary
// @Summary 用id查询SysDictionary
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysDictionary true "用id查询SysDictionary"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /sysDictionary/findSysDictionary [get]
func FindSysDictionary(c *gin.Context) {
var sysDictionary model.SysDictionary
_ = c.ShouldBindQuery(&sysDictionary)
err, resysDictionary := service.GetSysDictionary(sysDictionary.Type, sysDictionary.ID)
if err != nil {
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
} else {
response.OkWithData(gin.H{"resysDictionary": resysDictionary}, c)
}
}
// @Tags SysDictionary
// @Summary 分页获取SysDictionary列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.SysDictionarySearch true "分页获取SysDictionary列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /sysDictionary/getSysDictionaryList [get]
func GetSysDictionaryList(c *gin.Context) {
var pageInfo request.SysDictionarySearch
_ = c.ShouldBindQuery(&pageInfo)
err, list, total := service.GetSysDictionaryInfoList(pageInfo)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
} else {
response.OkWithData(resp.PageResult{
List: list,
Total: total,
Page: pageInfo.Page,
PageSize: pageInfo.PageSize,
}, c)
}
}
package v1
import (
"fmt"
"gin-vue-admin/global/response"
"gin-vue-admin/model"
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"github.com/gin-gonic/gin"
)
// @Tags SysDictionaryDetail
// @Summary 创建SysDictionaryDetail
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysDictionaryDetail true "创建SysDictionaryDetail"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /sysDictionaryDetail/createSysDictionaryDetail [post]
func CreateSysDictionaryDetail(c *gin.Context) {
var sysDictionaryDetail model.SysDictionaryDetail
_ = c.ShouldBindJSON(&sysDictionaryDetail)
err := service.CreateSysDictionaryDetail(sysDictionaryDetail)
if err != nil {
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
} else {
response.OkWithMessage("创建成功", c)
}
}
// @Tags SysDictionaryDetail
// @Summary 删除SysDictionaryDetail
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysDictionaryDetail true "删除SysDictionaryDetail"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /sysDictionaryDetail/deleteSysDictionaryDetail [delete]
func DeleteSysDictionaryDetail(c *gin.Context) {
var sysDictionaryDetail model.SysDictionaryDetail
_ = c.ShouldBindJSON(&sysDictionaryDetail)
err := service.DeleteSysDictionaryDetail(sysDictionaryDetail)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
} else {
response.OkWithMessage("删除成功", c)
}
}
// @Tags SysDictionaryDetail
// @Summary 更新SysDictionaryDetail
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysDictionaryDetail true "更新SysDictionaryDetail"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /sysDictionaryDetail/updateSysDictionaryDetail [put]
func UpdateSysDictionaryDetail(c *gin.Context) {
var sysDictionaryDetail model.SysDictionaryDetail
_ = c.ShouldBindJSON(&sysDictionaryDetail)
err := service.UpdateSysDictionaryDetail(&sysDictionaryDetail)
if err != nil {
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
} else {
response.OkWithMessage("更新成功", c)
}
}
// @Tags SysDictionaryDetail
// @Summary 用id查询SysDictionaryDetail
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysDictionaryDetail true "用id查询SysDictionaryDetail"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /sysDictionaryDetail/findSysDictionaryDetail [get]
func FindSysDictionaryDetail(c *gin.Context) {
var sysDictionaryDetail model.SysDictionaryDetail
_ = c.ShouldBindQuery(&sysDictionaryDetail)
err, resysDictionaryDetail := service.GetSysDictionaryDetail(sysDictionaryDetail.ID)
if err != nil {
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
} else {
response.OkWithData(gin.H{"resysDictionaryDetail": resysDictionaryDetail}, c)
}
}
// @Tags SysDictionaryDetail
// @Summary 分页获取SysDictionaryDetail列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.SysDictionaryDetailSearch true "分页获取SysDictionaryDetail列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /sysDictionaryDetail/getSysDictionaryDetailList [get]
func GetSysDictionaryDetailList(c *gin.Context) {
var pageInfo request.SysDictionaryDetailSearch
_ = c.ShouldBindQuery(&pageInfo)
err, list, total := service.GetSysDictionaryDetailInfoList(pageInfo)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
} else {
response.OkWithData(resp.PageResult{
List: list,
Total: total,
Page: pageInfo.Page,
PageSize: pageInfo.PageSize,
}, c)
}
}
package v1
import (
"fmt"
"gin-vue-admin/global/response"
"gin-vue-admin/model"
"gin-vue-admin/model/request"
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"github.com/gin-gonic/gin"
)
// @Tags SysOperationRecord
// @Summary 创建SysOperationRecord
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysOperationRecord true "创建SysOperationRecord"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /sysOperationRecord/createSysOperationRecord [post]
func CreateSysOperationRecord(c *gin.Context) {
var sysOperationRecord model.SysOperationRecord
_ = c.ShouldBindJSON(&sysOperationRecord)
err := service.CreateSysOperationRecord(sysOperationRecord)
if err != nil {
response.FailWithMessage(fmt.Sprintf("创建失败,%v", err), c)
} else {
response.OkWithMessage("创建成功", c)
}
}
// @Tags SysOperationRecord
// @Summary 删除SysOperationRecord
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysOperationRecord true "删除SysOperationRecord"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /sysOperationRecord/deleteSysOperationRecord [delete]
func DeleteSysOperationRecord(c *gin.Context) {
var sysOperationRecord model.SysOperationRecord
_ = c.ShouldBindJSON(&sysOperationRecord)
err := service.DeleteSysOperationRecord(sysOperationRecord)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
} else {
response.OkWithMessage("删除成功", c)
}
}
// @Tags SysOperationRecord
// @Summary 批量删除SysOperationRecord
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.IdsReq true "批量删除SysOperationRecord"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /sysOperationRecord/deleteSysOperationRecordByIds [delete]
func DeleteSysOperationRecordByIds(c *gin.Context) {
var IDS request.IdsReq
_ = c.ShouldBindJSON(&IDS)
err := service.DeleteSysOperationRecordByIds(IDS)
if err != nil {
response.FailWithMessage(fmt.Sprintf("删除失败,%v", err), c)
} else {
response.OkWithMessage("删除成功", c)
}
}
// @Tags SysOperationRecord
// @Summary 更新SysOperationRecord
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysOperationRecord true "更新SysOperationRecord"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"更新成功"}"
// @Router /sysOperationRecord/updateSysOperationRecord [put]
func UpdateSysOperationRecord(c *gin.Context) {
var sysOperationRecord model.SysOperationRecord
_ = c.ShouldBindJSON(&sysOperationRecord)
err := service.UpdateSysOperationRecord(&sysOperationRecord)
if err != nil {
response.FailWithMessage(fmt.Sprintf("更新失败,%v", err), c)
} else {
response.OkWithMessage("更新成功", c)
}
}
// @Tags SysOperationRecord
// @Summary 用id查询SysOperationRecord
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body model.SysOperationRecord true "用id查询SysOperationRecord"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"查询成功"}"
// @Router /sysOperationRecord/findSysOperationRecord [get]
func FindSysOperationRecord(c *gin.Context) {
var sysOperationRecord model.SysOperationRecord
_ = c.ShouldBindQuery(&sysOperationRecord)
err, resysOperationRecord := service.GetSysOperationRecord(sysOperationRecord.ID)
if err != nil {
response.FailWithMessage(fmt.Sprintf("查询失败,%v", err), c)
} else {
response.OkWithData(gin.H{"resysOperationRecord": resysOperationRecord}, c)
}
}
// @Tags SysOperationRecord
// @Summary 分页获取SysOperationRecord列表
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.SysOperationRecordSearch true "分页获取SysOperationRecord列表"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"获取成功"}"
// @Router /sysOperationRecord/getSysOperationRecordList [get]
func GetSysOperationRecordList(c *gin.Context) {
var pageInfo request.SysOperationRecordSearch
_ = c.ShouldBindQuery(&pageInfo)
err, list, total := service.GetSysOperationRecordInfoList(pageInfo)
if err != nil {
response.FailWithMessage(fmt.Sprintf("获取数据失败,%v", err), c)
} else {
response.OkWithData(resp.PageResult{
List: list,
Total: total,
Page: pageInfo.Page,
PageSize: pageInfo.PageSize,
}, c)
}
}
......@@ -10,7 +10,6 @@ import (
resp "gin-vue-admin/model/response"
"gin-vue-admin/service"
"gin-vue-admin/utils"
"github.com/dchest/captcha"
"github.com/dgrijalva/jwt-go"
"github.com/gin-gonic/gin"
"github.com/go-redis/redis"
......@@ -67,7 +66,7 @@ func Login(c *gin.Context) {
response.FailWithMessage(UserVerifyErr.Error(), c)
return
}
if captcha.VerifyString(L.CaptchaId, L.Captcha) {
if store.Verify(L.CaptchaId, L.Captcha, true) {
U := &model.SysUser{Username: L.Username, Password: L.Password}
if err, user := service.Login(U); err != nil {
response.FailWithMessage(fmt.Sprintf("用户名密码错误或%v", err), c)
......
......@@ -26,11 +26,14 @@ sqlite:
config: 'loc=Asia/Shanghai'
# oss configuration
# 请自行七牛申请对应的 公钥 私钥 bucket 和 域名地址
qiniu:
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'
......@@ -46,9 +49,9 @@ system:
# captcha configuration
captcha:
key-long: 4
img-width: 120
img-height: 40
key-long: 6
img-width: 240
img-height: 80
# logger configuration
log:
......
package config
type Server struct {
Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
Sqlite Sqlite `mapstructure:"sqlite" json:"sqlite" yaml:"sqlite"`
Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"`
Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"`
Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"`
System System `mapstructure:"system" json:"system" yaml:"system"`
JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
Log Log `mapstructure:"log" json:"log" yaml:"log"`
Mysql Mysql `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
Sqlite Sqlite `mapstructure:"sqlite" json:"sqlite" yaml:"sqlite"`
Qiniu Qiniu `mapstructure:"qiniu" json:"qiniu" yaml:"qiniu"`
Casbin Casbin `mapstructure:"casbin" json:"casbin" yaml:"casbin"`
Redis Redis `mapstructure:"redis" json:"redis" yaml:"redis"`
System System `mapstructure:"system" json:"system" yaml:"system"`
JWT JWT `mapstructure:"jwt" json:"jwt" yaml:"jwt"`
Captcha Captcha `mapstructure:"captcha" json:"captcha" yaml:"captcha"`
Log Log `mapstructure:"log" json:"log" yaml:"log"`
}
type System struct {
......
package core
import (
"fmt"
"gin-vue-admin/global"
"gin-vue-admin/initialize"
"gin-vue-admin/middleware"
"github.com/gin-gonic/gin"
"github.com/piexlmax/gvaplug"
)
func InstallPlugs(route *gin.Engine) {
GvaPlugsGroupBase := route.Group("") // 纯净路由 插件可通用 传递给插件的0号位置 为了不让插件的自动路由出问题 这里建议为 ""
/**安装一个插件需要的步骤 start**/
GvaPlugsGroupMiddle := route.Group("") // 携带中间件的路由 传递给插件的1号位置 为了不让插件的自动路由出问题 这里建议为 ""
GvaPlugsGroupMiddle.Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
// 插件安装 暂时只是后台功能 添加model 添加路由 添加对数据库的操作 详细插件测试模板可看https://github.com/piexlmax/gvaplug 此处不建议投入生产
err := initialize.InstallPlug(global.GVA_DB, [2]*gin.RouterGroup{
GvaPlugsGroupBase,
GvaPlugsGroupMiddle,
}, gvaplug.GvaPlug{SomeConfig: "插件给用户提供的配置区域"})
if err != nil {
panic(fmt.Sprintf("插件安装失败: %v", err))
}
/**安装一个插件需要的步骤 end**/
}
......@@ -5,6 +5,7 @@ import (
"gin-vue-admin/config"
"gin-vue-admin/global"
"gin-vue-admin/utils"
"github.com/gin-gonic/gin"
rotatelogs "github.com/lestrrat/go-file-rotatelogs"
oplogging "github.com/op/go-logging"
"io"
......@@ -30,26 +31,25 @@ func init() {
}
logger := oplogging.MustGetLogger(module)
var backends []oplogging.Backend
backends = registerStdout(c, backends)
backends = registerFile(c, backends)
registerStdout(c, &backends)
if fileWriter := registerFile(c, &backends); fileWriter != nil {
gin.DefaultWriter = io.MultiWriter(fileWriter, os.Stdout)
}
oplogging.SetBackend(backends...)
global.GVA_LOG = logger
}
func registerStdout(c config.Log, backends []oplogging.Backend) []oplogging.Backend {
func registerStdout(c config.Log, backends *[]oplogging.Backend) {
if c.Stdout != "" {
level, err := oplogging.LogLevel(c.Stdout)
if err != nil {
fmt.Println(err)
}
backends = append(backends, createBackend(os.Stdout, c, level))
*backends = append(*backends, createBackend(os.Stdout, c, level))
}
return backends
}
func registerFile(c config.Log, backends []oplogging.Backend) []oplogging.Backend {
func registerFile(c config.Log, backends *[]oplogging.Backend) io.Writer {
if c.File != "" {
if ok, _ := utils.PathExists(logDir); !ok {
// directory not exist
......@@ -67,16 +67,16 @@ func registerFile(c config.Log, backends []oplogging.Backend) []oplogging.Backen
)
if err != nil {
fmt.Println(err)
return backends
}
level, err := oplogging.LogLevel(c.File)
if err != nil {
fmt.Println(err)
}
backends = append(backends, createBackend(fileWriter, c, level))
}
*backends = append(*backends, createBackend(fileWriter, c, level))
return backends
return fileWriter
}
return nil
}
func createBackend(w io.Writer, c config.Log, level oplogging.Level) oplogging.Backend {
......
......@@ -4,10 +4,13 @@ import (
"fmt"
"gin-vue-admin/global"
"gin-vue-admin/initialize"
"net/http"
"time"
)
type server interface {
ListenAndServe() error
}
func RunWindowsServer() {
if global.GVA_CONFIG.System.UseMultipoint {
// 初始化redis服务
......@@ -16,21 +19,11 @@ func RunWindowsServer() {
Router := initialize.Routers()
Router.Static("/form-generator", "./resource/page")
// 插件安装 暂时只是后台功能 添加model 添加路由 添加对数据库的操作 详细插件测试模板可看https://github.com/piexlmax/gvaplug 此处不建议投入生产
//err := initialize.InstallPlug(global.GVA_DB, Router, gvaplug.GvaPlug{})
//if err != nil {
// panic(fmt.Sprintf("插件安装失败: %v", err))
//}
//InstallPlugs(Router)
// end 插件描述
address := fmt.Sprintf(":%d", global.GVA_CONFIG.System.Addr)
s := &http.Server{
Addr: address,
Handler: Router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
s := initServer(address, Router)
// 保证文本顺序输出
// In order to ensure that the text order output can be deleted
time.Sleep(10 * time.Microsecond)
......@@ -39,6 +32,6 @@ func RunWindowsServer() {
fmt.Printf(`欢迎使用 Gin-Vue-Admin
默认自动化文档地址:http://127.0.0.1%s/swagger/index.html
默认前端文件运行地址:http://127.0.0.1:8080
`, s.Addr)
`, address)
global.GVA_LOG.Error(s.ListenAndServe())
}
// +build !windows
package core
import (
"github.com/fvbock/endless"
"github.com/gin-gonic/gin"
"time"
)
func initServer(address string, router *gin.Engine) server {
s := endless.NewServer(address, router)
s.ReadHeaderTimeout = 10 * time.Millisecond
s.WriteTimeout = 10 * time.Second
s.MaxHeaderBytes = 1 << 20
return s
}
\ No newline at end of file
// +build windows
package core
import (
"github.com/gin-gonic/gin"
"net/http"
"time"
)
func initServer(address string, router *gin.Engine) server {
return &http.Server{
Addr: address,
Handler: router,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
}
\ No newline at end of file
INSERT INTO `sys_base_menus` VALUES (52, '2020-06-29 13:31:17', '2020-07-07 16:05:34', NULL, 0, 3, 'operation', 'operation', 0, 'view/superAdmin/operation/sysOperationRecord.vue', '操作历史', 'time', NULL, 6, 0, 0);
INSERT INTO `sys_dictionaries` VALUES (3, '2020-07-05 15:27:31', '2020-07-05 15:27:31', NULL, '数据库int类型', 'int', 1, 'int类型对应的数据库类型');
INSERT INTO `sys_dictionaries` VALUES (4, '2020-07-05 15:33:07', '2020-07-05 16:07:18', NULL, '数据库时间日期类型', 'time.Time', 1, '数据库时间日期类型');
INSERT INTO `sys_dictionaries` VALUES (5, '2020-07-05 15:34:23', '2020-07-05 15:52:45', NULL, '数据库浮点型', 'float64', 1, '数据库浮点型');
INSERT INTO `sys_dictionaries` VALUES (6, '2020-07-05 15:35:05', '2020-07-05 15:35:05', NULL, '数据库字符串', 'string', 1, '数据库字符串');
INSERT INTO `sys_dictionaries` VALUES (7, '2020-07-05 15:36:48', '2020-07-05 15:36:48', NULL, '数据库bool类型', 'bool', 1, '数据库bool类型');
INSERT INTO `sys_dictionary_details` VALUES (12, '2020-07-05 15:31:41', '2020-07-05 15:31:41', NULL, 'smallint', 1, 1, 1, 3);
INSERT INTO `sys_dictionary_details` VALUES (13, '2020-07-05 15:31:52', '2020-07-05 15:31:52', NULL, 'mediumint', 2, 1, 2, 3);
INSERT INTO `sys_dictionary_details` VALUES (14, '2020-07-05 15:32:04', '2020-07-05 15:32:04', NULL, 'int', 3, 1, 3, 3);
INSERT INTO `sys_dictionary_details` VALUES (15, '2020-07-05 15:32:11', '2020-07-05 15:32:11', NULL, 'bigint', 4, 1, 4, 3);
INSERT INTO `sys_dictionary_details` VALUES (19, '2020-07-05 15:33:16', '2020-07-05 15:33:16', NULL, 'data', 0, 1, 0, 4);
INSERT INTO `sys_dictionary_details` VALUES (20, '2020-07-05 15:33:21', '2020-07-05 15:33:21', NULL, 'time', 1, 1, 1, 4);
INSERT INTO `sys_dictionary_details` VALUES (21, '2020-07-05 15:33:25', '2020-07-05 15:33:25', NULL, 'year', 2, 1, 2, 4);
INSERT INTO `sys_dictionary_details` VALUES (22, '2020-07-05 15:33:35', '2020-07-05 15:33:35', NULL, 'datetime', 3, 1, 3, 4);
INSERT INTO `sys_dictionary_details` VALUES (23, '2020-07-05 15:33:42', '2020-07-05 15:33:42', NULL, 'timestamp', 5, 1, 5, 4);
INSERT INTO `sys_dictionary_details` VALUES (24, '2020-07-05 15:34:30', '2020-07-05 15:34:30', NULL, 'float', 0, 1, 0, 5);
INSERT INTO `sys_dictionary_details` VALUES (25, '2020-07-05 15:34:35', '2020-07-05 15:34:35', NULL, 'double', 1, 1, 1, 5);
INSERT INTO `sys_dictionary_details` VALUES (26, '2020-07-05 15:34:41', '2020-07-05 15:34:41', NULL, 'decimal', 2, 1, 2, 5);
INSERT INTO `sys_dictionary_details` VALUES (27, '2020-07-05 15:37:45', '2020-07-05 15:37:45', NULL, 'tinyint', 0, 1, 0, 7);
INSERT INTO `sys_dictionary_details` VALUES (28, '2020-07-05 15:53:25', '2020-07-05 15:53:25', NULL, 'char', 0, 1, 0, 6);
INSERT INTO `sys_dictionary_details` VALUES (29, '2020-07-05 15:53:29', '2020-07-05 15:53:29', NULL, 'varchar', 1, 1, 1, 6);
INSERT INTO `sys_dictionary_details` VALUES (30, '2020-07-05 15:53:35', '2020-07-05 15:53:35', NULL, 'tinyblob', 2, 1, 2, 6);
INSERT INTO `sys_dictionary_details` VALUES (31, '2020-07-05 15:53:40', '2020-07-05 15:53:40', NULL, 'tinytext', 3, 1, 3, 6);
INSERT INTO `sys_dictionary_details` VALUES (32, '2020-07-05 15:53:48', '2020-07-05 15:53:48', NULL, 'text', 4, 1, 4, 6);
INSERT INTO `sys_dictionary_details` VALUES (33, '2020-07-05 15:53:55', '2020-07-05 15:53:55', NULL, 'blob', 5, 1, 5, 6);
INSERT INTO `sys_dictionary_details` VALUES (34, '2020-07-05 15:54:02', '2020-07-05 15:54:02', NULL, 'mediumblob', 6, 1, 6, 6);
INSERT INTO `sys_dictionary_details` VALUES (35, '2020-07-05 15:54:09', '2020-07-05 15:54:09', NULL, 'mediumtext', 7, 1, 7, 6);
INSERT INTO `sys_dictionary_details` VALUES (36, '2020-07-05 15:54:16', '2020-07-05 15:54:16', NULL, 'longblob', 8, 1, 8, 6);
INSERT INTO `sys_dictionary_details` VALUES (37, '2020-07-05 15:54:24', '2020-07-05 15:54:24', NULL, 'longtext', 9, 1, 9, 6);
INSERT INTO `sys_apis` VALUES (91, '2020-06-29 13:21:35', '2020-06-29 13:21:35', NULL, NULL, '/sysOperationRecord/createSysOperationRecord', '新增操作记录', 'sysOperationRecord', 'POST');
INSERT INTO `sys_apis` VALUES (92, '2020-06-29 13:21:35', '2020-06-29 13:21:35', NULL, NULL, '/sysOperationRecord/deleteSysOperationRecord', '删除操作记录', 'sysOperationRecord', 'DELETE');
INSERT INTO `sys_apis` VALUES (93, '2020-06-29 13:21:35', '2020-06-29 13:21:35', NULL, NULL, '/sysOperationRecord/updateSysOperationRecord', '更新操作记录', 'sysOperationRecord', 'PUT');
INSERT INTO `sys_apis` VALUES (94, '2020-06-29 13:21:35', '2020-06-29 13:21:35', NULL, NULL, '/sysOperationRecord/findSysOperationRecord', '根据ID获取操作记录', 'sysOperationRecord', 'GET');
INSERT INTO `sys_apis` VALUES (95, '2020-06-29 13:21:35', '2020-06-29 13:21:35', NULL, NULL, '/sysOperationRecord/getSysOperationRecordList', '获取操作记录列表', 'sysOperationRecord', 'GET');
INSERT INTO `sys_apis` VALUES (96, '2020-07-05 14:34:20', '2020-07-05 14:34:20', NULL, NULL, '/autoCode/getTables', '获取数据库表', 'autoCode', 'GET');
INSERT INTO `sys_apis` VALUES (97, '2020-07-05 15:02:07', '2020-07-05 15:02:07', NULL, NULL, '/autoCode/getDB', '获取所有数据库', 'autoCode', 'GET');
INSERT INTO `sys_apis` VALUES (98, '2020-07-05 16:32:08', '2020-07-05 16:32:08', NULL, NULL, '/autoCode/getColume', '获取所选table的所有字段', 'autoCode', 'GET');
INSERT INTO `sys_apis` VALUES (99, '2020-07-07 15:59:53', '2020-07-07 15:59:53', NULL, NULL, '/sysOperationRecord/deleteSysOperationRecordByIds', '批量删除操作历史', 'sysOperationRecord', 'DELETE');
-- ----------------------------
-- Table structure for sys_operation_records
-- ----------------------------
DROP TABLE IF EXISTS `sys_operation_records`;
CREATE TABLE `sys_operation_records` (
`id` int(10) UNSIGNED NOT NULL AUTO_INCREMENT,
`created_at` datetime(0) NULL DEFAULT NULL,
`updated_at` datetime(0) NULL DEFAULT NULL,
`deleted_at` datetime(0) NULL DEFAULT NULL,
`ip` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '请求ip',
`method` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '请求方法',
`path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL COMMENT '请求路由',
`status` int(11) NULL DEFAULT NULL COMMENT '状态',
`latency` bigint(20) NULL DEFAULT NULL,
`agent` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`error_message` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL DEFAULT NULL,
`body` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT '请求Body',
`user_id` int(11) NULL DEFAULT NULL COMMENT '用户id',
`resp` text CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NULL COMMENT '响应Body',
PRIMARY KEY (`id`) USING BTREE,
INDEX `idx_sys_operation_records_deleted_at`(`deleted_at`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 342 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_bin ROW_FORMAT = Compact;
INSERT INTO `casbin_rule` VALUES ('p', '888', '/sysOperationRecord/createSysOperationRecord', 'POST', '', '', '');
INSERT INTO `casbin_rule` VALUES ('p', '888', '/sysOperationRecord/deleteSysOperationRecord', 'DELETE', '', '', '');
INSERT INTO `casbin_rule` VALUES ('p', '888', '/sysOperationRecord/updateSysOperationRecord', 'PUT', '', '', '');
INSERT INTO `casbin_rule` VALUES ('p', '888', '/sysOperationRecord/findSysOperationRecord', 'GET', '', '', '');
INSERT INTO `casbin_rule` VALUES ('p', '888', '/sysOperationRecord/getSysOperationRecordList', 'GET', '', '', '');
INSERT INTO `casbin_rule` VALUES ('p', '888', '/sysOperationRecord/deleteSysOperationRecordByIds', 'DELETE', '', '', '');
INSERT INTO `casbin_rule` VALUES ('p', '888', '/autoCode/getTables', 'GET', '', '', '');
INSERT INTO `casbin_rule` VALUES ('p', '888', '/autoCode/getDB', 'GET', '', '', '');
INSERT INTO `casbin_rule` VALUES ('p', '888', '/autoCode/getColume', 'GET', '', '', '');
INSERT INTO `sys_authority_menus` VALUES ('888', 52);
-- 2020/07/08版本更新补丁
-- 增加了共自动化用的字典
-- 增加了操作记录 menu
-- 增加了操作记录相关api
-- 增加了操作记录表
-- 增加了角色和操作记录关联api
-- 增加了角色和menu关联记录
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
......@@ -53,6 +53,10 @@ definitions:
properties:
accessKey:
type: string
bucket:
type: string
imgPath:
type: string
secretKey:
type: string
type: object
......@@ -123,6 +127,10 @@ definitions:
properties:
abbreviation:
type: string
autoCreateApiToSql:
type: boolean
description:
type: string
fields:
items:
$ref: '#/definitions/model.Field'
......@@ -131,6 +139,8 @@ definitions:
type: string
structName:
type: string
tableName:
type: string
type: object
model.ExaCustomer:
properties:
......@@ -161,10 +171,20 @@ definitions:
properties:
columnName:
type: string
comment:
type: string
dataType:
type: string
dataTypeLong:
type: string
fieldDesc:
type: string
fieldJson:
type: string
fieldName:
type: string
fieldSearchType:
type: string
fieldType:
type: string
type: object
......@@ -237,6 +257,60 @@ definitions:
title:
type: string
type: object
model.SysDictionary:
properties:
desc:
type: string
name:
type: string
status:
type: boolean
sysDictionaryDetails:
items:
$ref: '#/definitions/model.SysDictionaryDetail'
type: array
type:
type: string
type: object
model.SysDictionaryDetail:
properties:
label:
type: string
sort:
type: integer
status:
type: boolean
sysDictionaryID:
type: integer
value:
type: integer
type: object
model.SysOperationRecord:
properties:
agent:
type: string
body:
type: string
error_message:
type: string
ip:
type: string
latency:
type: string
method:
type: string
path:
type: string
resp:
type: string
status:
type: integer
user:
$ref: '#/definitions/model.SysUser'
type: object
user_id:
type: integer
type: object
model.SysUser:
properties:
authority:
......@@ -385,13 +459,79 @@ definitions:
uuid:
type: string
type: object
request.SysDictionaryDetailSearch:
properties:
label:
type: string
page:
type: integer
pageSize:
type: integer
sort:
type: integer
status:
type: boolean
sysDictionaryID:
type: integer
value:
type: integer
type: object
request.SysDictionarySearch:
properties:
desc:
type: string
name:
type: string
page:
type: integer
pageSize:
type: integer
status:
type: boolean
sysDictionaryDetails:
items:
$ref: '#/definitions/model.SysDictionaryDetail'
type: array
type:
type: string
type: object
request.SysOperationRecordSearch:
properties:
agent:
type: string
body:
type: string
error_message:
type: string
ip:
type: string
latency:
type: string
method:
type: string
page:
type: integer
pageSize:
type: integer
path:
type: string
resp:
type: string
status:
type: integer
user:
$ref: '#/definitions/model.SysUser'
type: object
user_id:
type: integer
type: object
response.SysAuthorityCopyResponse:
properties:
authority:
$ref: '#/definitions/model.SysAuthority'
type: object
oldAuthorityId:
type: integer
type: string
type: object
info:
contact: {}
......@@ -704,24 +844,24 @@ paths:
summary: 自动代码模板
tags:
- SysApi
/base/captcha:
post:
/autoCode/getDatabase:
get:
consumes:
- application/json
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"获取成功"}'
description: '{"success":true,"data":{},"msg":"创建成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 生成验证码
summary: 获取当前表所有字段
tags:
- base
/base/captcha/:
get:
- SysApi
/base/captcha:
post:
consumes:
- application/json
produces:
......@@ -733,7 +873,7 @@ paths:
type: string
security:
- ApiKeyAuth: []
summary: 生成验证码图片路径
summary: 生成验证码
tags:
- base
/base/login:
......@@ -1327,6 +1467,366 @@ paths:
summary: 更新菜单
tags:
- menu
/sysDictionary/createSysDictionary:
post:
consumes:
- application/json
parameters:
- description: 创建SysDictionary
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysDictionary'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"获取成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 创建SysDictionary
tags:
- SysDictionary
/sysDictionary/deleteSysDictionary:
delete:
consumes:
- application/json
parameters:
- description: 删除SysDictionary
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysDictionary'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"删除成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 删除SysDictionary
tags:
- SysDictionary
/sysDictionary/findSysDictionary:
get:
consumes:
- application/json
parameters:
- description: 用id查询SysDictionary
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysDictionary'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"查询成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 用id查询SysDictionary
tags:
- SysDictionary
/sysDictionary/getSysDictionaryList:
get:
consumes:
- application/json
parameters:
- description: 分页获取SysDictionary列表
in: body
name: data
required: true
schema:
$ref: '#/definitions/request.SysDictionarySearch'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"获取成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 分页获取SysDictionary列表
tags:
- SysDictionary
/sysDictionary/updateSysDictionary:
put:
consumes:
- application/json
parameters:
- description: 更新SysDictionary
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysDictionary'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"更新成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 更新SysDictionary
tags:
- SysDictionary
/sysDictionaryDetail/createSysDictionaryDetail:
post:
consumes:
- application/json
parameters:
- description: 创建SysDictionaryDetail
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysDictionaryDetail'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"获取成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 创建SysDictionaryDetail
tags:
- SysDictionaryDetail
/sysDictionaryDetail/deleteSysDictionaryDetail:
delete:
consumes:
- application/json
parameters:
- description: 删除SysDictionaryDetail
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysDictionaryDetail'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"删除成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 删除SysDictionaryDetail
tags:
- SysDictionaryDetail
/sysDictionaryDetail/findSysDictionaryDetail:
get:
consumes:
- application/json
parameters:
- description: 用id查询SysDictionaryDetail
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysDictionaryDetail'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"查询成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 用id查询SysDictionaryDetail
tags:
- SysDictionaryDetail
/sysDictionaryDetail/getSysDictionaryDetailList:
get:
consumes:
- application/json
parameters:
- description: 分页获取SysDictionaryDetail列表
in: body
name: data
required: true
schema:
$ref: '#/definitions/request.SysDictionaryDetailSearch'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"获取成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 分页获取SysDictionaryDetail列表
tags:
- SysDictionaryDetail
/sysDictionaryDetail/updateSysDictionaryDetail:
put:
consumes:
- application/json
parameters:
- description: 更新SysDictionaryDetail
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysDictionaryDetail'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"更新成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 更新SysDictionaryDetail
tags:
- SysDictionaryDetail
/sysOperationRecord/createSysOperationRecord:
post:
consumes:
- application/json
parameters:
- description: 创建SysOperationRecord
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysOperationRecord'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"获取成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 创建SysOperationRecord
tags:
- SysOperationRecord
/sysOperationRecord/deleteSysOperationRecord:
delete:
consumes:
- application/json
parameters:
- description: 删除SysOperationRecord
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysOperationRecord'
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:
- application/json
parameters:
- description: 用id查询SysOperationRecord
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysOperationRecord'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"查询成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 用id查询SysOperationRecord
tags:
- SysOperationRecord
/sysOperationRecord/getSysOperationRecordList:
get:
consumes:
- application/json
parameters:
- description: 分页获取SysOperationRecord列表
in: body
name: data
required: true
schema:
$ref: '#/definitions/request.SysOperationRecordSearch'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"获取成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 分页获取SysOperationRecord列表
tags:
- SysOperationRecord
/sysOperationRecord/updateSysOperationRecord:
put:
consumes:
- application/json
parameters:
- description: 更新SysOperationRecord
in: body
name: data
required: true
schema:
$ref: '#/definitions/model.SysOperationRecord'
type: object
produces:
- application/json
responses:
"200":
description: '{"success":true,"data":{},"msg":"更新成功"}'
schema:
type: string
security:
- ApiKeyAuth: []
summary: 更新SysOperationRecord
tags:
- SysOperationRecord
/system/ReloadSystem:
post:
parameters:
......@@ -1417,7 +1917,7 @@ paths:
name: data
required: true
schema:
$ref: '#/definitions/request.SetUserAuth'
$ref: '#/definitions/request.GetById'
type: object
produces:
- application/json
......
......@@ -6,16 +6,16 @@ require (
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751
github.com/casbin/casbin v1.9.1
github.com/casbin/gorm-adapter v1.0.0
github.com/dchest/captcha v0.0.0-20170622155422-6a29415a8364
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/fastly/go-utils v0.0.0-20180712184237-d95a45783239 // indirect
github.com/fsnotify/fsnotify v1.4.9
github.com/fvbock/endless v0.0.0-20170109170031-447134032cb6
github.com/gin-gonic/gin v1.6.3
github.com/go-openapi/spec v0.19.7 // indirect
github.com/go-openapi/swag v0.19.8 // indirect
github.com/go-playground/validator/v10 v10.3.0 // indirect
github.com/go-redis/redis v6.15.7+incompatible
github.com/go-sql-driver/mysql v1.5.0 // indirect
github.com/go-sql-driver/mysql v1.5.0
github.com/golang/protobuf v1.4.2 // indirect
github.com/jehiah/go-strftime v0.0.0-20171201141054-1d33003b3869 // indirect
github.com/jinzhu/gorm v1.9.12
......@@ -26,14 +26,15 @@ require (
github.com/lib/pq v1.3.0 // indirect
github.com/mailru/easyjson v0.7.1 // indirect
github.com/mitchellh/mapstructure v1.2.2 // indirect
github.com/mojocn/base64Captcha v1.3.1
github.com/onsi/ginkgo v1.7.0 // indirect
github.com/onsi/gomega v1.4.3 // indirect
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7
github.com/pelletier/go-toml v1.6.0 // indirect
github.com/piexlmax/gvaplug v0.0.5
github.com/piexlmax/gvaplug v0.0.8
github.com/pkg/errors v0.9.1 // indirect
github.com/qiniu/api.v7 v7.2.5+incompatible
github.com/qiniu/x v7.0.8+incompatible // indirect
github.com/qiniu/api.v7/v7 v7.4.1
github.com/qiniu/x v1.10.5
github.com/satori/go.uuid v1.2.0
github.com/spf13/afero v1.2.2 // indirect
github.com/spf13/cast v1.3.1 // indirect
......@@ -51,5 +52,4 @@ require (
google.golang.org/protobuf v1.24.0 // indirect
gopkg.in/ini.v1 v1.55.0 // indirect
gopkg.in/yaml.v2 v2.3.0 // indirect
qiniupkg.com/x v7.0.8+incompatible // indirect
)
......@@ -15,10 +15,13 @@ func DBTables() {
model.JwtBlacklist{},
model.SysWorkflow{},
model.SysWorkflowStepInfo{},
model.SysDictionary{},
model.SysDictionaryDetail{},
model.ExaFileUploadAndDownload{},
model.ExaFile{},
model.ExaFileChunk{},
model.ExaCustomer{},
model.SysOperationRecord{},
)
global.GVA_LOG.Debug("register table success")
}
......@@ -6,20 +6,18 @@ import (
)
type Plug interface {
InitRouter(*gin.Engine) error
InitRouter([2]*gin.RouterGroup) error
InitModel(*gorm.DB) error
}
func InstallPlug(db *gorm.DB, router *gin.Engine, p ...Plug) (err error) {
for _, v := range p {
err = v.InitModel(db)
if err != nil {
return err
}
err = v.InitRouter(router)
if err != nil {
return err
}
func InstallPlug(db *gorm.DB, router [2]*gin.RouterGroup, p Plug) (err error) {
err = p.InitModel(db)
if err != nil {
return err
}
err = p.InitRouter(router)
if err != nil {
return err
}
return nil
}
......@@ -35,6 +35,9 @@ func Routers() *gin.Engine {
router.InitSystemRouter(ApiGroup) // system相关路由
router.InitCustomerRouter(ApiGroup) // 客户路由
router.InitAutoCodeRouter(ApiGroup) // 创建自动化代码
router.InitSysDictionaryDetailRouter(ApiGroup) // 字典详情管理
router.InitSysDictionaryRouter(ApiGroup) // 字典管理
router.InitSysOperationRecordRouter(ApiGroup) // 操作记录
global.GVA_LOG.Info("router register success")
return Router
}
package middleware
import (
"bytes"
"gin-vue-admin/global"
"gin-vue-admin/model"
"gin-vue-admin/service"
"github.com/gin-gonic/gin"
"io/ioutil"
"net/http"
"strconv"
"time"
)
func OperationRecord() gin.HandlerFunc {
return func(c *gin.Context) {
var body []byte
if c.Request.Method != http.MethodGet {
var err error
body, err = ioutil.ReadAll(c.Request.Body)
if err != nil {
global.GVA_LOG.Error("read body from request error:", err)
} else {
c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))
}
}
userId, err := strconv.Atoi(c.Request.Header.Get("x-user-id"))
if err != nil {
userId = 0
}
record := model.SysOperationRecord{
Ip: c.ClientIP(),
Method: c.Request.Method,
Path: c.Request.URL.Path,
Agent: c.Request.UserAgent(),
Body: string(body),
UserId: userId,
}
writer := responseBodyWriter{
ResponseWriter: c.Writer,
body: &bytes.Buffer{},
}
c.Writer = writer
now := time.Now()
c.Next()
latency := time.Now().Sub(now)
record.ErrorMessage = c.Errors.ByType(gin.ErrorTypePrivate).String()
record.Status = c.Writer.Status()
record.Latency = latency
record.Resp = writer.body.String()
if err := service.CreateSysOperationRecord(record); err != nil {
global.GVA_LOG.Error("create operation record error:", err)
}
}
}
type responseBodyWriter struct {
gin.ResponseWriter
body *bytes.Buffer
}
func (r responseBodyWriter) Write(b []byte) (int, error) {
r.body.Write(b)
return r.ResponseWriter.Write(b)
}
......@@ -10,3 +10,7 @@ type PageInfo struct {
type GetById struct {
Id float64 `json:"id" form:"id"`
}
type IdsReq struct {
Ids []int `json:"ids" form:"ids"`
}
\ No newline at end of file
package request
type DBReq struct {
Database string `json:"database";gorm:"column:database"`
}
type TableReq struct {
TableName string `json:"tableName"`
}
type ColumeReq struct {
ColumeName string `json:"columeName";gorm:"column:colume_name"`
DataType string `json:"dataType";gorm:"column:data_type"`
DataTypeLong string `json:"dataTypeLong";gorm:"column:data_type_long"`
ColumeComment string `json:"columeComment";gorm:"column:colume_comment"`
}
package request
import "gin-vue-admin/model"
type SysDictionarySearch struct{
model.SysDictionary
PageInfo
}
\ No newline at end of file
package request
import "gin-vue-admin/model"
type SysDictionaryDetailSearch struct{
model.SysDictionaryDetail
PageInfo
}
\ No newline at end of file
package request
import "gin-vue-admin/model"
type SysOperationRecordSearch struct {
model.SysOperationRecord
PageInfo
}
......@@ -3,6 +3,7 @@ package model
// 初始版本自动化代码工具
type AutoCodeStruct struct {
StructName string `json:"structName"`
TableName string `json:"tableName"`
PackageName string `json:"packageName"`
Abbreviation string `json:"abbreviation"`
Description string `json:"description"`
......@@ -15,6 +16,8 @@ type Field struct {
FieldDesc string `json:"fieldDesc"`
FieldType string `json:"fieldType"`
FieldJson string `json:"fieldJson"`
DataType string `json:"dataType"`
DataTypeLong string `json:"dataTypeLong"`
Comment string `json:"comment"`
ColumnName string `json:"columnName"`
FieldSearchType string `json:"fieldSearchType"`
......
// 自动生成模板SysDictionary
package model
import (
"github.com/jinzhu/gorm"
)
// 如果含有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:'描述'"`
SysDictionaryDetails []SysDictionaryDetail `json:"sysDictionaryDetails" form:"sysDictionaryDetails"`
}
// 自动生成模板SysDictionaryDetail
package model
import (
"github.com/jinzhu/gorm"
)
// 如果含有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:'关联标记'"`
}
\ No newline at end of file
// 自动生成模板SysOperationRecord
package model
import (
"github.com/jinzhu/gorm"
"time"
)
// 如果含有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:"column:resp;comment:'响应Body'"`
UserId int `json:"user_id" form:"user_id" gorm:"column:user_id;comment:''"`
User SysUser `json:"user"`
}
......@@ -33,6 +33,22 @@ export const create{{.StructName}} = (data) => {
})
}
// @Tags {{.StructName}}
// @Summary 删除{{.StructName}}
// @Security ApiKeyAuth
// @accept application/json
// @Produce application/json
// @Param data body request.IdsReq true "批量删除{{.StructName}}"
// @Success 200 {string} string "{"success":true,"data":{},"msg":"删除成功"}"
// @Router /{{.Abbreviation}}/delete{{.StructName}} [delete]
export const delete{{.StructName}}ByIds = (data) => {
return service({
url: "/{{.Abbreviation}}/delete{{.StructName}}ByIds",
method: 'delete',
data
})
}
// @Tags {{.StructName}}
// @Summary 更新{{.StructName}}
// @Security ApiKeyAuth
......
......@@ -7,10 +7,11 @@ import (
)
func Init{{.StructName}}Router(Router *gin.RouterGroup) {
{{.StructName}}Router := Router.Group("{{.Abbreviation}}").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler())
{{.StructName}}Router := Router.Group("{{.Abbreviation}}").Use(middleware.JWTAuth()).Use(middleware.CasbinHandler()).Use(middleware.OperationRecord())
{
{{.StructName}}Router.POST("create{{.StructName}}", v1.Create{{.StructName}}) // 新建{{.StructName}}
{{.StructName}}Router.DELETE("delete{{.StructName}}", v1.Delete{{.StructName}}) // 删除{{.StructName}}
{{.StructName}}Router.DELETE("delete{{.StructName}}ByIds", v1.Delete{{.StructName}}ByIds) // 批量删除{{.StructName}}
{{.StructName}}Router.PUT("update{{.StructName}}", v1.Update{{.StructName}}) // 更新{{.StructName}}
{{.StructName}}Router.GET("find{{.StructName}}", v1.Find{{.StructName}}) // 根据ID获取{{.StructName}}
{{.StructName}}Router.GET("get{{.StructName}}List", v1.Get{{.StructName}}List) // 获取{{.StructName}}列表
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册