mirror of
https://github.com/flipped-aurora/gin-vue-admin.git
synced 2026-09-21 20:35:16 +00:00
基础架构变更 增加模块化
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
package system
|
||||
|
||||
type ServiceGroup struct {
|
||||
JwtService
|
||||
ApiService
|
||||
AuthorityService
|
||||
AutoCodeService
|
||||
AutoCodeHistoryService
|
||||
BaseMenuService
|
||||
CasbinService
|
||||
DictionaryService
|
||||
DictionaryDetailService
|
||||
EmailService
|
||||
InitDBService
|
||||
MenuService
|
||||
OperationRecordService
|
||||
SystemConfigService
|
||||
UserService
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/system"
|
||||
"time"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type JwtService struct {
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: JsonInBlacklist
|
||||
//@description: 拉黑jwt
|
||||
//@param: jwtList model.JwtBlacklist
|
||||
//@return: err error
|
||||
|
||||
func (jwtService *JwtService) JsonInBlacklist(jwtList system.JwtBlacklist) (err error) {
|
||||
err = global.GVA_DB.Create(&jwtList).Error
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: IsBlacklist
|
||||
//@description: 判断JWT是否在黑名单内部
|
||||
//@param: jwt string
|
||||
//@return: bool
|
||||
|
||||
func (jwtService *JwtService) IsBlacklist(jwt string) bool {
|
||||
err := global.GVA_DB.Where("jwt = ?", jwt).First(&system.JwtBlacklist{}).Error
|
||||
isNotFound := errors.Is(err, gorm.ErrRecordNotFound)
|
||||
return !isNotFound
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetRedisJWT
|
||||
//@description: 从redis取jwt
|
||||
//@param: userName string
|
||||
//@return: err error, redisJWT string
|
||||
|
||||
func (jwtService *JwtService) GetRedisJWT(userName string) (err error, redisJWT string) {
|
||||
redisJWT, err = global.GVA_REDIS.Get(context.Background(), userName).Result()
|
||||
return err, redisJWT
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: SetRedisJWT
|
||||
//@description: jwt存入redis并设置过期时间
|
||||
//@param: jwt string, userName string
|
||||
//@return: err error
|
||||
|
||||
func (jwtService *JwtService) SetRedisJWT(jwt string, userName string) (err error) {
|
||||
// 此处过期时间等于jwt过期时间
|
||||
timer := time.Duration(global.GVA_CONFIG.JWT.ExpiresTime) * time.Second
|
||||
err = global.GVA_REDIS.Set(context.Background(), userName, jwt, timer).Err()
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/common/request"
|
||||
"gin-vue-admin/model/system"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateApi
|
||||
//@description: 新增基础api
|
||||
//@param: api model.SysApi
|
||||
//@return: err error
|
||||
|
||||
type ApiService struct {
|
||||
}
|
||||
|
||||
var ApiServiceApp = new(ApiService)
|
||||
|
||||
func (apiService *ApiService) CreateApi(api system.SysApi) (err error) {
|
||||
if !errors.Is(global.GVA_DB.Where("path = ? AND method = ?", api.Path, api.Method).First(&system.SysApi{}).Error, gorm.ErrRecordNotFound) {
|
||||
return errors.New("存在相同api")
|
||||
}
|
||||
return global.GVA_DB.Create(&api).Error
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteApi
|
||||
//@description: 删除基础api
|
||||
//@param: api model.SysApi
|
||||
//@return: err error
|
||||
|
||||
func (apiService *ApiService) DeleteApi(api system.SysApi) (err error) {
|
||||
err = global.GVA_DB.Delete(&api).Error
|
||||
CasbinServiceApp.ClearCasbin(1, api.Path, api.Method)
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetAPIInfoList
|
||||
//@description: 分页获取数据,
|
||||
//@param: api model.SysApi, info request.PageInfo, order string, desc bool
|
||||
//@return: err error
|
||||
|
||||
func (apiService *ApiService) GetAPIInfoList(api system.SysApi, info request.PageInfo, order string, desc bool) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
db := global.GVA_DB.Model(&system.SysApi{})
|
||||
var apiList []system.SysApi
|
||||
|
||||
if api.Path != "" {
|
||||
db = db.Where("path LIKE ?", "%"+api.Path+"%")
|
||||
}
|
||||
|
||||
if api.Description != "" {
|
||||
db = db.Where("description LIKE ?", "%"+api.Description+"%")
|
||||
}
|
||||
|
||||
if api.Method != "" {
|
||||
db = db.Where("method = ?", api.Method)
|
||||
}
|
||||
|
||||
if api.ApiGroup != "" {
|
||||
db = db.Where("api_group = ?", api.ApiGroup)
|
||||
}
|
||||
|
||||
err = db.Count(&total).Error
|
||||
|
||||
if err != nil {
|
||||
return err, apiList, total
|
||||
} else {
|
||||
db = db.Limit(limit).Offset(offset)
|
||||
if order != "" {
|
||||
var OrderStr string
|
||||
if desc {
|
||||
OrderStr = order + " desc"
|
||||
} else {
|
||||
OrderStr = order
|
||||
}
|
||||
err = db.Order(OrderStr).Find(&apiList).Error
|
||||
} else {
|
||||
err = db.Order("api_group").Find(&apiList).Error
|
||||
}
|
||||
}
|
||||
return err, apiList, total
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetAllApis
|
||||
//@description: 获取所有的api
|
||||
//@return: err error, apis []model.SysApi
|
||||
|
||||
func (apiService *ApiService) GetAllApis() (err error, apis []system.SysApi) {
|
||||
err = global.GVA_DB.Find(&apis).Error
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetApiById
|
||||
//@description: 根据id获取api
|
||||
//@param: id float64
|
||||
//@return: err error, api model.SysApi
|
||||
|
||||
func (apiService *ApiService) GetApiById(id float64) (err error, api system.SysApi) {
|
||||
err = global.GVA_DB.Where("id = ?", id).First(&api).Error
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UpdateApi
|
||||
//@description: 根据id更新api
|
||||
//@param: api model.SysApi
|
||||
//@return: err error
|
||||
|
||||
func (apiService *ApiService) UpdateApi(api system.SysApi) (err error) {
|
||||
var oldA system.SysApi
|
||||
err = global.GVA_DB.Where("id = ?", api.ID).First(&oldA).Error
|
||||
if oldA.Path != api.Path || oldA.Method != api.Method {
|
||||
if !errors.Is(global.GVA_DB.Where("path = ? AND method = ?", api.Path, api.Method).First(&system.SysApi{}).Error, gorm.ErrRecordNotFound) {
|
||||
return errors.New("存在相同api路径")
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
err = CasbinServiceApp.UpdateCasbinApi(oldA.Path, api.Path, oldA.Method, api.Method)
|
||||
if err != nil {
|
||||
return err
|
||||
} else {
|
||||
err = global.GVA_DB.Save(&api).Error
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteApis
|
||||
//@description: 删除选中API
|
||||
//@param: apis []model.SysApi
|
||||
//@return: err error
|
||||
|
||||
func (apiService *ApiService) DeleteApisByIds(ids request.IdsReq) (err error) {
|
||||
err = global.GVA_DB.Delete(&[]system.SysApi{}, "id in ?", ids.Ids).Error
|
||||
return err
|
||||
}
|
||||
|
||||
func (apiService *ApiService) DeleteApiByIds(ids []string) (err error) {
|
||||
return global.GVA_DB.Delete(system.SysApi{}, ids).Error
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/common/request"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/model/system/response"
|
||||
"gorm.io/gorm"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateAuthority
|
||||
//@description: 创建一个角色
|
||||
//@param: auth model.SysAuthority
|
||||
//@return: err error, authority model.SysAuthority
|
||||
|
||||
type AuthorityService struct {
|
||||
}
|
||||
|
||||
var AuthorityServiceApp = new(AuthorityService)
|
||||
|
||||
func (authorityService *AuthorityService) CreateAuthority(auth system.SysAuthority) (err error, authority system.SysAuthority) {
|
||||
var authorityBox system.SysAuthority
|
||||
if !errors.Is(global.GVA_DB.Where("authority_id = ?", auth.AuthorityId).First(&authorityBox).Error, gorm.ErrRecordNotFound) {
|
||||
return errors.New("存在相同角色id"), auth
|
||||
}
|
||||
err = global.GVA_DB.Create(&auth).Error
|
||||
return err, auth
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CopyAuthority
|
||||
//@description: 复制一个角色
|
||||
//@param: copyInfo response.SysAuthorityCopyResponse
|
||||
//@return: err error, authority model.SysAuthority
|
||||
|
||||
func (authorityService *AuthorityService) CopyAuthority(copyInfo response.SysAuthorityCopyResponse) (err error, authority system.SysAuthority) {
|
||||
var authorityBox system.SysAuthority
|
||||
if !errors.Is(global.GVA_DB.Where("authority_id = ?", copyInfo.Authority.AuthorityId).First(&authorityBox).Error, gorm.ErrRecordNotFound) {
|
||||
return errors.New("存在相同角色id"), authority
|
||||
}
|
||||
copyInfo.Authority.Children = []system.SysAuthority{}
|
||||
err, menus := MenuServiceApp.GetMenuAuthority(&request.GetAuthorityId{AuthorityId: copyInfo.OldAuthorityId})
|
||||
var baseMenu []system.SysBaseMenu
|
||||
for _, v := range menus {
|
||||
intNum, _ := strconv.Atoi(v.MenuId)
|
||||
v.SysBaseMenu.ID = uint(intNum)
|
||||
baseMenu = append(baseMenu, v.SysBaseMenu)
|
||||
}
|
||||
copyInfo.Authority.SysBaseMenus = baseMenu
|
||||
err = global.GVA_DB.Create(©Info.Authority).Error
|
||||
|
||||
paths := CasbinServiceApp.GetPolicyPathByAuthorityId(copyInfo.OldAuthorityId)
|
||||
err = CasbinServiceApp.UpdateCasbin(copyInfo.Authority.AuthorityId, paths)
|
||||
if err != nil {
|
||||
_ = authorityService.DeleteAuthority(©Info.Authority)
|
||||
}
|
||||
return err, copyInfo.Authority
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UpdateAuthority
|
||||
//@description: 更改一个角色
|
||||
//@param: auth model.SysAuthority
|
||||
//@return: err error, authority model.SysAuthority
|
||||
|
||||
func (authorityService *AuthorityService) UpdateAuthority(auth system.SysAuthority) (err error, authority system.SysAuthority) {
|
||||
err = global.GVA_DB.Where("authority_id = ?", auth.AuthorityId).First(&system.SysAuthority{}).Updates(&auth).Error
|
||||
return err, auth
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteAuthority
|
||||
//@description: 删除角色
|
||||
//@param: auth *model.SysAuthority
|
||||
//@return: err error
|
||||
|
||||
func (authorityService *AuthorityService) DeleteAuthority(auth *system.SysAuthority) (err error) {
|
||||
if !errors.Is(global.GVA_DB.Where("authority_id = ?", auth.AuthorityId).First(&system.SysUser{}).Error, gorm.ErrRecordNotFound) {
|
||||
return errors.New("此角色有用户正在使用禁止删除")
|
||||
}
|
||||
if !errors.Is(global.GVA_DB.Where("parent_id = ?", auth.AuthorityId).First(&system.SysAuthority{}).Error, gorm.ErrRecordNotFound) {
|
||||
return errors.New("此角色存在子角色不允许删除")
|
||||
}
|
||||
db := global.GVA_DB.Preload("SysBaseMenus").Where("authority_id = ?", auth.AuthorityId).First(auth)
|
||||
err = db.Unscoped().Delete(auth).Error
|
||||
if len(auth.SysBaseMenus) > 0 {
|
||||
err = global.GVA_DB.Model(auth).Association("SysBaseMenus").Delete(auth.SysBaseMenus)
|
||||
//err = db.Association("SysBaseMenus").Delete(&auth)
|
||||
} else {
|
||||
err = db.Error
|
||||
}
|
||||
CasbinServiceApp.ClearCasbin(0, auth.AuthorityId)
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetAuthorityInfoList
|
||||
//@description: 分页获取数据
|
||||
//@param: info request.PageInfo
|
||||
//@return: err error, list interface{}, total int64
|
||||
|
||||
func (authorityService *AuthorityService) GetAuthorityInfoList(info request.PageInfo) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
db := global.GVA_DB
|
||||
var authority []system.SysAuthority
|
||||
err = db.Limit(limit).Offset(offset).Preload("DataAuthorityId").Where("parent_id = 0").Find(&authority).Error
|
||||
if len(authority) > 0 {
|
||||
for k := range authority {
|
||||
err = authorityService.findChildrenAuthority(&authority[k])
|
||||
}
|
||||
}
|
||||
return err, authority, total
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetAuthorityInfo
|
||||
//@description: 获取所有角色信息
|
||||
//@param: auth model.SysAuthority
|
||||
//@return: err error, sa model.SysAuthority
|
||||
|
||||
func (authorityService *AuthorityService) GetAuthorityInfo(auth system.SysAuthority) (err error, sa system.SysAuthority) {
|
||||
err = global.GVA_DB.Preload("DataAuthorityId").Where("authority_id = ?", auth.AuthorityId).First(&sa).Error
|
||||
return err, sa
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: SetDataAuthority
|
||||
//@description: 设置角色资源权限
|
||||
//@param: auth model.SysAuthority
|
||||
//@return: error
|
||||
|
||||
func (authorityService *AuthorityService) SetDataAuthority(auth system.SysAuthority) error {
|
||||
var s system.SysAuthority
|
||||
global.GVA_DB.Preload("DataAuthorityId").First(&s, "authority_id = ?", auth.AuthorityId)
|
||||
err := global.GVA_DB.Model(&s).Association("DataAuthorityId").Replace(&auth.DataAuthorityId)
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: SetMenuAuthority
|
||||
//@description: 菜单与角色绑定
|
||||
//@param: auth *model.SysAuthority
|
||||
//@return: error
|
||||
|
||||
func (authorityService *AuthorityService) SetMenuAuthority(auth *system.SysAuthority) error {
|
||||
var s system.SysAuthority
|
||||
global.GVA_DB.Preload("SysBaseMenus").First(&s, "authority_id = ?", auth.AuthorityId)
|
||||
err := global.GVA_DB.Model(&s).Association("SysBaseMenus").Replace(&auth.SysBaseMenus)
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: findChildrenAuthority
|
||||
//@description: 查询子角色
|
||||
//@param: authority *model.SysAuthority
|
||||
//@return: err error
|
||||
|
||||
func (authorityService *AuthorityService) findChildrenAuthority(authority *system.SysAuthority) (err error) {
|
||||
err = global.GVA_DB.Preload("DataAuthorityId").Where("parent_id = ?", authority.AuthorityId).Find(&authority.Children).Error
|
||||
if len(authority.Children) > 0 {
|
||||
for k := range authority.Children {
|
||||
err = authorityService.findChildrenAuthority(&authority.Children[k])
|
||||
}
|
||||
}
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,449 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/model/system/request"
|
||||
"gin-vue-admin/utils"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"strings"
|
||||
"text/template"
|
||||
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const (
|
||||
autoPath = "autoCode/"
|
||||
basePath = "resource/template"
|
||||
)
|
||||
|
||||
type tplData struct {
|
||||
template *template.Template
|
||||
locationPath string
|
||||
autoCodePath string
|
||||
autoMoveFilePath string
|
||||
}
|
||||
|
||||
type AutoCodeService struct {
|
||||
}
|
||||
|
||||
var AutoCodeServiceApp = new(AutoCodeService)
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: PreviewTemp
|
||||
//@description: 预览创建代码
|
||||
//@param: model.AutoCodeStruct
|
||||
//@return: map[string]string, error
|
||||
|
||||
func (autoCodeService *AutoCodeService) PreviewTemp(autoCode system.AutoCodeStruct) (map[string]string, error) {
|
||||
dataList, _, needMkdir, err := autoCodeService.getNeedList(&autoCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 写入文件前,先创建文件夹
|
||||
if err = utils.CreateDir(needMkdir...); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 创建map
|
||||
ret := make(map[string]string)
|
||||
|
||||
// 生成map
|
||||
for _, value := range dataList {
|
||||
ext := ""
|
||||
if ext = filepath.Ext(value.autoCodePath); ext == ".txt" {
|
||||
continue
|
||||
}
|
||||
f, err := os.OpenFile(value.autoCodePath, os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err = value.template.Execute(f, autoCode); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
_ = f.Close()
|
||||
f, err = os.OpenFile(value.autoCodePath, os.O_CREATE|os.O_RDONLY, 0755)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder := strings.Builder{}
|
||||
builder.WriteString("```")
|
||||
|
||||
if ext != "" && strings.Contains(ext, ".") {
|
||||
builder.WriteString(strings.Replace(ext, ".", "", -1))
|
||||
}
|
||||
builder.WriteString("\n\n")
|
||||
data, err := ioutil.ReadAll(f)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
builder.Write(data)
|
||||
builder.WriteString("\n\n```")
|
||||
|
||||
pathArr := strings.Split(value.autoCodePath, string(os.PathSeparator))
|
||||
ret[pathArr[1]+"-"+pathArr[3]] = builder.String()
|
||||
_ = f.Close()
|
||||
|
||||
}
|
||||
defer func() { // 移除中间文件
|
||||
if err := os.RemoveAll(autoPath); err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
return ret, nil
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateTemp
|
||||
//@description: 创建代码
|
||||
//@param: model.AutoCodeStruct
|
||||
//@return: err error
|
||||
|
||||
func (autoCodeService *AutoCodeService) CreateTemp(autoCode system.AutoCodeStruct, ids ...uint) (err error) {
|
||||
dataList, fileList, needMkdir, err := autoCodeService.getNeedList(&autoCode)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
meta, _ := json.Marshal(autoCode)
|
||||
// 写入文件前,先创建文件夹
|
||||
if err = utils.CreateDir(needMkdir...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// 生成文件
|
||||
for _, value := range dataList {
|
||||
f, err := os.OpenFile(value.autoCodePath, os.O_CREATE|os.O_WRONLY, 0755)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = value.template.Execute(f, autoCode); err != nil {
|
||||
return err
|
||||
}
|
||||
_ = f.Close()
|
||||
}
|
||||
|
||||
defer func() { // 移除中间文件
|
||||
if err := os.RemoveAll(autoPath); err != nil {
|
||||
return
|
||||
}
|
||||
}()
|
||||
bf := strings.Builder{}
|
||||
idBf := strings.Builder{}
|
||||
injectionCodeMeta := strings.Builder{}
|
||||
for _, id := range ids {
|
||||
idBf.WriteString(strconv.Itoa(int(id)))
|
||||
idBf.WriteString(";")
|
||||
}
|
||||
if autoCode.AutoMoveFile { // 判断是否需要自动转移
|
||||
for index := range dataList {
|
||||
autoCodeService.addAutoMoveFile(&dataList[index])
|
||||
}
|
||||
for _, value := range dataList { // 移动文件
|
||||
if err := utils.FileMove(value.autoCodePath, value.autoMoveFilePath); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
initializeGormFilePath := filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Server, global.GVA_CONFIG.AutoCode.SInitialize, "gorm.go")
|
||||
initializeRouterFilePath := filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Server, global.GVA_CONFIG.AutoCode.SInitialize, "router.go")
|
||||
err = utils.AutoInjectionCode(initializeGormFilePath, "MysqlTables", "model."+autoCode.StructName+"{},")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = utils.AutoInjectionCode(initializeRouterFilePath, "Routers", "router.Init"+autoCode.StructName+"Router(PrivateGroup)")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
injectionCodeMeta.WriteString(fmt.Sprintf("%s@%s@%s", initializeGormFilePath, "MysqlTables", "model."+autoCode.StructName+"{},"))
|
||||
injectionCodeMeta.WriteString(";")
|
||||
injectionCodeMeta.WriteString(fmt.Sprintf("%s@%s@%s", initializeRouterFilePath, "Routers", "router.Init"+autoCode.StructName+"Router(PrivateGroup)"))
|
||||
|
||||
// 保存生成信息
|
||||
for _, data := range dataList {
|
||||
if len(data.autoMoveFilePath) != 0 {
|
||||
bf.WriteString(data.autoMoveFilePath)
|
||||
bf.WriteString(";")
|
||||
}
|
||||
}
|
||||
|
||||
if global.GVA_CONFIG.AutoCode.TransferRestart {
|
||||
go func() {
|
||||
_ = utils.Reload()
|
||||
}()
|
||||
}
|
||||
//return errors.New("创建代码成功并移动文件成功")
|
||||
} else { // 打包
|
||||
if err = utils.ZipFiles("./ginvueadmin.zip", fileList, ".", "."); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if autoCode.AutoMoveFile || autoCode.AutoCreateApiToSql {
|
||||
if autoCode.TableName != "" {
|
||||
err = AutoCodeHistoryServiceApp.CreateAutoCodeHistory(
|
||||
string(meta),
|
||||
autoCode.StructName,
|
||||
autoCode.Description,
|
||||
bf.String(),
|
||||
injectionCodeMeta.String(),
|
||||
autoCode.TableName,
|
||||
idBf.String(),
|
||||
)
|
||||
} else {
|
||||
err = AutoCodeHistoryServiceApp.CreateAutoCodeHistory(
|
||||
string(meta),
|
||||
autoCode.StructName,
|
||||
autoCode.Description,
|
||||
bf.String(),
|
||||
injectionCodeMeta.String(),
|
||||
autoCode.StructName,
|
||||
idBf.String(),
|
||||
)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if autoCode.AutoMoveFile {
|
||||
return errors.New("创建代码成功并移动文件成功")
|
||||
}
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetAllTplFile
|
||||
//@description: 获取 pathName 文件夹下所有 tpl 文件
|
||||
//@param: pathName string, fileList []string
|
||||
//@return: []string, error
|
||||
|
||||
func (autoCodeService *AutoCodeService) GetAllTplFile(pathName string, fileList []string) ([]string, error) {
|
||||
files, err := ioutil.ReadDir(pathName)
|
||||
for _, fi := range files {
|
||||
if fi.IsDir() {
|
||||
fileList, err = autoCodeService.GetAllTplFile(pathName+"/"+fi.Name(), fileList)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
if strings.HasSuffix(fi.Name(), ".tpl") {
|
||||
fileList = append(fileList, pathName+"/"+fi.Name())
|
||||
}
|
||||
}
|
||||
}
|
||||
return fileList, err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetTables
|
||||
//@description: 获取数据库的所有表名
|
||||
//@param: dbName string
|
||||
//@return: err error, TableNames []request.TableReq
|
||||
|
||||
func (autoCodeService *AutoCodeService) GetTables(dbName string) (err error, TableNames []request.TableReq) {
|
||||
err = global.GVA_DB.Raw("select table_name as table_name from information_schema.tables where table_schema = ?", dbName).Scan(&TableNames).Error
|
||||
return err, TableNames
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetDB
|
||||
//@description: 获取数据库的所有数据库名
|
||||
//@return: err error, DBNames []request.DBReq
|
||||
|
||||
func (autoCodeService *AutoCodeService) GetDB() (err error, DBNames []request.DBReq) {
|
||||
err = global.GVA_DB.Raw("SELECT SCHEMA_NAME AS `database` FROM INFORMATION_SCHEMA.SCHEMATA;").Scan(&DBNames).Error
|
||||
return err, DBNames
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetDB
|
||||
//@description: 获取指定数据库和指定数据表的所有字段名,类型值等
|
||||
//@param: tableName string, dbName string
|
||||
//@return: err error, Columns []request.ColumnReq
|
||||
|
||||
func (autoCodeService *AutoCodeService) GetColumn(tableName string, dbName string) (err error, Columns []request.ColumnReq) {
|
||||
err = global.GVA_DB.Raw("SELECT COLUMN_NAME column_name,DATA_TYPE data_type,CASE DATA_TYPE WHEN 'longtext' THEN c.CHARACTER_MAXIMUM_LENGTH WHEN 'varchar' THEN c.CHARACTER_MAXIMUM_LENGTH WHEN 'double' THEN CONCAT_WS( ',', c.NUMERIC_PRECISION, c.NUMERIC_SCALE ) WHEN 'decimal' THEN CONCAT_WS( ',', c.NUMERIC_PRECISION, c.NUMERIC_SCALE ) WHEN 'int' THEN c.NUMERIC_PRECISION WHEN 'bigint' THEN c.NUMERIC_PRECISION ELSE '' END AS data_type_long,COLUMN_COMMENT column_comment FROM INFORMATION_SCHEMA.COLUMNS c WHERE table_name = ? AND table_schema = ?", tableName, dbName).Scan(&Columns).Error
|
||||
return err, Columns
|
||||
}
|
||||
|
||||
func (autoCodeService *AutoCodeService) DropTable(tableName string) error {
|
||||
return global.GVA_DB.Exec("DROP TABLE " + tableName).Error
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: addAutoMoveFile
|
||||
//@description: 生成对应的迁移文件路径
|
||||
//@param: *tplData
|
||||
//@return: null
|
||||
|
||||
func (autoCodeService *AutoCodeService) addAutoMoveFile(data *tplData) {
|
||||
base := filepath.Base(data.autoCodePath)
|
||||
fileSlice := strings.Split(data.autoCodePath, string(os.PathSeparator))
|
||||
n := len(fileSlice)
|
||||
if n <= 2 {
|
||||
return
|
||||
}
|
||||
if strings.Contains(fileSlice[1], "server") {
|
||||
if strings.Contains(fileSlice[n-2], "router") {
|
||||
data.autoMoveFilePath = filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server,
|
||||
global.GVA_CONFIG.AutoCode.SRouter, base)
|
||||
} else if strings.Contains(fileSlice[n-2], "api") {
|
||||
data.autoMoveFilePath = filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Server, global.GVA_CONFIG.AutoCode.SApi, base)
|
||||
} else if strings.Contains(fileSlice[n-2], "service") {
|
||||
data.autoMoveFilePath = filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Server, global.GVA_CONFIG.AutoCode.SService, base)
|
||||
} else if strings.Contains(fileSlice[n-2], "model") {
|
||||
data.autoMoveFilePath = filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Server, global.GVA_CONFIG.AutoCode.SModel, base)
|
||||
} else if strings.Contains(fileSlice[n-2], "request") {
|
||||
data.autoMoveFilePath = filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Server, global.GVA_CONFIG.AutoCode.SRequest, base)
|
||||
}
|
||||
} else if strings.Contains(fileSlice[1], "web") {
|
||||
if strings.Contains(fileSlice[n-1], "js") {
|
||||
data.autoMoveFilePath = filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Web, global.GVA_CONFIG.AutoCode.WApi, base)
|
||||
} else if strings.Contains(fileSlice[n-2], "form") {
|
||||
data.autoMoveFilePath = filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Web, global.GVA_CONFIG.AutoCode.WForm, filepath.Base(filepath.Dir(filepath.Dir(data.autoCodePath))), strings.TrimSuffix(base, filepath.Ext(base))+"Form.vue")
|
||||
} else if strings.Contains(fileSlice[n-2], "table") {
|
||||
data.autoMoveFilePath = filepath.Join(global.GVA_CONFIG.AutoCode.Root,
|
||||
global.GVA_CONFIG.AutoCode.Web, global.GVA_CONFIG.AutoCode.WTable, filepath.Base(filepath.Dir(filepath.Dir(data.autoCodePath))), base)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: CreateApi
|
||||
//@description: 自动创建api数据,
|
||||
//@param: a *model.AutoCodeStruct
|
||||
//@return: err error
|
||||
|
||||
func (autoCodeService *AutoCodeService) AutoCreateApi(a *system.AutoCodeStruct) (ids []uint, err error) {
|
||||
var apiList = []system.SysApi{
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "create" + a.StructName,
|
||||
Description: "新增" + a.Description,
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "POST",
|
||||
},
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "delete" + a.StructName,
|
||||
Description: "删除" + a.Description,
|
||||
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,
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "PUT",
|
||||
},
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "find" + a.StructName,
|
||||
Description: "根据ID获取" + a.Description,
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "GET",
|
||||
},
|
||||
{
|
||||
Path: "/" + a.Abbreviation + "/" + "get" + a.StructName + "List",
|
||||
Description: "获取" + a.Description + "列表",
|
||||
ApiGroup: a.Abbreviation,
|
||||
Method: "GET",
|
||||
},
|
||||
}
|
||||
err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
|
||||
for _, v := range apiList {
|
||||
var api system.SysApi
|
||||
if errors.Is(tx.Where("path = ? AND method = ?", v.Path, v.Method).First(&api).Error, gorm.ErrRecordNotFound) {
|
||||
if err = tx.Create(&v).Error; err != nil { // 遇到错误时回滚事务
|
||||
return err
|
||||
} else {
|
||||
ids = append(ids, v.ID)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return ids, err
|
||||
}
|
||||
|
||||
func (autoCodeService *AutoCodeService) getNeedList(autoCode *system.AutoCodeStruct) (dataList []tplData, fileList []string, needMkdir []string, err error) {
|
||||
// 去除所有空格
|
||||
utils.TrimSpace(autoCode)
|
||||
for _, field := range autoCode.Fields {
|
||||
utils.TrimSpace(field)
|
||||
}
|
||||
// 获取 basePath 文件夹下所有tpl文件
|
||||
tplFileList, err := autoCodeService.GetAllTplFile(basePath, nil)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
dataList = make([]tplData, 0, len(tplFileList))
|
||||
fileList = make([]string, 0, len(tplFileList))
|
||||
needMkdir = make([]string, 0, len(tplFileList)) // 当文件夹下存在多个tpl文件时,改为map更合理
|
||||
// 根据文件路径生成 tplData 结构体,待填充数据
|
||||
for _, value := range tplFileList {
|
||||
dataList = append(dataList, tplData{locationPath: value})
|
||||
}
|
||||
// 生成 *Template, 填充 template 字段
|
||||
for index, value := range dataList {
|
||||
dataList[index].template, err = template.ParseFiles(value.locationPath)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
}
|
||||
// 生成文件路径,填充 autoCodePath 字段,readme.txt.tpl不符合规则,需要特殊处理
|
||||
// resource/template/web/api.js.tpl -> autoCode/web/autoCode.PackageName/api/autoCode.PackageName.js
|
||||
// resource/template/readme.txt.tpl -> autoCode/readme.txt
|
||||
autoPath := "autoCode/"
|
||||
for index, value := range dataList {
|
||||
trimBase := strings.TrimPrefix(value.locationPath, basePath+"/")
|
||||
if trimBase == "readme.txt.tpl" {
|
||||
dataList[index].autoCodePath = autoPath + "readme.txt"
|
||||
continue
|
||||
}
|
||||
|
||||
if lastSeparator := strings.LastIndex(trimBase, "/"); lastSeparator != -1 {
|
||||
origFileName := strings.TrimSuffix(trimBase[lastSeparator+1:], ".tpl")
|
||||
firstDot := strings.Index(origFileName, ".")
|
||||
if firstDot != -1 {
|
||||
var fileName string
|
||||
if origFileName[firstDot:] != ".go" {
|
||||
fileName = autoCode.PackageName + origFileName[firstDot:]
|
||||
} else {
|
||||
fileName = autoCode.HumpPackageName + origFileName[firstDot:]
|
||||
}
|
||||
|
||||
dataList[index].autoCodePath = filepath.Join(autoPath, trimBase[:lastSeparator], autoCode.PackageName,
|
||||
origFileName[:firstDot], fileName)
|
||||
}
|
||||
}
|
||||
|
||||
if lastSeparator := strings.LastIndex(dataList[index].autoCodePath, string(os.PathSeparator)); lastSeparator != -1 {
|
||||
needMkdir = append(needMkdir, dataList[index].autoCodePath[:lastSeparator])
|
||||
}
|
||||
}
|
||||
for _, value := range dataList {
|
||||
fileList = append(fileList, value.autoCodePath)
|
||||
}
|
||||
return dataList, fileList, needMkdir, err
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/common/request"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/utils"
|
||||
"strings"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
type AutoCodeHistoryService struct {
|
||||
}
|
||||
|
||||
var AutoCodeHistoryServiceApp = new(AutoCodeHistoryService)
|
||||
|
||||
// CreateAutoCodeHistory RouterPath : RouterPath@RouterString;RouterPath2@RouterString2
|
||||
func (autoCodeHistoryService *AutoCodeHistoryService) CreateAutoCodeHistory(meta, structName, structCNName, autoCodePath string, injectionMeta string, tableName string, apiIds string) error {
|
||||
return global.GVA_DB.Create(&system.SysAutoCodeHistory{
|
||||
RequestMeta: meta,
|
||||
AutoCodePath: autoCodePath,
|
||||
InjectionMeta: injectionMeta,
|
||||
StructName: structName,
|
||||
StructCNName: structCNName,
|
||||
TableName: tableName,
|
||||
ApiIDs: apiIds,
|
||||
}).Error
|
||||
}
|
||||
|
||||
// RollBack 回滚
|
||||
func (autoCodeHistoryService *AutoCodeHistoryService) RollBack(id uint) error {
|
||||
md := system.SysAutoCodeHistory{}
|
||||
if err := global.GVA_DB.First(&md, id).Error; err != nil {
|
||||
return err
|
||||
}
|
||||
// 清除API表
|
||||
err := ApiServiceApp.DeleteApiByIds(strings.Split(md.ApiIDs, ";"))
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("ClearTag DeleteApiByIds:", zap.Error(err))
|
||||
}
|
||||
// 获取全部表名
|
||||
err, dbNames := AutoCodeServiceApp.GetTables(global.GVA_CONFIG.Mysql.Dbname)
|
||||
if err != nil {
|
||||
global.GVA_LOG.Error("ClearTag GetTables:", zap.Error(err))
|
||||
}
|
||||
// 删除表
|
||||
for _, name := range dbNames {
|
||||
if strings.Contains(strings.ToUpper(strings.Replace(name.TableName, "_", "", -1)), strings.ToUpper(md.TableName)) {
|
||||
// 删除表
|
||||
if err = AutoCodeServiceApp.DropTable(name.TableName); err != nil {
|
||||
global.GVA_LOG.Error("ClearTag DropTable:", zap.Error(err))
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// 删除文件
|
||||
for _, path := range strings.Split(md.AutoCodePath, ";") {
|
||||
_ = utils.DeLFile(path)
|
||||
}
|
||||
// 清除注入
|
||||
for _, v := range strings.Split(md.InjectionMeta, ";") {
|
||||
// RouterPath@functionName@RouterString
|
||||
meta := strings.Split(v, "@")
|
||||
if len(meta) == 3 {
|
||||
_ = utils.AutoClearCode(meta[0], meta[2])
|
||||
}
|
||||
}
|
||||
md.Flag = 1
|
||||
return global.GVA_DB.Save(&md).Error
|
||||
}
|
||||
|
||||
func (autoCodeHistoryService *AutoCodeHistoryService) GetMeta(id uint) (string, error) {
|
||||
var meta string
|
||||
return meta, global.GVA_DB.Model(system.SysAutoCodeHistory{}).Select("request_meta").First(&meta, id).Error
|
||||
}
|
||||
|
||||
// GetSysHistoryPage 获取系统历史数据
|
||||
func (autoCodeHistoryService *AutoCodeHistoryService) GetSysHistoryPage(info request.PageInfo) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
db := global.GVA_DB
|
||||
var fileLists []system.SysAutoCodeHistory
|
||||
err = db.Find(&fileLists).Count(&total).Error
|
||||
err = db.Limit(limit).Offset(offset).Order("updated_at desc").Select("id,created_at,updated_at,struct_name,struct_cn_name,flag,table_name").Find(&fileLists).Error
|
||||
return err, fileLists, total
|
||||
}
|
||||
|
||||
// DeletePage 删除历史数据
|
||||
func (autoCodeHistoryService *AutoCodeHistoryService) DeletePage(id uint) error {
|
||||
return global.GVA_DB.Delete(system.SysAutoCodeHistory{}, id).Error
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/system"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type BaseMenuService struct {
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteBaseMenu
|
||||
//@description: 删除基础路由
|
||||
//@param: id float64
|
||||
//@return: err error
|
||||
|
||||
func (baseMenuService *BaseMenuService) DeleteBaseMenu(id float64) (err error) {
|
||||
err = global.GVA_DB.Preload("Parameters").Where("parent_id = ?", id).First(&system.SysBaseMenu{}).Error
|
||||
if err != nil {
|
||||
var menu system.SysBaseMenu
|
||||
db := global.GVA_DB.Preload("SysAuthoritys").Where("id = ?", id).First(&menu).Delete(&menu)
|
||||
err = global.GVA_DB.Delete(&system.SysBaseMenuParameter{}, "sys_base_menu_id = ?", id).Error
|
||||
if len(menu.SysAuthoritys) > 0 {
|
||||
err = global.GVA_DB.Model(&menu).Association("SysAuthoritys").Delete(&menu.SysAuthoritys)
|
||||
} else {
|
||||
err = db.Error
|
||||
}
|
||||
} else {
|
||||
return errors.New("此菜单存在子菜单不可删除")
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UpdateBaseMenu
|
||||
//@description: 更新路由
|
||||
//@param: menu model.SysBaseMenu
|
||||
//@return: err error
|
||||
|
||||
func (baseMenuService *BaseMenuService) UpdateBaseMenu(menu system.SysBaseMenu) (err error) {
|
||||
var oldMenu system.SysBaseMenu
|
||||
upDateMap := make(map[string]interface{})
|
||||
upDateMap["keep_alive"] = menu.KeepAlive
|
||||
upDateMap["close_tab"] = menu.CloseTab
|
||||
upDateMap["default_menu"] = menu.DefaultMenu
|
||||
upDateMap["parent_id"] = menu.ParentId
|
||||
upDateMap["path"] = menu.Path
|
||||
upDateMap["name"] = menu.Name
|
||||
upDateMap["hidden"] = menu.Hidden
|
||||
upDateMap["component"] = menu.Component
|
||||
upDateMap["title"] = menu.Title
|
||||
upDateMap["icon"] = menu.Icon
|
||||
upDateMap["sort"] = menu.Sort
|
||||
|
||||
err = global.GVA_DB.Transaction(func(tx *gorm.DB) error {
|
||||
db := tx.Where("id = ?", menu.ID).Find(&oldMenu)
|
||||
if oldMenu.Name != menu.Name {
|
||||
if !errors.Is(tx.Where("id <> ? AND name = ?", menu.ID, menu.Name).First(&system.SysBaseMenu{}).Error, gorm.ErrRecordNotFound) {
|
||||
global.GVA_LOG.Debug("存在相同name修改失败")
|
||||
return errors.New("存在相同name修改失败")
|
||||
}
|
||||
}
|
||||
txErr := tx.Unscoped().Delete(&system.SysBaseMenuParameter{}, "sys_base_menu_id = ?", menu.ID).Error
|
||||
if txErr != nil {
|
||||
global.GVA_LOG.Debug(txErr.Error())
|
||||
return txErr
|
||||
}
|
||||
if len(menu.Parameters) > 0 {
|
||||
for k := range menu.Parameters {
|
||||
menu.Parameters[k].SysBaseMenuID = menu.ID
|
||||
}
|
||||
txErr = tx.Create(&menu.Parameters).Error
|
||||
if txErr != nil {
|
||||
global.GVA_LOG.Debug(txErr.Error())
|
||||
return txErr
|
||||
}
|
||||
}
|
||||
|
||||
txErr = db.Updates(upDateMap).Error
|
||||
if txErr != nil {
|
||||
global.GVA_LOG.Debug(txErr.Error())
|
||||
return txErr
|
||||
}
|
||||
return nil
|
||||
})
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetBaseMenuById
|
||||
//@description: 返回当前选中menu
|
||||
//@param: id float64
|
||||
//@return: err error, menu model.SysBaseMenu
|
||||
|
||||
func (baseMenuService *BaseMenuService) GetBaseMenuById(id float64) (err error, menu system.SysBaseMenu) {
|
||||
err = global.GVA_DB.Preload("Parameters").Where("id = ?", id).First(&menu).Error
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/model/system/request"
|
||||
"github.com/casbin/casbin/v2"
|
||||
"github.com/casbin/casbin/v2/util"
|
||||
gormadapter "github.com/casbin/gorm-adapter/v3"
|
||||
_ "github.com/go-sql-driver/mysql"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UpdateCasbin
|
||||
//@description: 更新casbin权限
|
||||
//@param: authorityId string, casbinInfos []request.CasbinInfo
|
||||
//@return: error
|
||||
|
||||
type CasbinService struct {
|
||||
}
|
||||
|
||||
var CasbinServiceApp = new(CasbinService)
|
||||
|
||||
func (casbinService *CasbinService) UpdateCasbin(authorityId string, casbinInfos []request.CasbinInfo) error {
|
||||
casbinService.ClearCasbin(0, authorityId)
|
||||
rules := [][]string{}
|
||||
for _, v := range casbinInfos {
|
||||
cm := system.CasbinModel{
|
||||
Ptype: "p",
|
||||
AuthorityId: authorityId,
|
||||
Path: v.Path,
|
||||
Method: v.Method,
|
||||
}
|
||||
rules = append(rules, []string{cm.AuthorityId, cm.Path, cm.Method})
|
||||
}
|
||||
e := casbinService.Casbin()
|
||||
success, _ := e.AddPolicies(rules)
|
||||
if success == false {
|
||||
return errors.New("存在相同api,添加失败,请联系管理员")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UpdateCasbinApi
|
||||
//@description: API更新随动
|
||||
//@param: oldPath string, newPath string, oldMethod string, newMethod string
|
||||
//@return: error
|
||||
|
||||
func (casbinService *CasbinService) UpdateCasbinApi(oldPath string, newPath string, oldMethod string, newMethod string) error {
|
||||
err := global.GVA_DB.Table("casbin_rule").Model(&system.CasbinModel{}).Where("v1 = ? AND v2 = ?", oldPath, oldMethod).Updates(map[string]interface{}{
|
||||
"v1": newPath,
|
||||
"v2": newMethod,
|
||||
}).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetPolicyPathByAuthorityId
|
||||
//@description: 获取权限列表
|
||||
//@param: authorityId string
|
||||
//@return: pathMaps []request.CasbinInfo
|
||||
|
||||
func (casbinService *CasbinService) GetPolicyPathByAuthorityId(authorityId string) (pathMaps []request.CasbinInfo) {
|
||||
e := casbinService.Casbin()
|
||||
list := e.GetFilteredPolicy(0, authorityId)
|
||||
for _, v := range list {
|
||||
pathMaps = append(pathMaps, request.CasbinInfo{
|
||||
Path: v[1],
|
||||
Method: v[2],
|
||||
})
|
||||
}
|
||||
return pathMaps
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: ClearCasbin
|
||||
//@description: 清除匹配的权限
|
||||
//@param: v int, p ...string
|
||||
//@return: bool
|
||||
|
||||
func (casbinService *CasbinService) ClearCasbin(v int, p ...string) bool {
|
||||
e := casbinService.Casbin()
|
||||
success, _ := e.RemoveFilteredPolicy(v, p...)
|
||||
return success
|
||||
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Casbin
|
||||
//@description: 持久化到数据库 引入自定义规则
|
||||
//@return: *casbin.Enforcer
|
||||
|
||||
var (
|
||||
syncedEnforcer *casbin.SyncedEnforcer
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
func (casbinService *CasbinService) Casbin() *casbin.SyncedEnforcer {
|
||||
once.Do(func() {
|
||||
a, _ := gormadapter.NewAdapterByDB(global.GVA_DB)
|
||||
syncedEnforcer, _ = casbin.NewSyncedEnforcer(global.GVA_CONFIG.Casbin.ModelPath, a)
|
||||
syncedEnforcer.AddFunction("ParamsMatch", casbinService.ParamsMatchFunc)
|
||||
})
|
||||
_ = syncedEnforcer.LoadPolicy()
|
||||
return syncedEnforcer
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: ParamsMatch
|
||||
//@description: 自定义规则函数
|
||||
//@param: fullNameKey1 string, key2 string
|
||||
//@return: bool
|
||||
|
||||
func (casbinService *CasbinService) ParamsMatch(fullNameKey1 string, key2 string) bool {
|
||||
key1 := strings.Split(fullNameKey1, "?")[0]
|
||||
// 剥离路径后再使用casbin的keyMatch2
|
||||
return util.KeyMatch2(key1, key2)
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: ParamsMatchFunc
|
||||
//@description: 自定义规则函数
|
||||
//@param: args ...interface{}
|
||||
//@return: interface{}, error
|
||||
|
||||
func (casbinService *CasbinService) ParamsMatchFunc(args ...interface{}) (interface{}, error) {
|
||||
name1 := args[0].(string)
|
||||
name2 := args[1].(string)
|
||||
|
||||
return casbinService.ParamsMatch(name1, name2), nil
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/model/system/request"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteSysDictionary
|
||||
//@description: 创建字典数据
|
||||
//@param: sysDictionary model.SysDictionary
|
||||
//@return: err error
|
||||
|
||||
type DictionaryService struct {
|
||||
}
|
||||
|
||||
func (dictionaryService *DictionaryService) CreateSysDictionary(sysDictionary system.SysDictionary) (err error) {
|
||||
if (!errors.Is(global.GVA_DB.First(&system.SysDictionary{}, "type = ?", sysDictionary.Type).Error, gorm.ErrRecordNotFound)) {
|
||||
return errors.New("存在相同的type,不允许创建")
|
||||
}
|
||||
err = global.GVA_DB.Create(&sysDictionary).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteSysDictionary
|
||||
//@description: 删除字典数据
|
||||
//@param: sysDictionary model.SysDictionary
|
||||
//@return: err error
|
||||
|
||||
func (dictionaryService *DictionaryService) DeleteSysDictionary(sysDictionary system.SysDictionary) (err error) {
|
||||
err = global.GVA_DB.Delete(&sysDictionary).Delete(&sysDictionary.SysDictionaryDetails).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UpdateSysDictionary
|
||||
//@description: 更新字典数据
|
||||
//@param: sysDictionary *model.SysDictionary
|
||||
//@return: err error
|
||||
|
||||
func (dictionaryService *DictionaryService) UpdateSysDictionary(sysDictionary *system.SysDictionary) (err error) {
|
||||
var dict system.SysDictionary
|
||||
sysDictionaryMap := map[string]interface{}{
|
||||
"Name": sysDictionary.Name,
|
||||
"Type": sysDictionary.Type,
|
||||
"Status": sysDictionary.Status,
|
||||
"Desc": sysDictionary.Desc,
|
||||
}
|
||||
db := global.GVA_DB.Where("id = ?", sysDictionary.ID).First(&dict)
|
||||
if dict.Type == sysDictionary.Type {
|
||||
err = db.Updates(sysDictionaryMap).Error
|
||||
} else {
|
||||
if (!errors.Is(global.GVA_DB.First(&system.SysDictionary{}, "type = ?", sysDictionary.Type).Error, gorm.ErrRecordNotFound)) {
|
||||
return errors.New("存在相同的type,不允许创建")
|
||||
}
|
||||
err = db.Updates(sysDictionaryMap).Error
|
||||
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetSysDictionary
|
||||
//@description: 根据id或者type获取字典单条数据
|
||||
//@param: Type string, Id uint
|
||||
//@return: err error, sysDictionary model.SysDictionary
|
||||
|
||||
func (dictionaryService *DictionaryService) GetSysDictionary(Type string, Id uint) (err error, sysDictionary system.SysDictionary) {
|
||||
err = global.GVA_DB.Where("type = ? OR id = ?", Type, Id).Preload("SysDictionaryDetails").First(&sysDictionary).Error
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: GetSysDictionaryInfoList
|
||||
//@description: 分页获取字典列表
|
||||
//@param: info request.SysDictionarySearch
|
||||
//@return: err error, list interface{}, total int64
|
||||
|
||||
func (dictionaryService *DictionaryService) GetSysDictionaryInfoList(info request.SysDictionarySearch) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
// 创建db
|
||||
db := global.GVA_DB.Model(&system.SysDictionary{})
|
||||
var sysDictionarys []system.SysDictionary
|
||||
// 如果有条件搜索 下方会自动创建搜索语句
|
||||
if info.Name != "" {
|
||||
db = db.Where("`name` LIKE ?", "%"+info.Name+"%")
|
||||
}
|
||||
if info.Type != "" {
|
||||
db = db.Where("`type` LIKE ?", "%"+info.Type+"%")
|
||||
}
|
||||
if info.Status != nil {
|
||||
db = db.Where("`status` = ?", info.Status)
|
||||
}
|
||||
if info.Desc != "" {
|
||||
db = db.Where("`desc` LIKE ?", "%"+info.Desc+"%")
|
||||
}
|
||||
err = db.Count(&total).Error
|
||||
err = db.Limit(limit).Offset(offset).Find(&sysDictionarys).Error
|
||||
return err, sysDictionarys, total
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/model/system/request"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: CreateSysDictionaryDetail
|
||||
//@description: 创建字典详情数据
|
||||
//@param: sysDictionaryDetail model.SysDictionaryDetail
|
||||
//@return: err error
|
||||
|
||||
type DictionaryDetailService struct {
|
||||
}
|
||||
|
||||
func (dictionaryDetailService *DictionaryDetailService) CreateSysDictionaryDetail(sysDictionaryDetail system.SysDictionaryDetail) (err error) {
|
||||
err = global.GVA_DB.Create(&sysDictionaryDetail).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteSysDictionaryDetail
|
||||
//@description: 删除字典详情数据
|
||||
//@param: sysDictionaryDetail model.SysDictionaryDetail
|
||||
//@return: err error
|
||||
|
||||
func (dictionaryDetailService *DictionaryDetailService) DeleteSysDictionaryDetail(sysDictionaryDetail system.SysDictionaryDetail) (err error) {
|
||||
err = global.GVA_DB.Delete(&sysDictionaryDetail).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: UpdateSysDictionaryDetail
|
||||
//@description: 更新字典详情数据
|
||||
//@param: sysDictionaryDetail *model.SysDictionaryDetail
|
||||
//@return: err error
|
||||
|
||||
func (dictionaryDetailService *DictionaryDetailService) UpdateSysDictionaryDetail(sysDictionaryDetail *system.SysDictionaryDetail) (err error) {
|
||||
err = global.GVA_DB.Save(sysDictionaryDetail).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetSysDictionaryDetail
|
||||
//@description: 根据id获取字典详情单条数据
|
||||
//@param: id uint
|
||||
//@return: err error, sysDictionaryDetail model.SysDictionaryDetail
|
||||
|
||||
func (dictionaryDetailService *DictionaryDetailService) GetSysDictionaryDetail(id uint) (err error, sysDictionaryDetail system.SysDictionaryDetail) {
|
||||
err = global.GVA_DB.Where("id = ?", id).First(&sysDictionaryDetail).Error
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetSysDictionaryDetailInfoList
|
||||
//@description: 分页获取字典详情列表
|
||||
//@param: info request.SysDictionaryDetailSearch
|
||||
//@return: err error, list interface{}, total int64
|
||||
|
||||
func (dictionaryDetailService *DictionaryDetailService) GetSysDictionaryDetailInfoList(info request.SysDictionaryDetailSearch) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
// 创建db
|
||||
db := global.GVA_DB.Model(&system.SysDictionaryDetail{})
|
||||
var sysDictionaryDetails []system.SysDictionaryDetail
|
||||
// 如果有条件搜索 下方会自动创建搜索语句
|
||||
if info.Label != "" {
|
||||
db = db.Where("label LIKE ?", "%"+info.Label+"%")
|
||||
}
|
||||
if info.Value != 0 {
|
||||
db = db.Where("value = ?", info.Value)
|
||||
}
|
||||
if info.Status != nil {
|
||||
db = db.Where("status = ?", info.Status)
|
||||
}
|
||||
if info.SysDictionaryID != 0 {
|
||||
db = db.Where("sys_dictionary_id = ?", info.SysDictionaryID)
|
||||
}
|
||||
err = db.Count(&total).Error
|
||||
err = db.Limit(limit).Offset(offset).Find(&sysDictionaryDetails).Error
|
||||
return err, sysDictionaryDetails, total
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"gin-vue-admin/utils"
|
||||
)
|
||||
|
||||
type EmailService struct {
|
||||
}
|
||||
|
||||
//@author: [maplepie](https://github.com/maplepie)
|
||||
//@function: EmailTest
|
||||
//@description: 发送邮件测试
|
||||
//@return: err error
|
||||
|
||||
func (e *EmailService) EmailTest() (err error) {
|
||||
subject := "test"
|
||||
body := "test"
|
||||
err = utils.EmailTest(subject, body)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/example"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/model/system/request"
|
||||
"gin-vue-admin/source"
|
||||
"gin-vue-admin/utils"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/spf13/viper"
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: writeConfig
|
||||
//@description: 回写配置
|
||||
//@param: viper *viper.Viper, mysql config.Mysql
|
||||
//@return: error
|
||||
|
||||
type InitDBService struct {
|
||||
}
|
||||
|
||||
func (initDBService *InitDBService) writeConfig(viper *viper.Viper, mysql config.Mysql) error {
|
||||
global.GVA_CONFIG.Mysql = mysql
|
||||
cs := utils.StructToMap(global.GVA_CONFIG)
|
||||
for k, v := range cs {
|
||||
viper.Set(k, v)
|
||||
}
|
||||
return viper.WriteConfig()
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: createTable
|
||||
//@description: 创建数据库(mysql)
|
||||
//@param: dsn string, driver string, createSql
|
||||
//@return: error
|
||||
|
||||
func (initDBService *InitDBService) createTable(dsn string, driver string, createSql string) error {
|
||||
db, err := sql.Open(driver, dsn)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer func(db *sql.DB) {
|
||||
err := db.Close()
|
||||
if err != nil {
|
||||
|
||||
}
|
||||
}(db)
|
||||
if err = db.Ping(); err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = db.Exec(createSql)
|
||||
return err
|
||||
}
|
||||
|
||||
func (initDBService *InitDBService) initDB(InitDBFunctions ...system.InitDBFunc) (err error) {
|
||||
for _, v := range InitDBFunctions {
|
||||
err = v.Init()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//@author: [songzhibin97](https://github.com/songzhibin97)
|
||||
//@function: InitDB
|
||||
//@description: 创建数据库并初始化
|
||||
//@param: conf request.InitDB
|
||||
//@return: error
|
||||
|
||||
func (initDBService *InitDBService) InitDB(conf request.InitDB) error {
|
||||
|
||||
if conf.Host == "" {
|
||||
conf.Host = "127.0.0.1"
|
||||
}
|
||||
|
||||
if conf.Port == "" {
|
||||
conf.Port = "3306"
|
||||
}
|
||||
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/", conf.UserName, conf.Password, conf.Host, conf.Port)
|
||||
createSql := fmt.Sprintf("CREATE DATABASE IF NOT EXISTS `%s` DEFAULT CHARACTER SET utf8mb4 DEFAULT COLLATE utf8mb4_general_ci;", conf.DBName)
|
||||
if err := initDBService.createTable(dsn, "mysql", createSql); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
MysqlConfig := config.Mysql{
|
||||
Path: fmt.Sprintf("%s:%s", conf.Host, conf.Port),
|
||||
Dbname: conf.DBName,
|
||||
Username: conf.UserName,
|
||||
Password: conf.Password,
|
||||
Config: "charset=utf8mb4&parseTime=True&loc=Local",
|
||||
}
|
||||
|
||||
if MysqlConfig.Dbname == "" {
|
||||
return nil
|
||||
}
|
||||
|
||||
linkDns := MysqlConfig.Username + ":" + MysqlConfig.Password + "@tcp(" + MysqlConfig.Path + ")/" + MysqlConfig.Dbname + "?" + MysqlConfig.Config
|
||||
mysqlConfig := mysql.Config{
|
||||
DSN: linkDns, // DSN data source name
|
||||
DefaultStringSize: 191, // string 类型字段的默认长度
|
||||
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
|
||||
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
|
||||
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
|
||||
SkipInitializeWithVersion: false, // 根据版本自动配置
|
||||
}
|
||||
if db, err := gorm.Open(mysql.New(mysqlConfig), &gorm.Config{DisableForeignKeyConstraintWhenMigrating: true}); err != nil {
|
||||
return nil
|
||||
} else {
|
||||
sqlDB, _ := db.DB()
|
||||
sqlDB.SetMaxIdleConns(MysqlConfig.MaxIdleConns)
|
||||
sqlDB.SetMaxOpenConns(MysqlConfig.MaxOpenConns)
|
||||
global.GVA_DB = db
|
||||
}
|
||||
|
||||
err := global.GVA_DB.AutoMigrate(
|
||||
system.SysUser{},
|
||||
system.SysAuthority{},
|
||||
system.SysApi{},
|
||||
system.SysBaseMenu{},
|
||||
system.SysBaseMenuParameter{},
|
||||
system.JwtBlacklist{},
|
||||
system.SysDictionary{},
|
||||
system.SysDictionaryDetail{},
|
||||
example.ExaFileUploadAndDownload{},
|
||||
example.ExaFile{},
|
||||
example.ExaFileChunk{},
|
||||
example.ExaSimpleUploader{},
|
||||
example.ExaCustomer{},
|
||||
system.SysOperationRecord{},
|
||||
system.SysAutoCodeHistory{},
|
||||
)
|
||||
if err != nil {
|
||||
global.GVA_DB = nil
|
||||
return err
|
||||
}
|
||||
err = initDBService.initDB(
|
||||
source.Admin,
|
||||
source.Api,
|
||||
source.AuthorityMenu,
|
||||
source.Authority,
|
||||
source.AuthoritiesMenus,
|
||||
source.Casbin,
|
||||
source.DataAuthorities,
|
||||
source.Dictionary,
|
||||
source.DictionaryDetail,
|
||||
source.File,
|
||||
source.BaseMenu)
|
||||
if err != nil {
|
||||
global.GVA_DB = nil
|
||||
return err
|
||||
}
|
||||
if err = initDBService.writeConfig(global.GVA_VP, MysqlConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
global.GVA_CONFIG.AutoCode.Root, _ = filepath.Abs("..")
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/common/request"
|
||||
"gin-vue-admin/model/system"
|
||||
"gorm.io/gorm"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: getMenuTreeMap
|
||||
//@description: 获取路由总树map
|
||||
//@param: authorityId string
|
||||
//@return: err error, treeMap map[string][]model.SysMenu
|
||||
|
||||
type MenuService struct {
|
||||
}
|
||||
|
||||
var MenuServiceApp = new(MenuService)
|
||||
|
||||
func (menuService *MenuService) getMenuTreeMap(authorityId string) (err error, treeMap map[string][]system.SysMenu) {
|
||||
var allMenus []system.SysMenu
|
||||
treeMap = make(map[string][]system.SysMenu)
|
||||
err = global.GVA_DB.Where("authority_id = ?", authorityId).Order("sort").Preload("Parameters").Find(&allMenus).Error
|
||||
for _, v := range allMenus {
|
||||
treeMap[v.ParentId] = append(treeMap[v.ParentId], v)
|
||||
}
|
||||
return err, treeMap
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetMenuTree
|
||||
//@description: 获取动态菜单树
|
||||
//@param: authorityId string
|
||||
//@return: err error, menus []model.SysMenu
|
||||
|
||||
func (menuService *MenuService) GetMenuTree(authorityId string) (err error, menus []system.SysMenu) {
|
||||
err, menuTree := menuService.getMenuTreeMap(authorityId)
|
||||
menus = menuTree["0"]
|
||||
for i := 0; i < len(menus); i++ {
|
||||
err = menuService.getChildrenList(&menus[i], menuTree)
|
||||
}
|
||||
return err, menus
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: getChildrenList
|
||||
//@description: 获取子菜单
|
||||
//@param: menu *model.SysMenu, treeMap map[string][]model.SysMenu
|
||||
//@return: err error
|
||||
|
||||
func (menuService *MenuService) getChildrenList(menu *system.SysMenu, treeMap map[string][]system.SysMenu) (err error) {
|
||||
menu.Children = treeMap[menu.MenuId]
|
||||
for i := 0; i < len(menu.Children); i++ {
|
||||
err = menuService.getChildrenList(&menu.Children[i], treeMap)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetInfoList
|
||||
//@description: 获取路由分页
|
||||
//@return: err error, list interface{}, total int64
|
||||
|
||||
func (menuService *MenuService) GetInfoList() (err error, list interface{}, total int64) {
|
||||
var menuList []system.SysBaseMenu
|
||||
err, treeMap := menuService.getBaseMenuTreeMap()
|
||||
menuList = treeMap["0"]
|
||||
for i := 0; i < len(menuList); i++ {
|
||||
err = menuService.getBaseChildrenList(&menuList[i], treeMap)
|
||||
}
|
||||
return err, menuList, total
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: getBaseChildrenList
|
||||
//@description: 获取菜单的子菜单
|
||||
//@param: menu *model.SysBaseMenu, treeMap map[string][]model.SysBaseMenu
|
||||
//@return: err error
|
||||
|
||||
func (menuService *MenuService) getBaseChildrenList(menu *system.SysBaseMenu, treeMap map[string][]system.SysBaseMenu) (err error) {
|
||||
menu.Children = treeMap[strconv.Itoa(int(menu.ID))]
|
||||
for i := 0; i < len(menu.Children); i++ {
|
||||
err = menuService.getBaseChildrenList(&menu.Children[i], treeMap)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: AddBaseMenu
|
||||
//@description: 添加基础路由
|
||||
//@param: menu model.SysBaseMenu
|
||||
//@return: error
|
||||
|
||||
func (menuService *MenuService) AddBaseMenu(menu system.SysBaseMenu) error {
|
||||
if !errors.Is(global.GVA_DB.Where("name = ?", menu.Name).First(&system.SysBaseMenu{}).Error, gorm.ErrRecordNotFound) {
|
||||
return errors.New("存在重复name,请修改name")
|
||||
}
|
||||
return global.GVA_DB.Create(&menu).Error
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: getBaseMenuTreeMap
|
||||
//@description: 获取路由总树map
|
||||
//@return: err error, treeMap map[string][]model.SysBaseMenu
|
||||
|
||||
func (menuService *MenuService) getBaseMenuTreeMap() (err error, treeMap map[string][]system.SysBaseMenu) {
|
||||
var allMenus []system.SysBaseMenu
|
||||
treeMap = make(map[string][]system.SysBaseMenu)
|
||||
err = global.GVA_DB.Order("sort").Preload("Parameters").Find(&allMenus).Error
|
||||
for _, v := range allMenus {
|
||||
treeMap[v.ParentId] = append(treeMap[v.ParentId], v)
|
||||
}
|
||||
return err, treeMap
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetBaseMenuTree
|
||||
//@description: 获取基础路由树
|
||||
//@return: err error, menus []model.SysBaseMenu
|
||||
|
||||
func (menuService *MenuService) GetBaseMenuTree() (err error, menus []system.SysBaseMenu) {
|
||||
err, treeMap := menuService.getBaseMenuTreeMap()
|
||||
menus = treeMap["0"]
|
||||
for i := 0; i < len(menus); i++ {
|
||||
err = menuService.getBaseChildrenList(&menus[i], treeMap)
|
||||
}
|
||||
return err, menus
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: AddMenuAuthority
|
||||
//@description: 为角色增加menu树
|
||||
//@param: menus []model.SysBaseMenu, authorityId string
|
||||
//@return: err error
|
||||
|
||||
func (menuService *MenuService) AddMenuAuthority(menus []system.SysBaseMenu, authorityId string) (err error) {
|
||||
var auth system.SysAuthority
|
||||
auth.AuthorityId = authorityId
|
||||
auth.SysBaseMenus = menus
|
||||
err = AuthorityServiceApp.SetMenuAuthority(&auth)
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetMenuAuthority
|
||||
//@description: 查看当前角色树
|
||||
//@param: info *request.GetAuthorityId
|
||||
//@return: err error, menus []model.SysMenu
|
||||
|
||||
func (menuService *MenuService) GetMenuAuthority(info *request.GetAuthorityId) (err error, menus []system.SysMenu) {
|
||||
err = global.GVA_DB.Where("authority_id = ? ", info.AuthorityId).Order("sort").Find(&menus).Error
|
||||
//sql := "SELECT authority_menu.keep_alive,authority_menu.default_menu,authority_menu.created_at,authority_menu.updated_at,authority_menu.deleted_at,authority_menu.menu_level,authority_menu.parent_id,authority_menu.path,authority_menu.`name`,authority_menu.hidden,authority_menu.component,authority_menu.title,authority_menu.icon,authority_menu.sort,authority_menu.menu_id,authority_menu.authority_id FROM authority_menu WHERE authority_menu.authority_id = ? ORDER BY authority_menu.sort ASC"
|
||||
//err = global.GVA_DB.Raw(sql, authorityId).Scan(&menus).Error
|
||||
return err, menus
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/common/request"
|
||||
"gin-vue-admin/model/system"
|
||||
systemReq "gin-vue-admin/model/system/request"
|
||||
)
|
||||
|
||||
//@author: [granty1](https://github.com/granty1)
|
||||
//@function: CreateSysOperationRecord
|
||||
//@description: 创建记录
|
||||
//@param: sysOperationRecord model.SysOperationRecord
|
||||
//@return: err error
|
||||
|
||||
type OperationRecordService struct {
|
||||
}
|
||||
|
||||
func (operationRecordService *OperationRecordService) CreateSysOperationRecord(sysOperationRecord system.SysOperationRecord) (err error) {
|
||||
err = global.GVA_DB.Create(&sysOperationRecord).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [granty1](https://github.com/granty1)
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteSysOperationRecordByIds
|
||||
//@description: 批量删除记录
|
||||
//@param: ids request.IdsReq
|
||||
//@return: err error
|
||||
|
||||
func (operationRecordService *OperationRecordService) DeleteSysOperationRecordByIds(ids request.IdsReq) (err error) {
|
||||
err = global.GVA_DB.Delete(&[]system.SysOperationRecord{}, "id in (?)", ids.Ids).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [granty1](https://github.com/granty1)
|
||||
//@function: DeleteSysOperationRecord
|
||||
//@description: 删除操作记录
|
||||
//@param: sysOperationRecord model.SysOperationRecord
|
||||
//@return: err error
|
||||
|
||||
func (operationRecordService *OperationRecordService) DeleteSysOperationRecord(sysOperationRecord system.SysOperationRecord) (err error) {
|
||||
err = global.GVA_DB.Delete(&sysOperationRecord).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [granty1](https://github.com/granty1)
|
||||
//@function: DeleteSysOperationRecord
|
||||
//@description: 根据id获取单条操作记录
|
||||
//@param: id uint
|
||||
//@return: err error, sysOperationRecord model.SysOperationRecord
|
||||
|
||||
func (operationRecordService *OperationRecordService) GetSysOperationRecord(id uint) (err error, sysOperationRecord system.SysOperationRecord) {
|
||||
err = global.GVA_DB.Where("id = ?", id).First(&sysOperationRecord).Error
|
||||
return
|
||||
}
|
||||
|
||||
//@author: [granty1](https://github.com/granty1)
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetSysOperationRecordInfoList
|
||||
//@description: 分页获取操作记录列表
|
||||
//@param: info systemReq.SysOperationRecordSearch
|
||||
//@return: err error, list interface{}, total int64
|
||||
|
||||
func (operationRecordService *OperationRecordService) GetSysOperationRecordInfoList(info systemReq.SysOperationRecordSearch) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
// 创建db
|
||||
db := global.GVA_DB.Model(&system.SysOperationRecord{})
|
||||
var sysOperationRecords []system.SysOperationRecord
|
||||
// 如果有条件搜索 下方会自动创建搜索语句
|
||||
if info.Method != "" {
|
||||
db = db.Where("method = ?", info.Method)
|
||||
}
|
||||
if info.Path != "" {
|
||||
db = db.Where("path LIKE ?", "%"+info.Path+"%")
|
||||
}
|
||||
if info.Status != 0 {
|
||||
db = db.Where("status = ?", info.Status)
|
||||
}
|
||||
err = db.Count(&total).Error
|
||||
err = db.Order("id desc").Limit(limit).Offset(offset).Preload("User").Find(&sysOperationRecords).Error
|
||||
return err, sysOperationRecords, total
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"gin-vue-admin/config"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/utils"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetSystemConfig
|
||||
//@description: 读取配置文件
|
||||
//@return: err error, conf config.Server
|
||||
|
||||
type SystemConfigService struct {
|
||||
}
|
||||
|
||||
func (systemConfigService *SystemConfigService) GetSystemConfig() (err error, conf config.Server) {
|
||||
return nil, global.GVA_CONFIG
|
||||
}
|
||||
|
||||
// @description set system config,
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: SetSystemConfig
|
||||
//@description: 设置配置文件
|
||||
//@param: system model.System
|
||||
//@return: err error
|
||||
|
||||
func (systemConfigService *SystemConfigService) SetSystemConfig(system system.System) (err error) {
|
||||
cs := utils.StructToMap(system.Config)
|
||||
for k, v := range cs {
|
||||
global.GVA_VP.Set(k, v)
|
||||
}
|
||||
err = global.GVA_VP.WriteConfig()
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: GetServerInfo
|
||||
//@description: 获取服务器信息
|
||||
//@return: server *utils.Server, err error
|
||||
|
||||
func (systemConfigService *SystemConfigService) GetServerInfo() (server *utils.Server, err error) {
|
||||
var s utils.Server
|
||||
s.Os = utils.InitOS()
|
||||
if s.Cpu, err = utils.InitCPU(); err != nil {
|
||||
global.GVA_LOG.Error("func utils.InitCPU() Failed", zap.String("err", err.Error()))
|
||||
return &s, err
|
||||
}
|
||||
if s.Rrm, err = utils.InitRAM(); err != nil {
|
||||
global.GVA_LOG.Error("func utils.InitRAM() Failed", zap.String("err", err.Error()))
|
||||
return &s, err
|
||||
}
|
||||
if s.Disk, err = utils.InitDisk(); err != nil {
|
||||
global.GVA_LOG.Error("func utils.InitDisk() Failed", zap.String("err", err.Error()))
|
||||
return &s, err
|
||||
}
|
||||
|
||||
return &s, nil
|
||||
}
|
||||
@@ -0,0 +1,134 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"gin-vue-admin/global"
|
||||
"gin-vue-admin/model/common/request"
|
||||
"gin-vue-admin/model/system"
|
||||
"gin-vue-admin/utils"
|
||||
uuid "github.com/satori/go.uuid"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Register
|
||||
//@description: 用户注册
|
||||
//@param: u model.SysUser
|
||||
//@return: err error, userInter model.SysUser
|
||||
|
||||
type UserService struct {
|
||||
}
|
||||
|
||||
func (userService *UserService) Register(u system.SysUser) (err error, userInter system.SysUser) {
|
||||
var user system.SysUser
|
||||
if !errors.Is(global.GVA_DB.Where("username = ?", u.Username).First(&user).Error, gorm.ErrRecordNotFound) { // 判断用户名是否注册
|
||||
return errors.New("用户名已注册"), userInter
|
||||
}
|
||||
// 否则 附加uuid 密码md5简单加密 注册
|
||||
u.Password = utils.MD5V([]byte(u.Password))
|
||||
u.UUID = uuid.NewV4()
|
||||
err = global.GVA_DB.Create(&u).Error
|
||||
return err, u
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: Login
|
||||
//@description: 用户登录
|
||||
//@param: u *model.SysUser
|
||||
//@return: err error, userInter *model.SysUser
|
||||
|
||||
func (userService *UserService) Login(u *system.SysUser) (err error, userInter *system.SysUser) {
|
||||
var user system.SysUser
|
||||
u.Password = utils.MD5V([]byte(u.Password))
|
||||
err = global.GVA_DB.Where("username = ? AND password = ?", u.Username, u.Password).Preload("Authority").First(&user).Error
|
||||
return err, &user
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: ChangePassword
|
||||
//@description: 修改用户密码
|
||||
//@param: u *model.SysUser, newPassword string
|
||||
//@return: err error, userInter *model.SysUser
|
||||
|
||||
func (userService *UserService) ChangePassword(u *system.SysUser, newPassword string) (err error, userInter *system.SysUser) {
|
||||
var user system.SysUser
|
||||
u.Password = utils.MD5V([]byte(u.Password))
|
||||
err = global.GVA_DB.Where("username = ? AND password = ?", u.Username, u.Password).First(&user).Update("password", utils.MD5V([]byte(newPassword))).Error
|
||||
return err, u
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: GetUserInfoList
|
||||
//@description: 分页获取数据
|
||||
//@param: info request.PageInfo
|
||||
//@return: err error, list interface{}, total int64
|
||||
|
||||
func (userService *UserService) GetUserInfoList(info request.PageInfo) (err error, list interface{}, total int64) {
|
||||
limit := info.PageSize
|
||||
offset := info.PageSize * (info.Page - 1)
|
||||
db := global.GVA_DB.Model(&system.SysUser{})
|
||||
var userList []system.SysUser
|
||||
err = db.Count(&total).Error
|
||||
err = db.Limit(limit).Offset(offset).Preload("Authority").Find(&userList).Error
|
||||
return err, userList, total
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: SetUserAuthority
|
||||
//@description: 设置一个用户的权限
|
||||
//@param: uuid uuid.UUID, authorityId string
|
||||
//@return: err error
|
||||
|
||||
func (userService *UserService) SetUserAuthority(uuid uuid.UUID, authorityId string) (err error) {
|
||||
err = global.GVA_DB.Where("uuid = ?", uuid).First(&system.SysUser{}).Update("authority_id", authorityId).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: DeleteUser
|
||||
//@description: 删除用户
|
||||
//@param: id float64
|
||||
//@return: err error
|
||||
|
||||
func (userService *UserService) DeleteUser(id float64) (err error) {
|
||||
var user system.SysUser
|
||||
err = global.GVA_DB.Where("id = ?", id).Delete(&user).Error
|
||||
return err
|
||||
}
|
||||
|
||||
//@author: [piexlmax](https://github.com/piexlmax)
|
||||
//@function: SetUserInfo
|
||||
//@description: 设置用户信息
|
||||
//@param: reqUser model.SysUser
|
||||
//@return: err error, user model.SysUser
|
||||
|
||||
func (userService *UserService) SetUserInfo(reqUser system.SysUser) (err error, user system.SysUser) {
|
||||
err = global.GVA_DB.Updates(&reqUser).Error
|
||||
return err, reqUser
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: FindUserById
|
||||
//@description: 通过id获取用户信息
|
||||
//@param: id int
|
||||
//@return: err error, user *model.SysUser
|
||||
|
||||
func (userService *UserService) FindUserById(id int) (err error, user *system.SysUser) {
|
||||
var u system.SysUser
|
||||
err = global.GVA_DB.Where("`id` = ?", id).First(&u).Error
|
||||
return err, &u
|
||||
}
|
||||
|
||||
//@author: [SliverHorn](https://github.com/SliverHorn)
|
||||
//@function: FindUserByUuid
|
||||
//@description: 通过uuid获取用户信息
|
||||
//@param: uuid string
|
||||
//@return: err error, user *model.SysUser
|
||||
|
||||
func (userService *UserService) FindUserByUuid(uuid string) (err error, user *system.SysUser) {
|
||||
var u system.SysUser
|
||||
if err = global.GVA_DB.Where("`uuid` = ?", uuid).First(&u).Error; err != nil {
|
||||
return errors.New("用户不存在"), &u
|
||||
}
|
||||
return nil, &u
|
||||
}
|
||||
Reference in New Issue
Block a user