diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c7ea37b --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +* linguist-language=GO diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b3b0b38 --- /dev/null +++ b/.gitignore @@ -0,0 +1,23 @@ +.buildpath +.hgignore.swp +.project +.orig +.swp +.idea/ +.settings/ +.vscode/ +vender/ +data/log/ +data/session/ +composer.lock +gitpush.sh +pkg/ +bin/ +cbuild +*/.DS_Store +main +.vscode +*.exe +tmp/* +public/resource/pub_upload/ +data/dataBak diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..25c8139 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,26 @@ +FROM loads/alpine:3.8 + +LABEL maintainer="john@goframe.org" + +############################################################################### +# INSTALLATION +############################################################################### + +# 设置固定的项目路径 +ENV WORKDIR /var/www/gfast + +# 添加应用可执行文件,并设置执行权限 +ADD ./bin/linux_amd64/main $WORKDIR/main +RUN chmod +x $WORKDIR/main + +# 添加I18N多语言文件、静态文件、配置文件、模板文件 +ADD i18n $WORKDIR/i18n +ADD public $WORKDIR/public +ADD config $WORKDIR/config +ADD template $WORKDIR/template + +############################################################################### +# START +############################################################################### +WORKDIR $WORKDIR +CMD ./main diff --git a/README.MD b/README.MD new file mode 100644 index 0000000..c2f1b68 --- /dev/null +++ b/README.MD @@ -0,0 +1,129 @@ +# GFast-V2 + +## 平台简介 +* 基于GF(Go Frame)的后台管理系统 +* 前端采用ruoyi-ui 、Vue、Element UI。 +* 后端采用GO语言 框架 GF(Go Frame)。 +* 阿里云优惠券:[点我进入](https://www.aliyun.com/minisite/goods?userCode=fcor2omk ),腾讯云优惠券:[点我领取](https://cloud.tencent.com/act/cps/redirect?redirect=1062&cps_key=20b1c3842f74986b2894e2c5fcde7ea2&from=console ) +* 本项目由奇讯科技团队开发。 + +## 内置功能 + +1. 用户管理:用户是系统操作者,该功能主要完成系统用户配置。 +2. 部门管理:配置系统组织机构(公司、部门、小组),树结构展现支持数据权限。 +3. 岗位管理:配置系统用户所属担任职务。 +4. 菜单管理:配置系统菜单,操作权限,按钮权限标识等。 +5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 +6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 +7. 参数管理:对系统动态配置常用参数。 +8. 操作日志:系统正常操作日志记录和查询;系统异常信息日志记录和查询。 +9. 登录日志:系统登录日志记录查询包含登录异常。 +10. 在线用户:当前系统中活跃用户状态监控。 +11. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。 +12. 代码生成:前后端代码的生成。 +13. 服务监控:监视当前系统CPU、内存、磁盘、堆栈等相关信息。 +14. 在线构建器:拖动表单元素生成相应的HTML代码。 +15. 文件上传,缓存标签等。 +16. 正在开发中的功能:cms管理、模型管理、工作流引擎 + +## 演示地址 +[http://demo.g-fast.cn](http://demo.g-fast.cn/) +账号:demo 密码:123456 +## 配置 +项目数据库文件 /data/db.sql 创建数据库导入后修改配置/config/config.toml + +其中jwt配置 + +```yaml +[gToken] + [gToken.system] + CacheMode = 2 #此处若使用了redis配置为2 若没使用redis配置1 + CacheKey = "GToken:" + Timeout = 3600000 #1个小时 + MaxRefresh = 0 + TokenDelimiter="_" + EncryptKey = "koi29a83idakguqjq29asd9asd8a7jhq" + AuthFailMsg = "登录超时,请重新登录" + MultiLogin = true #后台是否允许多端同时在线 +``` + +##运行 +go run main.go 直接访问http://localhost:8199 + +账号:demo 密码:123456 + +项目为前后端分离,前端地址: + +github地址:[https://github.com/tiger1103/gfast-ui](https://github.com/tiger1103/gfast-ui) + +gitee地址:[https://gitee.com/tiger1103/gfast-ui](https://gitee.com/tiger1103/gfast-ui) + +## 文档地址 +[http://doc.qjit.cn/docs/gfast/introduce](http://doc.qjit.cn/docs/gfast/introduce) + +## 演示图 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +## 感谢(排名不分先后) +> gf框架 [https://github.com/gogf/gf](https://github.com/gogf/gf) +> +> RuoYi-Vue [https://gitee.com/y_project/RuoYi-Vue](https://gitee.com/y_project/RuoYi-Vue) +> +> swaggo [https://github.com/swaggo/swag](https://github.com/swaggo/swag) +> +>tpflow [https://gitee.com/ntdgg/tpflow](https://gitee.com/ntdgg/tpflow) +> +>gtoken [https://github.com/goflyfox/gtoken](https://github.com/goflyfox/gtoken) +> +>casbin [https://github.com/casbin/casbin](https://github.com/casbin/casbin) +> +>云捷go [https://gitee.com/yunjieg/yjgo](https://gitee.com/yunjieg/yjgo) +## 交流QQ群 + +> + +> 快来加入群聊【Gfast框架交流群】(群号865697297),发现精彩内容。 + +## 免责声明: +> 1、Gfast仅限自己学习使用,一切商业行为与Gfast无关。 + +> 2、用户不得利用Gfast从事非法行为,用户应当合法合规的使用,发现用户在使用产品时有任何的非法行为,Gfast有权配合有关机关进行调查或向政府部门举报,Gfast不承担用户因非法行为造成的任何法律责任,一切法律责任由用户自行承担,如因用户使用造成第三方损害的,用户应当依法予以赔偿。 + +> 3、所有与使用Gfast相关的资源直接风险均由用户承担。 + +###生成dao +因为我们在开发过程中,goFrame框架的gf-cli 一直在更新功能,建议不要直接去覆盖,生成到tmp目录后将需要的文件复制到对应的地方 +``` +例如: gf gen dao -path ./tmp -l "mysql:root:123456@tcp(127.0.0.1:3306)/gfast-v2" -t 表名 +``` + diff --git a/app/common/adapter/upload.go b/app/common/adapter/upload.go new file mode 100644 index 0000000..d045219 --- /dev/null +++ b/app/common/adapter/upload.go @@ -0,0 +1,63 @@ +/* +* @desc:上传适配器 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/7 8:54 + */ + +package adapter + +import ( + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" +) + +// FileInfo 上传的文件信息 +type FileInfo struct { + FileName string `json:"fileName"` + FileSize int64 `json:"fileSize"` + FileUrl string `json:"fileUrl"` + FileType string `json:"fileType"` +} + +type UploadAdapter interface { + UpImg(file *ghttp.UploadFile) (fileInfo *FileInfo, err error) + UpFile(file *ghttp.UploadFile) (fileInfo *FileInfo, err error) + UpImgs(files []*ghttp.UploadFile) (fileInfos []*FileInfo, err error) + UpFiles(files []*ghttp.UploadFile) (fileInfos []*FileInfo, err error) +} + +type upload struct { + adapter UploadAdapter +} + +var Upload = &upload{ + //使用本地上传 + adapter: UploadLocalAdapter{ + UpPath: "/pub_upload/", + UploadPath: g.Cfg().GetString("server.ServerRoot") + "/pub_upload/", + }, + //使用腾讯云COS上传 + /*adapter: UploadTencentCOSAdapter{ + UpPath: "/gfast/", + RawUrl: "https://您的cos空间域名.cos.ap-chongqing.myqcloud.com", + SecretID: "填写您的SecretID", + SecretKey: "填写您的SecretKey", + },*/ +} + +func (u upload) UpImg(file *ghttp.UploadFile) (fileInfo *FileInfo, err error) { + return u.adapter.UpImg(file) +} + +func (u upload) UpFile(file *ghttp.UploadFile) (fileInfo *FileInfo, err error) { + return u.adapter.UpFile(file) +} + +func (u upload) UpImgs(files []*ghttp.UploadFile) (fileInfos []*FileInfo, err error) { + return u.adapter.UpImgs(files) +} + +func (u upload) UpFiles(files []*ghttp.UploadFile) (fileInfos []*FileInfo, err error) { + return u.adapter.UpFiles(files) +} diff --git a/app/common/adapter/upload_local_apapter.go b/app/common/adapter/upload_local_apapter.go new file mode 100644 index 0000000..33fde70 --- /dev/null +++ b/app/common/adapter/upload_local_apapter.go @@ -0,0 +1,225 @@ +/* +* @desc:本地上传 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/7 8:47 + */ + +package adapter + +import ( + "gfast/app/common/model" + "gfast/app/common/service" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/text/gregex" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gconv" +) + +type UploadLocalAdapter struct { + UpPath string + UploadPath string +} + +// UpImg 上传图片 +func (up UploadLocalAdapter) UpImg(file *ghttp.UploadFile) (fileInfo *FileInfo, err error) { + return up.upByType(file, "img") +} + +// UpFile 上传文件 +func (up UploadLocalAdapter) UpFile(file *ghttp.UploadFile) (fileInfo *FileInfo, err error) { + return up.upByType(file, "file") +} + +// UpImgs 批量上传图片 +func (up UploadLocalAdapter) UpImgs(files []*ghttp.UploadFile) (fileInfos []*FileInfo, err error) { + return up.upBathByType(files, "img") +} + +// UpFiles 批量上传文件 +func (up UploadLocalAdapter) UpFiles(files []*ghttp.UploadFile) (fileInfos []*FileInfo, err error) { + return up.upBathByType(files, "file") +} + +//文件上传 img|file +func (up UploadLocalAdapter) upByType(file *ghttp.UploadFile, fType string) (fileInfo *FileInfo, err error) { + if file == nil { + err = gerror.New("未上传任何文件") + return + } + var ( + typeKey string + sizeKey string + ) + if fType == "img" { + typeKey = "sys.uploadFile.imageType" + sizeKey = "sys.uploadFile.imageSize" + } else if fType == "file" { + typeKey = "sys.uploadFile.fileType" + sizeKey = "sys.uploadFile.fileSize" + } + //获取上传类型配置 + config, err := up.getUpConfig(typeKey) + if err != nil { + return + } + + //检测文件类型 + rightType := up.checkFileType(file.Filename, config.ConfigValue) + if !rightType { + err = gerror.New("上传文件类型错误,只能包含后缀为:" + config.ConfigValue + "的文件。") + return + } + //获取上传大小配置 + config, err = up.getUpConfig(sizeKey) + if err != nil { + return + } + rightSize, err := up.checkSize(config.ConfigValue, file.Size) + if err != nil { + return + } + if !rightSize { + err = gerror.New("上传文件超过最大尺寸:" + config.ConfigValue) + return + } + path := up.getUpPath() + fileName, err := file.Save(path, true) + if err != nil { + return + } + fileInfo = &FileInfo{ + FileName: file.Filename, + FileSize: file.Size, + FileUrl: up.getUrl(path, fileName), + FileType: file.Header.Get("Content-type"), + } + return +} + +//批量上传 img|file +func (up UploadLocalAdapter) upBathByType(files []*ghttp.UploadFile, fType string) (fileInfos []*FileInfo, err error) { + if len(files) == 0 { + err = gerror.New("未上传任何文件") + return + } + var ( + typeKey string + sizeKey string + ) + if fType == "img" { + typeKey = "sys.uploadFile.imageType" + sizeKey = "sys.uploadFile.imageSize" + } else if fType == "file" { + typeKey = "sys.uploadFile.fileType" + sizeKey = "sys.uploadFile.fileSize" + } + //获取上传类型配置 + configType, err := up.getUpConfig(typeKey) + if err != nil { + return + } + //获取上传大小配置 + configSize, err := up.getUpConfig(sizeKey) + if err != nil { + return + } + for _, file := range files { + //检测文件类型 + rightType := up.checkFileType(file.Filename, configType.ConfigValue) + if !rightType { + err = gerror.New("上传文件类型错误,只能包含后缀为:" + configType.ConfigValue + "的文件。") + return + } + var rightSize bool + rightSize, err = up.checkSize(configSize.ConfigValue, file.Size) + if err != nil { + return + } + if !rightSize { + err = gerror.New("上传文件超过最大尺寸:" + configSize.ConfigValue) + return + } + } + path := up.getUpPath() + for _, file := range files { + var fileName string + fileName, err = file.Save(path, true) + if err != nil { + return + } + fileInfo := &FileInfo{ + FileName: file.Filename, + FileSize: file.Size, + FileUrl: up.getUrl(path, fileName), + FileType: file.Header.Get("Content-type"), + } + fileInfos = append(fileInfos, fileInfo) + } + return +} + +//检查文件大小是否合法 +func (up UploadLocalAdapter) checkSize(configSize string, fileSize int64) (bool, error) { + match, err := gregex.MatchString(`^([0-9]+)(?i:([a-z]*))$`, configSize) + if err != nil { + return false, err + } + if len(match) == 0 { + err = gerror.New("上传文件大小未设置,请在后台配置,格式为(30M,30k,30MB)") + return false, err + } + var cfSize int64 + switch gstr.ToUpper(match[2]) { + case "MB", "M": + cfSize = gconv.Int64(match[1]) * 1024 * 1024 + case "KB", "K": + cfSize = gconv.Int64(match[1]) * 1024 + case "": + cfSize = gconv.Int64(match[1]) + } + if cfSize == 0 { + err = gerror.New("上传文件大小未设置,请在后台配置,格式为(30M,30k,30MB),最大单位为MB") + return false, err + } + return cfSize >= fileSize, nil +} + +//获取上传配置 +func (up UploadLocalAdapter) getUpConfig(key string) (config *model.SysConfig, err error) { + config, err = service.SysConfig.GetConfigByKey(key) + if err != nil { + return + } + if config == nil { + err = gerror.New("上传文件类型未设置,请在后台配置") + return + } + return +} + +//判断上传文件类型是否合法 +func (up UploadLocalAdapter) checkFileType(fileName, typeString string) bool { + suffix := gstr.SubStrRune(fileName, gstr.PosRRune(fileName, ".")+1, gstr.LenRune(fileName)-1) + imageType := gstr.Split(typeString, ",") + rightType := false + for _, v := range imageType { + if gstr.Equal(suffix, v) { + rightType = true + break + } + } + return rightType +} + +func (up UploadLocalAdapter) getUpPath() (upPath string) { + upPath = up.UploadPath + gtime.Date() + "/" + return +} + +func (up UploadLocalAdapter) getUrl(path, fileName string) string { + url := gstr.SubStr(path, gstr.Pos(path, up.UpPath)+1) + fileName + return url +} diff --git a/app/common/adapter/upload_tencent_cos_adapter.go b/app/common/adapter/upload_tencent_cos_adapter.go new file mode 100644 index 0000000..21e6337 --- /dev/null +++ b/app/common/adapter/upload_tencent_cos_adapter.go @@ -0,0 +1,268 @@ +/* +* @desc:腾讯oss +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/7 15:51 + */ + +package adapter + +import ( + "context" + "gfast/app/common/model" + "gfast/app/common/service" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/gfile" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/text/gregex" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/grand" + "github.com/tencentyun/cos-go-sdk-v5" + "github.com/tencentyun/cos-go-sdk-v5/debug" + "io" + "net/http" + "net/url" + "strconv" + "strings" +) + +type UploadTencentCOSAdapter struct { + UpPath string + SecretID string + SecretKey string + RawUrl string +} + +func (u UploadTencentCOSAdapter) UpImg(file *ghttp.UploadFile) (fileInfo *FileInfo, err error) { + return u.upByType(file, "img") +} + +func (u UploadTencentCOSAdapter) UpFile(file *ghttp.UploadFile) (fileInfo *FileInfo, err error) { + return u.upByType(file, "file") +} + +func (u UploadTencentCOSAdapter) UpImgs(files []*ghttp.UploadFile) (fileInfos []*FileInfo, err error) { + return u.upBathByType(files, "img") +} + +func (u UploadTencentCOSAdapter) UpFiles(files []*ghttp.UploadFile) (fileInfos []*FileInfo, err error) { + return u.upBathByType(files, "file") +} + +//文件上传 img|file +func (u UploadTencentCOSAdapter) upByType(file *ghttp.UploadFile, fType string) (fileInfo *FileInfo, err error) { + if file == nil { + err = gerror.New("未上传任何文件") + return + } + var ( + typeKey string + sizeKey string + ) + if fType == "img" { + typeKey = "sys.uploadFile.imageType" + sizeKey = "sys.uploadFile.imageSize" + } else if fType == "file" { + typeKey = "sys.uploadFile.fileType" + sizeKey = "sys.uploadFile.fileSize" + } + //获取上传类型配置 + config, err := u.getUpConfig(typeKey) + if err != nil { + return + } + + //检测文件类型 + rightType := u.checkFileType(file.Filename, config.ConfigValue) + if !rightType { + err = gerror.New("上传文件类型错误,只能包含后缀为:" + config.ConfigValue + "的文件。") + return + } + //获取上传大小配置 + config, err = u.getUpConfig(sizeKey) + if err != nil { + return + } + rightSize, err := u.checkSize(config.ConfigValue, file.Size) + if err != nil { + return + } + if !rightSize { + err = gerror.New("上传文件超过最大尺寸:" + config.ConfigValue) + return + } + var path string + path, err = u.upAction(file) + if err != nil { + return + } + fileInfo = &FileInfo{ + FileName: file.Filename, + FileSize: file.Size, + FileUrl: u.getUrl(path), + FileType: file.Header.Get("Content-type"), + } + return +} + +//批量上传 img|file +func (u UploadTencentCOSAdapter) upBathByType(files []*ghttp.UploadFile, fType string) (fileInfos []*FileInfo, err error) { + if len(files) == 0 { + err = gerror.New("未上传任何文件") + return + } + var ( + typeKey string + sizeKey string + ) + if fType == "img" { + typeKey = "sys.uploadFile.imageType" + sizeKey = "sys.uploadFile.imageSize" + } else if fType == "file" { + typeKey = "sys.uploadFile.fileType" + sizeKey = "sys.uploadFile.fileSize" + } + //获取上传类型配置 + configType, err := u.getUpConfig(typeKey) + if err != nil { + return + } + //获取上传大小配置 + configSize, err := u.getUpConfig(sizeKey) + if err != nil { + return + } + for _, file := range files { + //检测文件类型 + rightType := u.checkFileType(file.Filename, configType.ConfigValue) + if !rightType { + err = gerror.New("上传文件类型错误,只能包含后缀为:" + configType.ConfigValue + "的文件。") + return + } + var rightSize bool + rightSize, err = u.checkSize(configSize.ConfigValue, file.Size) + if err != nil { + return + } + if !rightSize { + err = gerror.New("上传文件超过最大尺寸:" + configSize.ConfigValue) + return + } + } + for _, file := range files { + var path string + path, err = u.upAction(file) + if err != nil { + return + } + fileInfo := &FileInfo{ + FileName: file.Filename, + FileSize: file.Size, + FileUrl: u.getUrl(path), + FileType: file.Header.Get("Content-type"), + } + fileInfos = append(fileInfos, fileInfo) + } + return +} + +// 上传到腾讯cos操作 +func (u UploadTencentCOSAdapter) upAction(file *ghttp.UploadFile) (path string, err error) { + name := gfile.Basename(file.Filename) + name = strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) + name = name + gfile.Ext(file.Filename) + + path = u.getUpPath() + name + url, _ := url.Parse(u.RawUrl) + b := &cos.BaseURL{BucketURL: url} + c := cos.NewClient(b, &http.Client{ + Transport: &cos.AuthorizationTransport{ + SecretID: u.SecretID, + SecretKey: u.SecretKey, + Transport: &debug.DebugRequestTransport{ + RequestHeader: false, + RequestBody: false, + ResponseHeader: false, + ResponseBody: false, + }, + }, + }) + opt := &cos.ObjectPutOptions{ + ObjectPutHeaderOptions: &cos.ObjectPutHeaderOptions{ + ContentLength: int64(file.Size), + }, + } + var f io.ReadCloser + f, err = file.Open() + if err != nil { + return + } + defer f.Close() + _, err = c.Object.Put(context.Background(), path, f, opt) + return +} + +//获取上传配置 +func (u UploadTencentCOSAdapter) getUpConfig(key string) (config *model.SysConfig, err error) { + config, err = service.SysConfig.GetConfigByKey(key) + if err != nil { + return + } + if config == nil { + err = gerror.New("上传文件类型未设置,请在后台配置") + return + } + return +} + +//判断上传文件类型是否合法 +func (u UploadTencentCOSAdapter) checkFileType(fileName, typeString string) bool { + suffix := gstr.SubStrRune(fileName, gstr.PosRRune(fileName, ".")+1, gstr.LenRune(fileName)-1) + imageType := gstr.Split(typeString, ",") + rightType := false + for _, v := range imageType { + if gstr.Equal(suffix, v) { + rightType = true + break + } + } + return rightType +} + +//检查文件大小是否合法 +func (u UploadTencentCOSAdapter) checkSize(configSize string, fileSize int64) (bool, error) { + match, err := gregex.MatchString(`^([0-9]+)(?i:([a-z]*))$`, configSize) + if err != nil { + return false, err + } + if len(match) == 0 { + err = gerror.New("上传文件大小未设置,请在后台配置,格式为(30M,30k,30MB)") + return false, err + } + var cfSize int64 + switch gstr.ToUpper(match[2]) { + case "MB", "M": + cfSize = gconv.Int64(match[1]) * 1024 * 1024 + case "KB", "K": + cfSize = gconv.Int64(match[1]) * 1024 + case "": + cfSize = gconv.Int64(match[1]) + } + if cfSize == 0 { + err = gerror.New("上传文件大小未设置,请在后台配置,格式为(30M,30k,30MB),最大单位为MB") + return false, err + } + return cfSize >= fileSize, nil +} + +func (u UploadTencentCOSAdapter) getUpPath() (upPath string) { + upPath = u.UpPath + gtime.Date() + "/" + return +} + +func (u UploadTencentCOSAdapter) getUrl(path string) string { + url := u.RawUrl + path + return url +} diff --git a/app/common/api/captcha.go b/app/common/api/captcha.go new file mode 100644 index 0000000..750927d --- /dev/null +++ b/app/common/api/captcha.go @@ -0,0 +1,24 @@ +package api + +import ( + "gfast/app/common/service" + "gfast/library" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" +) + +type captcha struct{} + +var Captcha = new(captcha) + +// Img +// @Summary 获取验证码图片信息 +// @Description 获取验证码图片信息 +// @Tags 公共 +// @Success 0 {object} response.Response "{"code": 200, "data": [...]}" +// @Router /system/public/verify [post] +// @Security +func (c *captcha) Img(r *ghttp.Request) { + idKeyC, base64stringC := service.Captcha.GetVerifyImgString() + library.SusJson(true, r, "ok", g.MapStrStr{"idKeyC": idKeyC, "base64stringC": base64stringC}) +} diff --git a/app/common/api/common_base.go b/app/common/api/common_base.go new file mode 100644 index 0000000..d670b31 --- /dev/null +++ b/app/common/api/common_base.go @@ -0,0 +1,33 @@ +package api + +import ( + "gfast/library" + "github.com/gogf/gf/net/ghttp" +) + +type CommonBase struct{} + +// SusJson 成功的返回 +func (c *CommonBase) SusJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) { + library.SusJson(isExit, r, msg, data...) +} + +// FailJson 失败的返回 +func (c *CommonBase) FailJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) { + library.FailJson(isExit, r, msg, data...) +} + +// FailJsonExit 失败中断返回 +func (c *CommonBase) FailJsonExit(r *ghttp.Request, msg string) { + c.FailJson(true, r, msg) +} + +// SusJsonExit 成功中断返回 +func (c *CommonBase) SusJsonExit(r *ghttp.Request, data ...interface{}) { + c.SusJson(true, r, "success", data...) +} + +// JsonExit 输出json并中断 +func (c *CommonBase) JsonExit(r *ghttp.Request, code int, msg string, data ...interface{}) { + library.JsonExit(r, code, msg, data...) +} diff --git a/app/common/dao/casbin_rule.go b/app/common/dao/casbin_rule.go new file mode 100644 index 0000000..2db608f --- /dev/null +++ b/app/common/dao/casbin_rule.go @@ -0,0 +1,25 @@ +// ============================================================================ +// This is auto-generated by gf cli tool only once. Fill this file as you wish. +// ============================================================================ + +package dao + +import ( + "gfast/app/common/dao/internal" +) + +// casbinRuleDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type casbinRuleDao struct { + internal.CasbinRuleDao +} + +var ( + // CasbinRule is globally public accessible object for table casbin_rule operations. + CasbinRule = casbinRuleDao{ + internal.CasbinRule, + } +) + +// Fill with you ideas below. diff --git a/app/common/dao/internal/casbin_rule.go b/app/common/dao/internal/casbin_rule.go new file mode 100644 index 0000000..11defc3 --- /dev/null +++ b/app/common/dao/internal/casbin_rule.go @@ -0,0 +1,395 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "context" + "database/sql" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" + "time" + + "gfast/app/common/model" +) + +// CasbinRuleDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type CasbinRuleDao struct { + gmvc.M + DB gdb.DB + Table string + Columns casbinRuleColumns +} + +// CasbinRuleColumns defines and stores column names for table casbin_rule. +type casbinRuleColumns struct { + Ptype string // + V0 string // + V1 string // + V2 string // + V3 string // + V4 string // + V5 string // +} + +var ( + // CasbinRule is globally public accessible object for table casbin_rule operations. + CasbinRule = CasbinRuleDao{ + M: g.DB("default").Model("casbin_rule").Safe(), + DB: g.DB("default"), + Table: "casbin_rule", + Columns: casbinRuleColumns{ + Ptype: "ptype", + V0: "v0", + V1: "v1", + V2: "v2", + V3: "v3", + V4: "v4", + V5: "v5", + }, + } +) + +// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy +// of current DB object and with given context in it. +// Note that this returned DB object can be used only once, so do not assign it to +// a global or package variable for long using. +func (d *CasbinRuleDao) Ctx(ctx context.Context) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Ctx(ctx)} +} + +// As sets an alias name for current table. +func (d *CasbinRuleDao) As(as string) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.As(as)} +} + +// TX sets the transaction for current operation. +func (d *CasbinRuleDao) TX(tx *gdb.TX) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.TX(tx)} +} + +// Master marks the following operation on master node. +func (d *CasbinRuleDao) Master() *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Master()} +} + +// Slave marks the following operation on slave node. +// Note that it makes sense only if there's any slave node configured. +func (d *CasbinRuleDao) Slave() *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Slave()} +} + +// Args sets custom arguments for model operation. +func (d *CasbinRuleDao) Args(args ...interface{}) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Args(args...)} +} + +// LeftJoin does "LEFT JOIN ... ON ..." statement on the model. +// The parameter can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *CasbinRuleDao) LeftJoin(table ...string) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.LeftJoin(table...)} +} + +// RightJoin does "RIGHT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *CasbinRuleDao) RightJoin(table ...string) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.RightJoin(table...)} +} + +// InnerJoin does "INNER JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *CasbinRuleDao) InnerJoin(table ...string) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.InnerJoin(table...)} +} + +// Fields sets the operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *CasbinRuleDao) Fields(fieldNamesOrMapStruct ...interface{}) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Fields(fieldNamesOrMapStruct...)} +} + +// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *CasbinRuleDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)} +} + +// Option sets the extra operation option for the model. +func (d *CasbinRuleDao) Option(option int) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Option(option)} +} + +// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers +// the data and where attributes for empty values. +func (d *CasbinRuleDao) OmitEmpty() *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.OmitEmpty()} +} + +// Filter marks filtering the fields which does not exist in the fields of the operated table. +func (d *CasbinRuleDao) Filter() *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Filter()} +} + +// Where sets the condition statement for the model. The parameter can be type of +// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times, +// multiple conditions will be joined into where statement using "AND". +// Eg: +// Where("uid=10000") +// Where("uid", 10000) +// Where("money>? AND name like ?", 99999, "vip_%") +// Where("uid", 1).Where("name", "john") +// Where("status IN (?)", g.Slice{1,2,3}) +// Where("age IN(?,?)", 18, 50) +// Where(User{ Id : 1, UserName : "john"}) +func (d *CasbinRuleDao) Where(where interface{}, args ...interface{}) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Where(where, args...)} +} + +// WherePri does the same logic as M.Where except that if the parameter +// is a single condition like int/string/float/slice, it treats the condition as the primary +// key value. That is, if primary key is "id" and given parameter as "123", the +// WherePri function treats the condition as "id=123", but M.Where treats the condition +// as string "123". +func (d *CasbinRuleDao) WherePri(where interface{}, args ...interface{}) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.WherePri(where, args...)} +} + +// And adds "AND" condition to the where statement. +func (d *CasbinRuleDao) And(where interface{}, args ...interface{}) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.And(where, args...)} +} + +// Or adds "OR" condition to the where statement. +func (d *CasbinRuleDao) Or(where interface{}, args ...interface{}) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Or(where, args...)} +} + +// Group sets the "GROUP BY" statement for the model. +func (d *CasbinRuleDao) Group(groupBy string) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Group(groupBy)} +} + +// Order sets the "ORDER BY" statement for the model. +func (d *CasbinRuleDao) Order(orderBy ...string) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Order(orderBy...)} +} + +// Limit sets the "LIMIT" statement for the model. +// The parameter can be either one or two number, if passed two number is passed, +// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]" +// statement. +func (d *CasbinRuleDao) Limit(limit ...int) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Limit(limit...)} +} + +// Offset sets the "OFFSET" statement for the model. +// It only makes sense for some databases like SQLServer, PostgreSQL, etc. +func (d *CasbinRuleDao) Offset(offset int) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Offset(offset)} +} + +// Page sets the paging number for the model. +// The parameter is started from 1 for paging. +// Note that, it differs that the Limit function start from 0 for "LIMIT" statement. +func (d *CasbinRuleDao) Page(page, limit int) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Page(page, limit)} +} + +// Batch sets the batch operation number for the model. +func (d *CasbinRuleDao) Batch(batch int) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Batch(batch)} +} + +// Cache sets the cache feature for the model. It caches the result of the sql, which means +// if there's another same sql request, it just reads and returns the result from cache, it +// but not committed and executed into the database. +// +// If the parameter < 0, which means it clear the cache with given . +// If the parameter = 0, which means it never expires. +// If the parameter > 0, which means it expires after . +// +// The optional parameter is used to bind a name to the cache, which means you can later +// control the cache like changing the or clearing the cache with specified . +// +// Note that, the cache feature is disabled if the model is operating on a transaction. +func (d *CasbinRuleDao) Cache(duration time.Duration, name ...string) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Cache(duration, name...)} +} + +// Data sets the operation data for the model. +// The parameter can be type of string/map/gmap/slice/struct/*struct, etc. +// Eg: +// Data("uid=10000") +// Data("uid", 10000) +// Data(g.Map{"uid": 10000, "name":"john"}) +// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) +func (d *CasbinRuleDao) Data(data ...interface{}) *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Data(data...)} +} + +// All does "SELECT FROM ..." statement for the model. +// It retrieves the records from table and returns the result as []*model.CasbinRule. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *CasbinRuleDao) All(where ...interface{}) ([]*model.CasbinRule, error) { + all, err := d.M.All(where...) + if err != nil { + return nil, err + } + var entities []*model.CasbinRule + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// One retrieves one record from table and returns the result as *model.CasbinRule. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *CasbinRuleDao) One(where ...interface{}) (*model.CasbinRule, error) { + one, err := d.M.One(where...) + if err != nil { + return nil, err + } + var entity *model.CasbinRule + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindOne retrieves and returns a single Record by M.WherePri and M.One. +// Also see M.WherePri and M.One. +func (d *CasbinRuleDao) FindOne(where ...interface{}) (*model.CasbinRule, error) { + one, err := d.M.FindOne(where...) + if err != nil { + return nil, err + } + var entity *model.CasbinRule + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindAll retrieves and returns Result by by M.WherePri and M.All. +// Also see M.WherePri and M.All. +func (d *CasbinRuleDao) FindAll(where ...interface{}) ([]*model.CasbinRule, error) { + all, err := d.M.FindAll(where...) + if err != nil { + return nil, err + } + var entities []*model.CasbinRule + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// Struct retrieves one record from table and converts it into given struct. +// The parameter should be type of *struct/**struct. If type **struct is given, +// it can create the struct internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Struct(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Struct(&user) +func (d *CasbinRuleDao) Struct(pointer interface{}, where ...interface{}) error { + return d.M.Struct(pointer, where...) +} + +// Structs retrieves records from table and converts them into given struct slice. +// The parameter should be type of *[]struct/*[]*struct. It can create and fill the struct +// slice internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not empty. +// +// Eg: +// users := ([]User)(nil) +// err := dao.User.Structs(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Structs(&users) +func (d *CasbinRuleDao) Structs(pointer interface{}, where ...interface{}) error { + return d.M.Structs(pointer, where...) +} + +// Scan automatically calls Struct or Structs function according to the type of parameter . +// It calls function Struct if is type of *struct/**struct. +// It calls function Structs if is type of *[]struct/*[]*struct. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Scan(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Scan(&user) +// +// users := ([]User)(nil) +// err := dao.User.Scan(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Scan(&users) +func (d *CasbinRuleDao) Scan(pointer interface{}, where ...interface{}) error { + return d.M.Scan(pointer, where...) +} + +// Chunk iterates the table with given size and callback function. +func (d *CasbinRuleDao) Chunk(limit int, callback func(entities []*model.CasbinRule, err error) bool) { + d.M.Chunk(limit, func(result gdb.Result, err error) bool { + var entities []*model.CasbinRule + err = result.Structs(&entities) + if err == sql.ErrNoRows { + return false + } + return callback(entities, err) + }) +} + +// LockUpdate sets the lock for update for current operation. +func (d *CasbinRuleDao) LockUpdate() *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.LockUpdate()} +} + +// LockShared sets the lock in share mode for current operation. +func (d *CasbinRuleDao) LockShared() *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.LockShared()} +} + +// Unscoped enables/disables the soft deleting feature. +func (d *CasbinRuleDao) Unscoped() *CasbinRuleDao { + return &CasbinRuleDao{M: d.M.Unscoped()} +} diff --git a/app/common/dao/internal/sys_config.go b/app/common/dao/internal/sys_config.go new file mode 100644 index 0000000..759dfed --- /dev/null +++ b/app/common/dao/internal/sys_config.go @@ -0,0 +1,57 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysConfigDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysConfigDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + C sysConfigColumns // C is the short type for Columns, which contains all the column names of Table for convenient usage. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the underlying table name of the DAO. +} + +// SysConfigColumns defines and stores column names for table sys_config. +type sysConfigColumns struct { + ConfigId string // 参数主键 + ConfigName string // 参数名称 + ConfigKey string // 参数键名 + ConfigValue string // 参数键值 + ConfigType string // 系统内置(Y是 N否) + CreateBy string // 创建者 + UpdateBy string // 更新者 + Remark string // 备注 + CreatedAt string // 创建时间 + UpdatedAt string // 修改时间 + DeletedAt string // 删除时间 +} + +// NewSysConfigDao creates and returns a new DAO object for table data access. +func NewSysConfigDao() *SysConfigDao { + columns := sysConfigColumns{ + ConfigId: "config_id", + ConfigName: "config_name", + ConfigKey: "config_key", + ConfigValue: "config_value", + ConfigType: "config_type", + CreateBy: "create_by", + UpdateBy: "update_by", + Remark: "remark", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + } + return &SysConfigDao{ + C: columns, + M: g.DB("default").Model("sys_config").Safe(), + DB: g.DB("default"), + Table: "sys_config", + } +} diff --git a/app/common/dao/sys_config.go b/app/common/dao/sys_config.go new file mode 100644 index 0000000..e360ec7 --- /dev/null +++ b/app/common/dao/sys_config.go @@ -0,0 +1,26 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "gfast/app/common/dao/internal" +) + +// sysConfigDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysConfigDao struct { + *internal.SysConfigDao +} + +var ( + // SysConfig is globally public accessible object for table sys_config operations. + SysConfig sysConfigDao +) + +func init() { + SysConfig = sysConfigDao{ + internal.NewSysConfigDao(), + } +} diff --git a/app/common/global/cache_key.go b/app/common/global/cache_key.go new file mode 100644 index 0000000..8925aae --- /dev/null +++ b/app/common/global/cache_key.go @@ -0,0 +1,22 @@ +package global + +const ( + //缓存前缀 + cachePrefix = "cache_" + + // SysAuthMenu 缓存菜单KEY + SysAuthMenu = cachePrefix + "sysAuthMenu" + // SysDict 字典缓存菜单KEY + SysDict = cachePrefix + "sysDict" + // SysRole 角色缓存key + SysRole = cachePrefix + "sysRole" + // SysWebSet 站点配置缓存key + SysWebSet = cachePrefix + "sysWebSet" + + // SysAuthTag 权限缓存TAG标签 + SysAuthTag = cachePrefix + "sysAuthTag" + // SysDictTag 字典缓存标签 + SysDictTag = cachePrefix + "sysDictTag" + // SysConfigTag 系统参数配置 + SysConfigTag = cachePrefix + "sysConfigTag" +) diff --git a/app/common/model/casbin_rule.go b/app/common/model/casbin_rule.go new file mode 100644 index 0000000..f1970c7 --- /dev/null +++ b/app/common/model/casbin_rule.go @@ -0,0 +1,14 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. Fill this file as you wish. +// ========================================================================== + +package model + +import ( + "gfast/app/common/model/internal" +) + +// CasbinRule is the golang structure for table casbin_rule. +type CasbinRule internal.CasbinRule + +// Fill with you ideas below. diff --git a/app/common/model/internal/casbin_rule.go b/app/common/model/internal/casbin_rule.go new file mode 100644 index 0000000..b75f131 --- /dev/null +++ b/app/common/model/internal/casbin_rule.go @@ -0,0 +1,16 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +// CasbinRule is the golang structure for table casbin_rule. +type CasbinRule struct { + Ptype string `orm:"ptype" json:"ptype"` // + V0 string `orm:"v0" json:"v0"` // + V1 string `orm:"v1" json:"v1"` // + V2 string `orm:"v2" json:"v2"` // + V3 string `orm:"v3" json:"v3"` // + V4 string `orm:"v4" json:"v4"` // + V5 string `orm:"v5" json:"v5"` // +} diff --git a/app/common/model/req.go b/app/common/model/req.go new file mode 100644 index 0000000..86c1984 --- /dev/null +++ b/app/common/model/req.go @@ -0,0 +1,13 @@ +package model + +import "context" + +const PageSize = 10 + +type PageReq struct { + BeginTime string `p:"beginTime"` //开始时间 + EndTime string `p:"endTime"` //结束时间 + PageNum int `p:"PageNum"` //当前页码 + PageSize int `p:"pageSize"` //每页数 + Ctx context.Context +} diff --git a/app/common/model/sys_config.go b/app/common/model/sys_config.go new file mode 100644 index 0000000..5083b2d --- /dev/null +++ b/app/common/model/sys_config.go @@ -0,0 +1,51 @@ +// ================================================================================= +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package model + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysConfig is the golang structure for table sys_config. +type SysConfig struct { + ConfigId uint `orm:"config_id,primary" json:"configId"` // 参数主键 + ConfigName string `orm:"config_name" json:"configName"` // 参数名称 + ConfigKey string `orm:"config_key,unique" json:"configKey"` // 参数键名 + ConfigValue string `orm:"config_value" json:"configValue"` // 参数键值 + ConfigType int `orm:"config_type" json:"configType"` // 系统内置(Y是 N否) + CreateBy uint `orm:"create_by" json:"createBy"` // 创建者 + UpdateBy uint `orm:"update_by" json:"updateBy"` // 更新者 + Remark string `orm:"remark" json:"remark"` // 备注 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 修改时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除时间 +} + +//分页请求参数 +type SysConfigSearchReq struct { + ConfigName string `p:"configName"` //参数名称 + ConfigKey string `p:"configKey"` //参数键名 + ConfigType string `p:"configType"` //状态 + BeginTime string `p:"beginTime"` //开始时间 + EndTime string `p:"endTime"` //结束时间 + PageReq +} + +//新增页面请求参数 +type SysConfigAddReq struct { + ConfigName string `p:"configName" v:"required#参数名称不能为空"` + ConfigKey string `p:"configKey" v:"required#参数键名不能为空"` + ConfigValue string `p:"configValue" v:"required#参数键值不能为空"` + ConfigType int `p:"configType" v:"required|in:0,1#系统内置不能为空|系统内置类型只能为0或1"` + Remark string `p:"remark"` + CreateBy uint64 +} + +//修改页面请求参数 +type SysConfigEditReq struct { + ConfigId int64 `p:"configId" v:"required|min:1#主键ID不能为空|主键ID参数错误"` + UpdateBy uint64 + SysConfigAddReq +} diff --git a/app/common/service/cache.go b/app/common/service/cache.go new file mode 100644 index 0000000..6a6b687 --- /dev/null +++ b/app/common/service/cache.go @@ -0,0 +1,244 @@ +package service + +import ( + "context" + "fmt" + "github.com/gogf/gcache-adapter/adapter" + "github.com/gogf/gf/crypto/gmd5" + "github.com/gogf/gf/encoding/gjson" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/gcache" + "github.com/gogf/gf/util/gconv" + "reflect" + "sync" + "time" +) + +type cache struct { +} + +type cacheTagService struct { + tagKey interface{} + cache *gcache.Cache + tagSetMux *sync.Mutex +} + +var ( + Cache = new(cache) + userRedis = g.Cfg().GetBool("redis.open") + gChe = gcache.New() +) + +func (s *cache) New() *cacheTagService { + gChe.Ctx(context.Background()) + if userRedis { + adapter := adapter.NewRedis(g.Redis()) + gChe.SetAdapter(adapter) + } + return &cacheTagService{ + cache: gChe, + tagSetMux: new(sync.Mutex), + } +} + +//设置tag缓存的keys +func (c *cacheTagService) cacheTagKey(key interface{}, tag interface{}) { + c.setTagKey(tag) + if c.tagKey != nil { + tagValue := []interface{}{key} + value, _ := c.cache.Get(c.tagKey) + if value != nil { + var keyValue []interface{} + //若是字符串 + if kStr, ok := value.(string); ok { + js, err := gjson.DecodeToJson(kStr) + if err != nil { + g.Log().Error(err) + return + } + keyValue = gconv.SliceAny(js.Value()) + } else { + keyValue = gconv.SliceAny(value) + } + for _, v := range keyValue { + if !reflect.DeepEqual(key, v) { + tagValue = append(tagValue, v) + } + } + } + c.cache.Set(c.tagKey, tagValue, 0) + } +} + +//获取带标签的键名 +func (c *cacheTagService) setTagKey(tag interface{}) { + if tag != nil { + c.tagKey = interface{}(fmt.Sprintf("cache_tag_%s", gmd5.MustEncryptString(gconv.String(tag)))) + } +} + +// Set sets cache with - pair, which is expired after . +// It does not expire if <= 0. +func (c *cacheTagService) Set(key interface{}, value interface{}, duration time.Duration, tag ...interface{}) { + c.tagSetMux.Lock() + if len(tag) > 0 { + c.cacheTagKey(key, tag[0]) + } + err := c.cache.Set(key, value, duration) + if err != nil { + g.Log().Error(err) + } + c.tagSetMux.Unlock() +} + +// SetIfNotExist sets cache with - pair if does not exist in the cache, +// which is expired after . It does not expire if <= 0. +func (c *cacheTagService) SetIfNotExist(key interface{}, value interface{}, duration time.Duration, tag interface{}) bool { + c.tagSetMux.Lock() + defer c.tagSetMux.Unlock() + c.cacheTagKey(key, tag) + v, _ := c.cache.SetIfNotExist(key, value, duration) + return v +} + +// Sets batch sets cache with tagKey-value pairs by , which is expired after . +// +// It does not expire if <= 0. +func (c *cacheTagService) Sets(data map[interface{}]interface{}, duration time.Duration, tag interface{}) { + c.tagSetMux.Lock() + if tag != nil { + for k, _ := range data { + c.cacheTagKey(k, tag) + } + c.cache.Sets(data, duration) + } else { + c.cache.Sets(data, duration) + } + c.tagSetMux.Unlock() +} + +// Get returns the value of . +// It returns nil if it does not exist or its value is nil. +func (c *cacheTagService) Get(key interface{}) interface{} { + v, err := c.cache.Get(key) + if err != nil { + g.Log().Error(err) + } + return v +} + +// GetOrSet returns the value of , +// or sets - pair and returns if does not exist in the cache. +// The tagKey-value pair expires after . +// +// It does not expire if <= 0. +func (c *cacheTagService) GetOrSet(key interface{}, value interface{}, duration time.Duration, tag interface{}) interface{} { + c.tagSetMux.Lock() + defer c.tagSetMux.Unlock() + c.cacheTagKey(key, tag) + v, _ := c.cache.GetOrSet(key, value, duration) + return v +} + +// GetOrSetFunc returns the value of , or sets with result of function +// and returns its result if does not exist in the cache. The tagKey-value pair expires +// after . It does not expire if <= 0. +func (c *cacheTagService) GetOrSetFunc(key interface{}, f func() (interface{}, error), duration time.Duration, tag interface{}) interface{} { + c.tagSetMux.Lock() + defer c.tagSetMux.Unlock() + c.cacheTagKey(key, tag) + v, _ := c.cache.GetOrSetFunc(key, f, duration) + return v +} + +// GetOrSetFuncLock returns the value of , or sets with result of function +// and returns its result if does not exist in the cache. The tagKey-value pair expires +// after . It does not expire if <= 0. +// +// Note that the function is executed within writing mutex lock. +func (c *cacheTagService) GetOrSetFuncLock(key interface{}, f func() (interface{}, error), duration time.Duration, tag interface{}) interface{} { + c.tagSetMux.Lock() + defer c.tagSetMux.Unlock() + c.cacheTagKey(key, tag) + v, _ := c.cache.GetOrSetFuncLock(key, f, duration) + return v +} + +// Contains returns true if exists in the cache, or else returns false. +func (c *cacheTagService) Contains(key interface{}) bool { + v, _ := c.cache.Contains(key) + return v +} + +// Remove deletes the in the cache, and returns its value. +func (c *cacheTagService) Remove(key interface{}) interface{} { + v, _ := c.cache.Remove(key) + return v +} + +// Removes deletes in the cache. +func (c *cacheTagService) Removes(keys []interface{}) { + c.cache.Remove(keys...) +} + +// Remove deletes the in the cache, and returns its value. +func (c *cacheTagService) RemoveByTag(tag interface{}) { + c.tagSetMux.Lock() + c.setTagKey(tag) + //删除tagKey 对应的 key和值 + keys := c.Get(c.tagKey) + if keys != nil { + //如果是字符串 + if kStr, ok := keys.(string); ok { + js, err := gjson.DecodeToJson(kStr) + if err != nil { + g.Log().Error(err) + return + } + ks := gconv.SliceAny(js.Value()) + c.Removes(ks) + } else { + ks := gconv.SliceAny(keys) + c.Removes(ks) + } + } + c.Remove(c.tagKey) + c.tagSetMux.Unlock() +} + +// Removes deletes in the cache. +func (c *cacheTagService) RemoveByTags(tag []interface{}) { + for _, v := range tag { + c.RemoveByTag(v) + } +} + +// Data returns a copy of all tagKey-value pairs in the cache as map type. +func (c *cacheTagService) Data() map[interface{}]interface{} { + v, _ := c.cache.Data() + return v +} + +// Keys returns all keys in the cache as slice. +func (c *cacheTagService) Keys() []interface{} { + v, _ := c.cache.Keys() + return v +} + +// KeyStrings returns all keys in the cache as string slice. +func (c *cacheTagService) KeyStrings() []string { + v, _ := c.cache.KeyStrings() + return v +} + +// Values returns all values in the cache as slice. +func (c *cacheTagService) Values() []interface{} { + v, _ := c.cache.Values() + return v +} + +// Size returns the size of the cache. +func (c *cacheTagService) Size() int { + v, _ := c.cache.Size() + return v +} diff --git a/app/common/service/captcha.go b/app/common/service/captcha.go new file mode 100644 index 0000000..281cf7b --- /dev/null +++ b/app/common/service/captcha.go @@ -0,0 +1,41 @@ +package service + +import ( + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/text/gstr" + "github.com/mojocn/base64Captcha" +) + +type captcha struct{} + +var Captcha = new(captcha) + +//获取字母数字混合验证码 +func (s *captcha) GetVerifyImgString() (idKeyC string, base64stringC string) { + driver := &base64Captcha.DriverString{ + Height: 80, + Width: 240, + NoiseCount: 50, + ShowLineOptions: 20, + Length: 4, + Source: "abcdefghjkmnpqrstuvwxyz23456789", + Fonts: []string{"chromohv.ttf"}, + } + driver = driver.ConvertFonts() + store := base64Captcha.DefaultMemStore + c := base64Captcha.NewCaptcha(driver, store) + idKeyC, base64stringC, err := c.Generate() + if err != nil { + g.Log().Error(err) + } + return +} + +//验证输入的验证码是否正确 +func (s *captcha) VerifyString(id, answer string) bool { + driver := new(base64Captcha.DriverString) + store := base64Captcha.DefaultMemStore + c := base64Captcha.NewCaptcha(driver, store) + answer = gstr.ToLower(answer) + return c.Verify(id, answer, true) +} diff --git a/app/common/service/casbin.go b/app/common/service/casbin.go new file mode 100644 index 0000000..dd48c55 --- /dev/null +++ b/app/common/service/casbin.go @@ -0,0 +1,237 @@ +package service + +import ( + "gfast/app/common/dao" + dbModel "gfast/app/common/model" + "github.com/casbin/casbin/v2" + "github.com/casbin/casbin/v2/model" + "github.com/casbin/casbin/v2/persist" + "github.com/gogf/gf/frame/g" + "sync" +) + +type cabin struct{} + +type adapterCasbin struct { + Enforcer *casbin.SyncedEnforcer + EnforcerErr error +} + +var ( + Casbin = new(cabin) + once sync.Once + m sync.RWMutex + ac *adapterCasbin +) + +// GetEnforcer 获取adapter单例对象 +func (s *cabin) GetEnforcer() (enforcer *casbin.SyncedEnforcer, err error) { + once.Do(func() { + ac = s.newAdapter() + }) + enforcer = ac.Enforcer + err = ac.EnforcerErr + return +} + +//初始化adapter操作 +func (s *cabin) newAdapter() (a *adapterCasbin) { + a = new(adapterCasbin) + a.initPolicy() + return +} + +func (a *adapterCasbin) initPolicy() { + // Because the DB is empty at first, + // so we need to load the policy from the file adapter (.CSV) first. + e, err := casbin.NewSyncedEnforcer(g.Cfg().GetString("casbin.modelFile"), + g.Cfg().GetString("casbin.policyFile")) + + if err != nil { + a.EnforcerErr = err + return + } + + // This is a trick to save the current policy to the DB. + // We can't call e.SavePolicy() because the adapter in the enforcer is still the file adapter. + // The current policy means the policy in the Casbin enforcer (aka in memory). + //err = a.SavePolicy(e.GetModel()) + //if err != nil { + // return err + //} + //set adapter + e.SetAdapter(a) + // Clear the current policy. + e.ClearPolicy() + a.Enforcer = e + // Load the policy from DB. + err = a.LoadPolicy(e.GetModel()) + if err != nil { + a.EnforcerErr = err + return + } +} + +// SavePolicy saves policy to database. +func (a *adapterCasbin) SavePolicy(model model.Model) (err error) { + err = a.dropTable() + if err != nil { + return + } + err = a.createTable() + if err != nil { + return + } + for ptype, ast := range model["p"] { + for _, rule := range ast.Policy { + line := savePolicyLine(ptype, rule) + _, err := dao.CasbinRule.Data(line).Insert() + if err != nil { + return err + } + } + } + + for ptype, ast := range model["g"] { + for _, rule := range ast.Policy { + line := savePolicyLine(ptype, rule) + _, err := dao.CasbinRule.Data(line).Insert() + if err != nil { + return err + } + } + } + return +} + +func (a *adapterCasbin) dropTable() (err error) { + return +} + +func (a *adapterCasbin) createTable() (err error) { + return +} + +// LoadPolicy loads policy from database. +func (a *adapterCasbin) LoadPolicy(model model.Model) error { + var lines []*dbModel.CasbinRule + if err := dao.CasbinRule.Scan(&lines); err != nil { + return err + } + for _, line := range lines { + loadPolicyLine(line, model) + } + return nil +} + +// AddPolicy adds a policy rule to the storage. +func (a *adapterCasbin) AddPolicy(sec string, ptype string, rule []string) error { + line := savePolicyLine(ptype, rule) + _, err := dao.CasbinRule.Data(line).Insert() + return err +} + +// RemovePolicy removes a policy rule from the storage. +func (a *adapterCasbin) RemovePolicy(sec string, ptype string, rule []string) error { + line := savePolicyLine(ptype, rule) + err := rawDelete(a, line) + return err +} + +// RemoveFilteredPolicy removes policy rules that match the filter from the storage. +func (a *adapterCasbin) RemoveFilteredPolicy(sec string, ptype string, + fieldIndex int, fieldValues ...string) error { + line := &dbModel.CasbinRule{} + line.Ptype = ptype + if fieldIndex <= 0 && 0 < fieldIndex+len(fieldValues) { + line.V0 = fieldValues[0-fieldIndex] + } + if fieldIndex <= 1 && 1 < fieldIndex+len(fieldValues) { + line.V1 = fieldValues[1-fieldIndex] + } + if fieldIndex <= 2 && 2 < fieldIndex+len(fieldValues) { + line.V2 = fieldValues[2-fieldIndex] + } + if fieldIndex <= 3 && 3 < fieldIndex+len(fieldValues) { + line.V3 = fieldValues[3-fieldIndex] + } + if fieldIndex <= 4 && 4 < fieldIndex+len(fieldValues) { + line.V4 = fieldValues[4-fieldIndex] + } + if fieldIndex <= 5 && 5 < fieldIndex+len(fieldValues) { + line.V5 = fieldValues[5-fieldIndex] + } + err := rawDelete(a, line) + return err +} + +func loadPolicyLine(line *dbModel.CasbinRule, model model.Model) { + lineText := line.Ptype + if line.V0 != "" { + lineText += ", " + line.V0 + } + if line.V1 != "" { + lineText += ", " + line.V1 + } + if line.V2 != "" { + lineText += ", " + line.V2 + } + if line.V3 != "" { + lineText += ", " + line.V3 + } + if line.V4 != "" { + lineText += ", " + line.V4 + } + if line.V5 != "" { + lineText += ", " + line.V5 + } + persist.LoadPolicyLine(lineText, model) +} + +func savePolicyLine(ptype string, rule []string) *dbModel.CasbinRule { + line := &dbModel.CasbinRule{} + line.Ptype = ptype + if len(rule) > 0 { + line.V0 = rule[0] + } + if len(rule) > 1 { + line.V1 = rule[1] + } + if len(rule) > 2 { + line.V2 = rule[2] + } + if len(rule) > 3 { + line.V3 = rule[3] + } + if len(rule) > 4 { + line.V4 = rule[4] + } + if len(rule) > 5 { + line.V5 = rule[5] + } + return line +} + +func rawDelete(a *adapterCasbin, line *dbModel.CasbinRule) error { + db := dao.CasbinRule.Where("ptype = ?", line.Ptype) + if line.V0 != "" { + db = db.Where("v0 = ?", line.V0) + } + if line.V1 != "" { + db = db.Where("v1 = ?", line.V1) + } + if line.V2 != "" { + db = db.Where("v2 = ?", line.V2) + } + if line.V3 != "" { + db = db.Where("v3 = ?", line.V3) + } + if line.V4 != "" { + db = db.Where("v4 = ?", line.V4) + } + if line.V5 != "" { + db = db.Where("v5 = ?", line.V5) + } + _, err := db.Delete() + return err +} diff --git a/app/common/service/sys_config.go b/app/common/service/sys_config.go new file mode 100644 index 0000000..116707c --- /dev/null +++ b/app/common/service/sys_config.go @@ -0,0 +1,150 @@ +/* +* @desc:系统参数设置 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/5 18:00 + */ + +package service + +import ( + "gfast/app/common/dao" + "gfast/app/common/global" + "gfast/app/common/model" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" +) + +type sysConfig struct { +} + +var SysConfig = new(sysConfig) + +func (s *sysConfig) SelectListByPage(req *model.SysConfigSearchReq) (total, page int, list []*model.SysConfig, err error) { + m := dao.SysConfig.Ctx(req.Ctx) + if req != nil { + if req.ConfigName != "" { + m = m.Where("config_name like ?", "%"+req.ConfigName+"%") + } + if req.ConfigType != "" { + m = m.Where("config_type = ", gconv.Int(req.ConfigType)) + } + if req.ConfigKey != "" { + m = m.Where("config_key like ?", "%"+req.ConfigKey+"%") + } + if req.BeginTime != "" { + m = m.Where("create_time >= ? ", req.BeginTime) + } + + if req.EndTime != "" { + m = m.Where("create_time<=?", req.EndTime) + } + } + total, err = m.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + if req.PageNum == 0 { + req.PageNum = 1 + } + page = req.PageNum + if req.PageSize == 0 { + req.PageSize = model.PageSize + } + err = m.Page(page, req.PageSize).Order("config_id asc").Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + return + } + return +} + +// CheckConfigKeyUniqueAll 验证参数键名是否存在 +func (s *sysConfig) CheckConfigKeyUniqueAll(configKey string) error { + entity, err := dao.SysConfig.Fields(dao.SysConfig.C.ConfigId).FindOne(dao.SysConfig.C.ConfigKey, configKey) + if err != nil { + g.Log().Error(err) + return gerror.New("校验数据失败") + } + if entity != nil { + return gerror.New("参数键名已经存在") + } + return nil +} + +// AddSave 添加操作 +func (s *sysConfig) AddSave(req *model.SysConfigAddReq) (err error) { + _, err = dao.SysConfig.Insert(req) + return +} + +func (s *sysConfig) GetById(id int) (data *model.SysConfig, err error) { + err = dao.SysConfig.WherePri(id).Scan(&data) + return +} + +// CheckConfigKeyUnique 检查键是否已经存在 +func (s *sysConfig) CheckConfigKeyUnique(configKey string, configId int64) error { + entity, err := dao.SysConfig.Fields(dao.SysConfig.C.ConfigId). + FindOne(dao.SysConfig.C.ConfigKey+"=? and "+dao.SysConfig.C.ConfigId+"!=?", + configKey, configId) + if err != nil { + g.Log().Error(err) + return gerror.New("校验数据失败") + } + if entity != nil { + return gerror.New("参数键名已经存在") + } + return nil +} + +// EditSave 修改系统参数 +func (s *sysConfig) EditSave(req *model.SysConfigEditReq) (err error) { + _, err = dao.SysConfig.FieldsEx(dao.SysConfig.C.ConfigId, dao.SysConfig.C.CreateBy). + WherePri(req.ConfigId).Data(req).Update() + return +} + +// DeleteByIds 删除 +func (s *sysConfig) DeleteByIds(ids []int) error { + _, err := dao.SysConfig.Delete(dao.SysConfig.C.ConfigId+" in (?)", ids) + if err != nil { + g.Log().Error(err) + return gerror.New("删除失败") + } + return nil +} + +// GetConfigByKey 通过key获取参数(从缓存获取) +func (s *sysConfig) GetConfigByKey(key string) (config *model.SysConfig, err error) { + if key == "" { + err = gerror.New("参数key不能为空") + return + } + cache := Cache.New() + cf := cache.Get(global.SysConfigTag + key) + if cf != nil { + err = gconv.Struct(cf, &config) + return + } + config, err = s.GetByKey(key) + if err != nil { + return + } + cache.Set(global.SysConfigTag+key, config, 0, global.SysConfigTag) + return +} + +// GetByKey 通过key获取参数(从数据库获取) +func (s *sysConfig) GetByKey(key string) (config *model.SysConfig, err error) { + err = dao.SysConfig.Where("config_key", key).Scan(&config) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取配置失败") + } + return +} diff --git a/app/system/api/auth.go b/app/system/api/auth.go new file mode 100644 index 0000000..f153653 --- /dev/null +++ b/app/system/api/auth.go @@ -0,0 +1,228 @@ +package api + +import ( + "gfast/app/common/api" + comModel "gfast/app/common/model" + commonService "gfast/app/common/service" + "gfast/app/system/model" + "gfast/app/system/service" + "gfast/library" + "github.com/goflyfox/gtoken/gtoken" + "github.com/gogf/gf/crypto/gmd5" + "github.com/gogf/gf/encoding/gjson" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/gcache" + "github.com/gogf/gf/os/genv" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/gvalid" + "github.com/mssola/user_agent" + "strings" +) + +type auth struct { + api.CommonBase +} + +var ( + Auth = new(auth) + MultiLogin = g.Cfg().GetBool("gToken.system.MultiLogin") + GfToken = >oken.GfToken{ + CacheMode: g.Cfg().GetInt8("gToken.system.CacheMode"), + CacheKey: g.Cfg().GetString("gToken.system.CacheKey"), + Timeout: g.Cfg().GetInt("gToken.system.Timeout"), + MaxRefresh: g.Cfg().GetInt("gToken.system.MaxRefresh"), + TokenDelimiter: g.Cfg().GetString("gToken.system.TokenDelimiter"), + EncryptKey: g.Cfg().GetBytes("gToken.system.EncryptKey"), + AuthFailMsg: g.Cfg().GetString("gToken.system.AuthFailMsg"), + MultiLogin: MultiLogin, + LoginPath: "/login", + LoginBeforeFunc: Auth.login, + LoginAfterFunc: Auth.loginAfter, + LogoutPath: "/logout", + AuthExcludePaths: g.SliceStr{"/login"}, + AuthAfterFunc: Auth.authAfterFunc, + LogoutBeforeFunc: Auth.loginOut, + } +) + +//后台用户登陆验证 +func (c *auth) login(r *ghttp.Request) (string, interface{}) { + var ctx = r.GetCtx() + var apiReq *model.LoginParamsReq + if err := r.Parse(&apiReq); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + //判断验证码是否正确 + debug := genv.GetWithCmd("gf.debug") + if debug.Int() != 1 { + if !commonService.Captcha.VerifyString(apiReq.VerifyKey, apiReq.VerifyCode) { + c.FailJson(true, r, "验证码输入错误") + } + } + ip := library.GetClientIp(r) + userAgent := r.Header.Get("User-Agent") + if user, err := service.SysUser.GetAdminUserByUsernamePassword(ctx, apiReq); err != nil { + //保存日志(异步) + service.SysLoginLog.Invoke(&model.LoginLogParams{ + Status: 0, + Username: apiReq.Username, + Ip: ip, + UserAgent: userAgent, + Msg: err.Error(), + Module: "系统后台", + }) + c.FailJsonExit(r, err.Error()) + } else if user != nil { + r.SetParam("userInfo", user) + //更新用户登录记录 写入日志信息 + service.SysUser.UpdateLoginInfo(user.Id, apiReq.Username, ip, userAgent, "登录成功", "系统后台") + var keys string + if MultiLogin { + keys = gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword+ip) + } else { + keys = gconv.String(user.Id) + "-" + gmd5.MustEncryptString(user.UserName) + gmd5.MustEncryptString(user.UserPassword) + } + return keys, user + } + return "", nil +} + +//登录成功返回 +func (c *auth) loginAfter(r *ghttp.Request, respData gtoken.Resp) { + if !respData.Success() { + r.Response.WriteJson(respData) + } else { + token := respData.GetString("token") + uuid := respData.GetString("uuid") + var userInfo *model.LoginUserRes + r.GetParamVar("userInfo").Struct(&userInfo) + //保存用户在线状态token到数据库 + userAgent := r.Header.Get("User-Agent") + ua := user_agent.New(userAgent) + os := ua.OS() + explorer, _ := ua.Browser() + onlineData := &model.SysUserOnline{ + Uuid: uuid, + Token: token, + CreateTime: gtime.Now(), + UserName: userInfo.UserName, + Ip: library.GetClientIp(r), + Explorer: explorer, + Os: os, + } + //保存用户在线状态(异步) + service.Online.Invoke(onlineData) + c.SusJsonExit(r, g.Map{ + "token": token, + }) + } +} + +//gToken验证后返回 +func (c *auth) authAfterFunc(r *ghttp.Request, respData gtoken.Resp) { + if r.Method == "OPTIONS" || respData.Success() { + r.Middleware.Next() + } else { + c.JsonExit(r, respData.Code, "用户信息验证失败") + } +} + +//后台退出登陆 +func (c *auth) loginOut(r *ghttp.Request) bool { + //删除在线用户状态 + authHeader := r.Header.Get("Authorization") + if authHeader != "" { + parts := strings.SplitN(authHeader, " ", 2) + if len(parts) == 2 && parts[0] == "Bearer" && parts[1] != "" { + //删除在线用户状态操作 + service.Online.DeleteOnlineByToken(parts[1]) + } + } + authHeader = r.GetString("token") + if authHeader != "" { + //删除在线用户状态操作 + service.Online.DeleteOnlineByToken(authHeader) + } + return true +} + +// CheckUserOnline 检查在线用户 +func (c *auth) CheckUserOnline() { + param := &model.SysUserOnlineSearchReq{ + PageReq: comModel.PageReq{ + PageNum: 1, + PageSize: 50, + }, + } + var total int + for { + var ( + list []*model.SysUserOnline + err error + ) + total, _, list, err = service.Online.GetOnlineListPage(param, true) + if err != nil { + g.Log().Error(err) + break + } + if list == nil { + break + } + for _, v := range list { + if b := c.UserIsOnline(v.Token); !b { + service.Online.DeleteOnlineByToken(v.Token) + } + } + if param.PageNum*param.PageSize >= total { + break + } + param.PageNum++ + } +} + +// UserIsOnline 判断用户是否在线 +func (c *auth) UserIsOnline(token string) bool { + uuid, userKey := c.GetUuidUserKeyByToken(token) + cacheKey := GfToken.CacheKey + userKey + switch GfToken.CacheMode { + case gtoken.CacheModeCache: + userCacheValue, _ := gcache.Get(cacheKey) + if userCacheValue == nil { + return false + } + return true + case gtoken.CacheModeRedis: + var userCache g.Map + userCacheJson, err := g.Redis().Do("GET", cacheKey) + if err != nil { + g.Log().Error("[GToken]cache get error", err) + return false + } + if userCacheJson == nil { + return false + } + err = gjson.DecodeTo(userCacheJson, &userCache) + if err != nil { + g.Log().Error("[GToken]cache get json error", err) + return false + } + if uuid != userCache["uuid"] { + return false + } + return true + } + return false +} + +// GetUuidUserKeyByToken 通过token获取uuid和userKey +func (c *auth) GetUuidUserKeyByToken(token string) (uuid, userKey string) { + decryptToken := GfToken.DecryptToken(token) + if !decryptToken.Success() { + return + } + userKey = decryptToken.GetString("userKey") + uuid = decryptToken.GetString("uuid") + return +} diff --git a/app/system/api/sys_auth_rule.go b/app/system/api/sys_auth_rule.go new file mode 100644 index 0000000..1c83bcd --- /dev/null +++ b/app/system/api/sys_auth_rule.go @@ -0,0 +1,158 @@ +package api + +import ( + "gfast/app/common/global" + CommService "gfast/app/common/service" + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type authRule struct { + systemBase +} + +var AuthRule = new(authRule) + +func (c *authRule) MenuList(r *ghttp.Request) { + + var ( + req *model.SysAuthRuleReqSearch + listEntities []*model.SysAuthRuleInfoRes + err error + ) + + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.Error()) + } + + listEntities, err = service.Rule.GetMenuListSearch(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + + list := make([]*model.SysAuthRuleTreeRes, 0, len(listEntities)) + if !req.IsEmpty() { + for _, menu := range listEntities { + list = append(list, &model.SysAuthRuleTreeRes{ + SysAuthRuleInfoRes: menu, + }) + } + } else { + list = service.Rule.GetMenuListTree(0, listEntities) + } + c.SusJsonExit(r, g.Map{ + "list": list, + }) +} + +func (c *authRule) GetMenus(r *ghttp.Request) { + listEntities, err := service.Rule.GetIsMenuList() + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, g.Map{ + "parentList": listEntities, + }) +} + +func (c *authRule) AddMenuPost(r *ghttp.Request) { + var menu *model.MenuReq + if err := r.Parse(&menu); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + //判断菜单规则是否存在 + if !service.Rule.CheckMenuNameUnique(menu.Name, 0) { + c.FailJsonExit(r, "菜单规则名称已经存在") + } + + //判断路由是否已经存在 + if !service.Rule.CheckMenuPathUnique(menu.Path, 0) { + c.FailJsonExit(r, "路由地址已经存在") + } + err, _ := service.Rule.AddMenu(menu) + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "添加菜单失败") + } + CommService.Cache.New().RemoveByTag(global.SysAuthTag) + c.SusJsonExit(r, "添加菜单成功") +} + +func (c *authRule) ModelOptions(r *ghttp.Request) { + module := r.GetString("module") + models, err := service.Rule.ModelOptions(module) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + + c.SusJsonExit(r, models) +} + +func (c *authRule) GetMenu(r *ghttp.Request) { + id := r.GetUint64("menuId") + menuEntity, err := service.Rule.One(id) + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, err.Error()) + } + listEntities, err := service.Rule.GetIsMenuList() + if err != nil { + c.FailJsonExit(r, err.Error()) + } + list := service.Rule.ParentSonSort(listEntities, 0) + var models []*model.SysModelInfo + if menuEntity.ModuleType != "" { + models, err = service.Rule.ModelOptions(menuEntity.ModuleType) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + } + c.SusJsonExit(r, g.Map{ + "parentList": list, + "menu": menuEntity, + "modelOptions": models, + }) +} + +func (c *authRule) EditPost(r *ghttp.Request) { + id := r.GetInt("menuId") + menu := new(model.MenuReq) + if err := r.Parse(menu); err != nil { + c.FailJsonExit(r, err.Error()) + } + //判断菜单规则是否存在 + if !service.Rule.CheckMenuNameUnique(menu.Name, id) { + c.FailJsonExit(r, "菜单规则名称已经存在") + } + + //判断路由是否已经存在 + if !service.Rule.CheckMenuPathUnique(menu.Path, id) { + c.FailJsonExit(r, "路由地址已经存在") + } + + err, _ := service.Rule.EditMenu(menu, id) + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "修改菜单失败") + } + + CommService.Cache.New().RemoveByTag(global.SysAuthTag) + c.SusJsonExit(r, "修改菜单成功") +} + +func (c *authRule) DeleteMenu(r *ghttp.Request) { + ids := r.GetInts("ids") + if len(ids) == 0 { + c.FailJsonExit(r, "删除失败,参数错误") + } + err := service.Rule.DeleteMenuByIds(ids) + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "删除失败") + } + CommService.Cache.New().RemoveByTag(global.SysAuthTag) + c.SusJsonExit(r, "删除成功") +} diff --git a/app/system/api/sys_base.go b/app/system/api/sys_base.go new file mode 100644 index 0000000..716e71a --- /dev/null +++ b/app/system/api/sys_base.go @@ -0,0 +1,18 @@ +package api + +import ( + "context" + "gfast/app/common/api" + "gfast/app/system/dao" + "gfast/app/system/service" +) + +type systemBase struct { + api.CommonBase +} + +// GetCurrentUser 获取当前登陆用户信息 +func (c *systemBase) GetCurrentUser(ctx context.Context) *dao.CtxUser { + context := service.Context.Get(ctx) + return context.User +} diff --git a/app/system/api/sys_config.go b/app/system/api/sys_config.go new file mode 100644 index 0000000..aedbf48 --- /dev/null +++ b/app/system/api/sys_config.go @@ -0,0 +1,109 @@ +/* +* @desc:系统配置 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/5 17:46 + */ + +package api + +import ( + "gfast/app/common/global" + "gfast/app/common/model" + "gfast/app/common/service" + commonService "gfast/app/common/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type sysConfig struct { + systemBase +} + +var SysConfig = new(sysConfig) + +// List 系统参数配置列表 +func (c *sysConfig) List(r *ghttp.Request) { + var req *model.SysConfigSearchReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + req.Ctx = r.GetCtx() + total, page, list, err := service.SysConfig.SelectListByPage(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + + result := g.Map{ + "currentPage": page, + "total": total, + "list": list, + } + c.SusJsonExit(r, result) +} + +// Add 添加 +func (c *sysConfig) Add(r *ghttp.Request) { + var req *model.SysConfigAddReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + err := service.SysConfig.CheckConfigKeyUniqueAll(req.ConfigKey) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + req.CreateBy = c.GetCurrentUser(r.GetCtx()).GetUserId() //获取登陆用户id + err = service.SysConfig.AddSave(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + commonService.Cache.New().Remove(global.SysConfigTag + req.ConfigKey) + c.SusJsonExit(r, "添加参数成功") +} + +// Get 获取参数信息 +func (c *sysConfig) Get(r *ghttp.Request) { + id := r.GetInt("id") + params, err := service.SysConfig.GetById(id) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, params) +} + +// Edit 修改系统参数 +func (c *sysConfig) Edit(r *ghttp.Request) { + var req *model.SysConfigEditReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + err := service.SysConfig.CheckConfigKeyUnique(req.ConfigKey, req.ConfigId) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + req.UpdateBy = c.GetCurrentUser(r.Context()).GetUserId() + err = service.SysConfig.EditSave(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + commonService.Cache.New().Remove(global.SysConfigTag + req.ConfigKey) + c.SusJsonExit(r, "修改参数成功") +} + +// Delete 删除参数 +func (c *sysConfig) Delete(r *ghttp.Request) { + ids := r.GetInts("ids") + if len(ids) == 0 { + c.FailJsonExit(r, "删除失败") + } + err := service.SysConfig.DeleteByIds(ids) + if err != nil { + c.FailJsonExit(r, "删除失败") + } + commonService.Cache.New().RemoveByTag(global.SysConfigTag) + c.SusJsonExit(r, "删除成功") +} diff --git a/app/system/api/sys_dept.go b/app/system/api/sys_dept.go new file mode 100644 index 0000000..dca3a72 --- /dev/null +++ b/app/system/api/sys_dept.go @@ -0,0 +1,124 @@ +package api + +import ( + "gfast/app/common/global" + CommService "gfast/app/common/service" + "gfast/app/system/dao" + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type dept struct { + systemBase +} + +var Dept = new(dept) + +// List 部门列表 +func (c *dept) List(r *ghttp.Request) { + var searchParams *dao.SysDeptSearchParams + if err := r.Parse(&searchParams); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + if list, err := service.Dept.GetList(searchParams); err != nil { + c.FailJsonExit(r, err.Error()) + } else { + if list != nil { + c.SusJsonExit(r, list) + } else { + c.SusJsonExit(r, []*model.SysDept{}) + } + } +} + +func (c *dept) Add(r *ghttp.Request) { + var addParams *dao.SysDeptAddParams + if err := r.Parse(&addParams); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + addParams.CreatedBy = c.GetCurrentUser(r.GetCtx()).GetUserId() + if err := service.Dept.AddDept(addParams); err != nil { + c.FailJsonExit(r, err.Error()) + } + CommService.Cache.New().RemoveByTag(global.SysAuthTag) + c.SusJsonExit(r, "添加成功") +} + +func (c *dept) Get(r *ghttp.Request) { + id := r.GetUint64("id") + if id == 0 { + c.FailJsonExit(r, "参数错误") + } + if dept, err := service.Dept.GetDeptById(id); err != nil { + c.FailJsonExit(r, err.Error()) + } else { + c.SusJsonExit(r, dept) + } +} + +func (c *dept) Edit(r *ghttp.Request) { + var editParams *dao.EditParams + if err := r.Parse(&editParams); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + editParams.UpdatedBy = c.GetCurrentUser(r.GetCtx()).GetUserId() + if err := service.Dept.EditDept(editParams); err != nil { + c.FailJsonExit(r, err.Error()) + } + CommService.Cache.New().RemoveByTag(global.SysAuthTag) + c.SusJsonExit(r, "编辑成功") +} + +func (c *dept) Delete(r *ghttp.Request) { + id := r.GetInt64("id") + if id == 0 { + c.FailJsonExit(r, "删除失败") + } + err := service.Dept.DelDept(id) + if err != nil { + c.FailJsonExit(r, "删除失败") + } + CommService.Cache.New().RemoveByTag(global.SysAuthTag) + c.SusJsonExit(r, "删除成功") +} + +func (c *dept) RoleDeptTreeSelect(r *ghttp.Request) { + id := r.GetInt64("roleId") + if id == 0 { + c.FailJsonExit(r, "参数错误") + } + list, err := service.Dept.GetList(&dao.SysDeptSearchParams{ + Status: "1", + }) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + + //获取关联的角色数据权限 + checkedKeys, err := service.Dept.GetRoleDepts(id) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + dList := service.Dept.GetDeptListTree(0, list) + res := g.Map{ + "depts": dList, + "checkedKeys": checkedKeys, + } + c.SusJsonExit(r, res) +} + +func (c *dept) TreeSelect(r *ghttp.Request) { + //获取正常状态部门数据 + list, err := service.Dept.GetList(&dao.SysDeptSearchParams{Status: "1"}) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + dList := service.Dept.GetDeptListTree(0, list) + res := g.Map{ + "depts": dList, + } + c.SusJsonExit(r, res) +} diff --git a/app/system/api/sys_dict_data.go b/app/system/api/sys_dict_data.go new file mode 100644 index 0000000..c552c9d --- /dev/null +++ b/app/system/api/sys_dict_data.go @@ -0,0 +1,119 @@ +/* +* @desc:字典数据 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/4/3 11:52 + */ + +package api + +import ( + "gfast/app/common/global" + commonService "gfast/app/common/service" + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type dictData struct { + systemBase +} + +var DictData = new(dictData) + +// List 字典列表 +func (c *dictData) List(r *ghttp.Request) { + var req *model.SelectDictPageReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + req.Ctx = r.GetCtx() + total, page, list, err := service.SysDictData.DictDataList(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + result := g.Map{ + "currentPage": page, + "total": total, + "list": list, + } + c.SusJsonExit(r, result) +} + +// Add 添加字典数据 +func (c *dictData) Add(r *ghttp.Request) { + var req *model.DictDataAddReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + req.CreateBy = c.GetCurrentUser(r.GetCtx()).GetUserId() //获取登陆用户id + _, err := service.SysDictData.AddSave(req) + if err != nil { + g.Log().Error(err.Error()) + c.FailJsonExit(r, "字典数据添加失败") + } + //清除tag缓存 + commonService.Cache.New().RemoveByTag(global.SysDictTag) + c.SusJsonExit(r, "添加字典数据成功") +} + +// Get 获取字典数据信息 +func (c *dictData) Get(r *ghttp.Request) { + dictCode := r.GetInt("dictCode") + data, err := service.SysDictData.GetDictDataById(dictCode) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, data) +} + +// Edit 修改字典数据 +func (c *dictData) Edit(r *ghttp.Request) { + var req *model.EditDictDataReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + req.UpdateBy = c.GetCurrentUser(r.GetCtx()).GetUserId() + err := service.SysDictData.EditSaveData(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + //清除tag缓存 + commonService.Cache.New().RemoveByTag(global.SysDictTag) + c.SusJsonExit(r, "修改字典数据成功") +} + +// Delete 删除字典数据 +func (c *dictData) Delete(r *ghttp.Request) { + dictCodes := r.GetInts("ids") + if len(dictCodes) == 0 { + c.FailJsonExit(r, "删除失败") + } + err := service.SysDictData.DeleteDictDataByIds(dictCodes) + if err != nil { + c.FailJsonExit(r, "删除失败") + } + //清除tag缓存 + commonService.Cache.New().RemoveByTag(global.SysDictTag) + c.SusJsonExit(r, "删除成功") +} + +// GetDictData 获取字典数据 +func (c *dictData) GetDictData(r *ghttp.Request) { + var req *model.GetDictReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + req.Ctx = r.GetCtx() + dict, err := service.SysDictData.GetDictWithDataByType(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, dict) +} diff --git a/app/system/api/sys_dict_type.go b/app/system/api/sys_dict_type.go new file mode 100644 index 0000000..52af686 --- /dev/null +++ b/app/system/api/sys_dict_type.go @@ -0,0 +1,96 @@ +package api + +import ( + "gfast/app/common/global" + comService "gfast/app/common/service" + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type dictType struct { + systemBase +} + +var DictType = new(dictType) + +func (c *dictType) List(r *ghttp.Request) { + var req *model.ListSysDictTypeReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + req.Ctx = r.GetCtx() + total, page, list, err := service.SysDictType.SelectList(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, g.Map{ + "total": total, + "page": page, + "list": list, + }) +} + +func (c *dictType) Get(r *ghttp.Request) { + id := r.GetInt("dictId") + entity, err := service.SysDictType.GetDictById(id) + if err != nil { + c.FailJsonExit(r, "字典数据获取失败") + } + c.SusJsonExit(r, entity) +} + +func (c *dictType) Add(r *ghttp.Request) { + var req *model.SysDictTypeAddReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + if service.SysDictType.ExistsDictType(req.DictType) { + c.FailJsonExit(r, "字典类型已经存在") + } + req.CreateBy = c.GetCurrentUser(r.GetCtx()).GetUserId() + err := service.SysDictType.Add(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + //清除缓存 + comService.Cache.New().RemoveByTag(global.SysDictTag) + c.SusJsonExit(r) +} + +func (c *dictType) Edit(r *ghttp.Request) { + var req *model.SysDictTypeEditReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + if service.SysDictType.ExistsDictType(req.DictType, req.DictId) { + c.FailJsonExit(r, "字典类型已经存在") + } + ctx := r.GetCtx() + req.UpdateBy = c.GetCurrentUser(ctx).Id + err := service.SysDictType.Edit(ctx, req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + //清除缓存 + comService.Cache.New().RemoveByTag(global.SysDictTag) + c.SusJsonExit(r) +} + +func (c *dictType) Delete(r *ghttp.Request) { + dictIds := r.GetInts("dictIds") + if len(dictIds) == 0 { + c.FailJsonExit(r, "参数错误") + } + if err := service.SysDictType.Delete(r.GetCtx(), dictIds); err != nil { + c.FailJsonExit(r, "删除失败") + } + //清除缓存 + comService.Cache.New().RemoveByTag(global.SysDictTag) + c.SusJsonExit(r) +} diff --git a/app/system/api/sys_job.go b/app/system/api/sys_job.go new file mode 100644 index 0000000..8f066d4 --- /dev/null +++ b/app/system/api/sys_job.go @@ -0,0 +1,116 @@ +/* +* @desc:定时任务 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/14 9:02 + */ + +package api + +import ( + "gfast/app/system/dao" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type sysJob struct { + systemBase +} + +var SysJob = new(sysJob) + +// List 任务列表 +func (c *sysJob) List(r *ghttp.Request) { + var req *dao.SysJobSearchReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + total, page, list, err := service.SysJob.JobList(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + result := g.Map{ + "currentPage": page, + "total": total, + "list": list, + } + c.SusJsonExit(r, result) +} + +func (c *sysJob) Add(r *ghttp.Request) { + var req *dao.SysJobAddReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + req.CreateBy = c.GetCurrentUser(r.GetCtx()).GetUserId() + err := service.SysJob.AddJob(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "任务添加成功") +} + +func (c *sysJob) Get(r *ghttp.Request) { + id := r.GetInt64("id") + job, err := service.SysJob.GetJobInfoById(id) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, job) +} + +func (c *sysJob) Edit(r *ghttp.Request) { + var req *dao.SysJobEditReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + req.UpdateBy = c.GetCurrentUser(r.GetCtx()).GetUserId() //获取登陆用户id + err := service.SysJob.EditJob(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "修改任务成功") +} + +// Start 启动任务 +func (c *sysJob) Start(r *ghttp.Request) { + id := r.GetInt64("id") + job, err := service.SysJob.GetJobInfoById(id) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + err = service.SysJob.JobStart(job) + if err != nil { + c.FailJsonExit(r, "定时任务管理启动"+err.Error()) + } + c.SusJsonExit(r, "定时任务管理启动成功") +} + +// Stop 停止任务 +func (c *sysJob) Stop(r *ghttp.Request) { + id := r.GetInt64("id") + job, err := service.SysJob.GetJobInfoById(id) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + err = service.SysJob.JobStop(job) + if err != nil { + c.FailJsonExit(r, "定时任务管理停止"+err.Error()) + } + c.SusJsonExit(r, "定时任务管理停止成功") +} + +// Delete 删除任务 +func (c *sysJob) Delete(r *ghttp.Request) { + ids := r.GetInts("ids") + err := service.SysJob.DeleteJobByIds(ids) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "删除成功") +} diff --git a/app/system/api/sys_login_log.go b/app/system/api/sys_login_log.go new file mode 100644 index 0000000..7391405 --- /dev/null +++ b/app/system/api/sys_login_log.go @@ -0,0 +1,60 @@ +/* +* @desc:登录日志 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/19 10:21 + */ + +package api + +import ( + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type sysLoginLog struct { + systemBase +} + +var SysLoginLog = new(sysLoginLog) + +// List 获取日志列表 +func (c sysLoginLog) List(r *ghttp.Request) { + var req *model.SysLoginLogSearchReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + total, page, list, err := service.SysLoginLog.LoginLogListByPage(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + result := g.Map{ + "currentPage": page, + "total": total, + "list": list, + } + c.SusJsonExit(r, result) +} + +// Delete 删除日志 +func (c *sysLoginLog) Delete(r *ghttp.Request) { + ids := r.GetInts("ids") + err := service.SysLoginLog.DeleteLoginLogByIds(ids) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "删除成功") +} + +// Clear 清空日志 +func (c *sysLoginLog) Clear(r *ghttp.Request) { + err := service.SysLoginLog.ClearLoginLog() + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "清除成功") +} diff --git a/app/system/api/sys_monitor.go b/app/system/api/sys_monitor.go new file mode 100644 index 0000000..8ad819e --- /dev/null +++ b/app/system/api/sys_monitor.go @@ -0,0 +1,150 @@ +/* +* @desc:系统服务信息 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/19 9:03 + */ + +package api + +import ( + "fmt" + "gfast/library" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/util/gconv" + "github.com/shirou/gopsutil/cpu" + "github.com/shirou/gopsutil/disk" + "github.com/shirou/gopsutil/host" + "github.com/shirou/gopsutil/load" + "github.com/shirou/gopsutil/mem" + "os" + "runtime" + "strconv" + "time" +) + +type sysMonitor struct { + systemBase + startTime *gtime.Time +} + +var SysMonitor = &sysMonitor{ + startTime: gtime.Now(), +} + +// Info 服务监控信息 +func (c *sysMonitor) Info(r *ghttp.Request) { + cpuNum := runtime.NumCPU() //核心数 + var cpuUsed float64 = 0 //用户使用率 + var cpuAvg5 float64 = 0 //CPU负载5 + var cpuAvg15 float64 = 0 //当前空闲率 + + cpuInfo, err := cpu.Percent(time.Duration(time.Second), false) + if err == nil { + cpuUsed, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", cpuInfo[0]), 64) + } + + loadInfo, err := load.Avg() + if err == nil { + cpuAvg5, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", loadInfo.Load5), 64) + cpuAvg15, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", loadInfo.Load5), 64) + } + + var memTotal uint64 = 0 //总内存 + var memUsed uint64 = 0 //总内存 := 0 //已用内存 + var memFree uint64 = 0 //剩余内存 + var memUsage float64 = 0 //使用率 + + v, err := mem.VirtualMemory() + if err == nil { + memTotal = v.Total + memUsed = v.Used + memFree = memTotal - memUsed + memUsage, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", v.UsedPercent), 64) + } + + var goTotal uint64 = 0 //go分配的总内存数 + var goUsed uint64 = 0 //go使用的内存数 + var goFree uint64 = 0 //go剩余的内存数 + var goUsage float64 = 0 //使用率 + + var gomem runtime.MemStats + runtime.ReadMemStats(&gomem) + goUsed = gomem.Sys + goUsage = gconv.Float64(fmt.Sprintf("%.2f", gconv.Float64(goUsed)/gconv.Float64(memTotal)*100)) + sysComputerIp := "" //服务器IP + + ip, err := library.GetLocalIP() + if err == nil { + sysComputerIp = ip + } + + sysComputerName := "" //服务器名称 + sysOsName := "" //操作系统 + sysOsArch := "" //系统架构 + + sysInfo, err := host.Info() + + if err == nil { + sysComputerName = sysInfo.Hostname + sysOsName = sysInfo.OS + sysOsArch = sysInfo.KernelArch + } + + goName := "GoLang" //语言环境 + goVersion := runtime.Version() //版本 + gtime.Date() + goStartTime := c.startTime //启动时间 + + goRunTime := gtime.Now().Timestamp() - c.startTime.Timestamp() //运行时长(秒) + goHome := runtime.GOROOT() //安装路径 + goUserDir := "" //项目路径 + + curDir, err := os.Getwd() + + if err == nil { + goUserDir = curDir + } + + //服务器磁盘信息 + diskList := make([]disk.UsageStat, 0) + diskInfo, err := disk.Partitions(true) //所有分区 + if err == nil { + for _, p := range diskInfo { + diskDetail, err := disk.Usage(p.Mountpoint) + if err == nil { + diskDetail.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", diskDetail.UsedPercent), 64) + diskList = append(diskList, *diskDetail) + } + } + } + + res := g.Map{ + "cpuNum": cpuNum, + "cpuUsed": cpuUsed, + "cpuAvg5": cpuAvg5, + "cpuAvg15": cpuAvg15, + "memTotal": memTotal, + "goTotal": goTotal, + "memUsed": memUsed, + "goUsed": goUsed, + "memFree": memFree, + "goFree": goFree, + "memUsage": memUsage, + "goUsage": goUsage, + "sysComputerName": sysComputerName, + "sysOsName": sysOsName, + "sysComputerIp": sysComputerIp, + "sysOsArch": sysOsArch, + "goName": goName, + "goVersion": goVersion, + "goStartTime": goStartTime, + "goRunTime": goRunTime, + "goHome": goHome, + "goUserDir": goUserDir, + "diskList": diskList, + } + c.SusJsonExit(r, res) +} diff --git a/app/system/api/sys_oper_log.go b/app/system/api/sys_oper_log.go new file mode 100644 index 0000000..446e552 --- /dev/null +++ b/app/system/api/sys_oper_log.go @@ -0,0 +1,110 @@ +/* +* @desc:操作日志管理 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/19 14:50 + */ + +package api + +import ( + "gfast/app/system/dao" + "gfast/app/system/model" + "gfast/app/system/service" + "gfast/library" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gvalid" +) + +type sysOperLog struct { + systemBase +} + +var SysOperLog = new(sysOperLog) + +// List 操作日志列表 +func (c *sysOperLog) List(r *ghttp.Request) { + var req *dao.SysOperLogSearchReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + total, page, list, err := service.SysOperLog.OperationLogListByPage(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + result := g.Map{ + "currentPage": page, + "total": total, + "list": list, + } + c.SusJsonExit(r, result) +} + +// Detail 日志详细 +func (c *sysOperLog) Detail(r *ghttp.Request) { + id := r.GetInt64("id") + log, err := service.SysOperLog.GetOperationLogById(id) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, g.Map{ + "info": log, + }) +} + +// Delete 删除 +func (c *sysOperLog) Delete(r *ghttp.Request) { + ids := r.GetInts("ids") + err := service.SysOperLog.DeleteOperationLogByIds(ids) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "删除成功") +} + +// Clear 清空 +func (c *sysOperLog) Clear(r *ghttp.Request) { + err := service.SysOperLog.ClearOperationLog() + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "清除成功") +} + +// OperationLog 操作日志记录 +func (c *sysOperLog) OperationLog(r *ghttp.Request) { + user := c.GetCurrentUser(r.GetCtx()) + if user == nil { + return + } + url := r.Request.URL //请求地址 + //获取菜单 + //获取地址对应的菜单id + menuList, err := service.Rule.GetMenuList() + if err != nil { + g.Log().Error(err) + return + } + var menu *model.SysAuthRuleInfoRes + path := gstr.TrimLeft(url.Path, "/") + for _, m := range menuList { + if gstr.Equal(m.Name, path) { + menu = m + break + } + } + + data := &dao.SysOperLogAdd{ + User: user, + Menu: menu, + Url: url, + Params: r.GetMap(), + Method: r.Method, + ClientIp: library.GetClientIp(r), + OperatorType: 1, + } + service.SysOperLog.Invoke(data) +} diff --git a/app/system/api/sys_post.go b/app/system/api/sys_post.go new file mode 100644 index 0000000..05a6391 --- /dev/null +++ b/app/system/api/sys_post.go @@ -0,0 +1,88 @@ +/* +* @desc:岗位管理 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/12 10:32 + */ + +package api + +import ( + "gfast/app/system/dao" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type sysPost struct { + systemBase +} + +var SysPost = new(sysPost) + +func (c *sysPost) List(r *ghttp.Request) { + var req *dao.SysPostSearchParams + + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + total, page, list, err := service.SysPost.List(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + result := g.Map{ + "total": total, + "list": list, + "page": page, + } + c.SusJsonExit(r, result) +} + +func (c *sysPost) Add(r *ghttp.Request) { + var addParams *dao.SysPostAddParams + if err := r.Parse(&addParams); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + addParams.CreatedBy = c.GetCurrentUser(r.GetCtx()).GetUserId() + if err := service.SysPost.Add(addParams); err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "添加成功") +} + +func (c *sysPost) Get(r *ghttp.Request) { + id := r.GetInt64("id") + if id == 0 { + c.FailJsonExit(r, "id必须") + } + if post, err := service.SysPost.GetOneById(id); err != nil { + c.FailJsonExit(r, err.Error()) + } else { + c.SusJsonExit(r, post) + } +} + +func (c *sysPost) Edit(r *ghttp.Request) { + var editParams *dao.SysPostEditParams + if err := r.Parse(&editParams); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + editParams.UpdatedBy = c.GetCurrentUser(r.GetCtx()).GetUserId() + if err := service.SysPost.Edit(editParams); err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "修改成功") +} + +func (c *sysPost) Delete(r *ghttp.Request) { + ids := r.GetInts("ids") + if len(ids) == 0 { + c.FailJsonExit(r, "删除失败") + } + err := service.SysPost.Delete(ids) + if err != nil { + c.FailJsonExit(r, "删除失败") + } + c.SusJsonExit(r, "删除信息成功") +} diff --git a/app/system/api/sys_role.go b/app/system/api/sys_role.go new file mode 100644 index 0000000..4696205 --- /dev/null +++ b/app/system/api/sys_role.go @@ -0,0 +1,138 @@ +package api + +import ( + "gfast/app/common/global" + CommService "gfast/app/common/service" + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type sysRole struct { + systemBase +} + +var SysRole = new(sysRole) + +// RoleList 角色列表 +func (c *sysRole) RoleList(r *ghttp.Request) { + var req *model.SelectPageReq + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + total, page, list, err := service.SysRole.GetRoleListSearch(req) + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "获取数据失败") + } + c.SusJsonExit(r, g.Map{ + "currentPage": page, + "total": total, + "list": list, + }) +} + +// GetRoleMenu GetRole 新增角色 +func (c *sysRole) GetRoleMenu(r *ghttp.Request) { + mListEntities, err := service.Rule.GetMenuList() + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "获取数据失败") + } + mList := service.Rule.GetMenuListTree(0, mListEntities) + res := g.Map{ + "menuList": mList, + } + c.SusJsonExit(r, res) +} + +// AddRole 新增角色提交 +func (c *sysRole) AddRole(r *ghttp.Request) { + res := r.GetFormMap() + if err := service.SysRole.AddRolePost(res); err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "添加角色成功") +} + +// 获取修改的角色 +func (c *sysRole) GetRole(r *ghttp.Request) { + id := r.GetRequestInt("roleId") + //获取角色信息 + role, err := service.SysRole.One(id) + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "获取角色数据失败") + } + //获取菜单信息 + mListEntities, err := service.Rule.GetMenuList() + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "获取菜单数据失败") + } + mList := service.Rule.GetMenuListTree(0, mListEntities) + //获取角色关联的菜单规则 + gpSlice, err := service.SysRole.GetFilteredNamedPolicy(id) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, g.Map{ + "menuList": mList, + "role": role, + "checkedRules": gpSlice, + }) +} + +// EditRole 编辑角色提交 +func (c *sysRole) EditRole(r *ghttp.Request) { + id := r.GetRequestInt("roleId") + res := r.GetFormMap() + if err := service.SysRole.EditRolePost(res, id); err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "修改角色成功") +} + +// StatusSetRole 设置角色状态 +func (c *sysRole) StatusSetRole(r *ghttp.Request) { + var req *model.StatusSetReq + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + err := service.SysRole.StatusSetRole(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "状态设置成功") +} + +// RoleDataScope 角色数据权限分配 +func (c *sysRole) RoleDataScope(r *ghttp.Request) { + var req *model.DataScopeReq + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).Current().Error()) + } + err := service.SysRole.RoleDataScope(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + CommService.Cache.New().RemoveByTag(global.SysAuthTag) + c.SusJsonExit(r, req) +} + +// DeleteRole 删除角色 +func (c *sysRole) DeleteRole(r *ghttp.Request) { + ids := r.GetInts("ids") + if len(ids) == 0 { + c.FailJsonExit(r, "删除失败,参数错误") + } + err := service.SysRole.DeleteByIds(ids) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + CommService.Cache.New().RemoveByTag(global.SysAuthTag) + c.SusJsonExit(r, "删除成功") + +} diff --git a/app/system/api/sys_user.go b/app/system/api/sys_user.go new file mode 100644 index 0000000..eba58b5 --- /dev/null +++ b/app/system/api/sys_user.go @@ -0,0 +1,233 @@ +package api + +import ( + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/gvalid" +) + +type user struct { + systemBase +} + +var User = new(user) + +// UserList 获取用户列表 +func (c *user) UserList(r *ghttp.Request) { + var req *model.SysUserSearchReq + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + + if err := service.SysUser.WriteDeptIdsOfSearchReq(req); err != nil { + c.FailJsonExit(r, err.Error()) + } + + total, page, userList, err := service.SysUser.GetUserList(req) + if err != nil { + c.FailJsonExit(r, "获取用户列表数据失败") + } + + users, err := service.SysUser.GetUsersRoleDept(userList) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + + c.SusJsonExit(r, g.Map{ + "total": total, + "currentPage": page, + "userList": users, + }) +} + +// Get 获取添加用户信息 +func (c *user) Get(r *ghttp.Request) { + roleListEntities, err := service.SysRole.GetRoleList() + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "获取角色数据失败") + } + posts, err := service.SysUser.GetUsedPost() + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, g.Map{ + "roleList": roleListEntities, + "posts": posts, + }) +} + +// AddUser 添加用户提交 +func (c *user) AddUser(r *ghttp.Request) { + var req *model.AddUserReq + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + err := service.SysUser.AddUser(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "添加管理员成功") +} + +// GetEditUser 获取编辑的用户 +func (c *user) GetEditUser(r *ghttp.Request) { + id := r.GetUint64("id") + res, err := service.SysUser.GetEditUser(id) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, res) +} + +// EditUser 编辑用户提交 +func (c *user) EditUser(r *ghttp.Request) { + var req *model.EditUserReq + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + err := service.SysUser.EditUser(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "修改管理员成功") +} + +// GetInfo 获取登陆用户信息 +func (c *user) GetInfo(r *ghttp.Request) { + userInfo := c.GetCurrentUser(r.Context()) + rolesList := make([]string, 0, 10) + var permissions []string + userId := userInfo.Id + allRoles, err := service.SysRole.GetRoleList() + if err != nil { + c.FailJsonExit(r, err.Error()) + } + roles, err := service.SysUser.GetAdminRole(userId, allRoles) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + name := make([]string, len(roles)) + roleIds := make([]uint, len(roles)) + for k, v := range roles { + name[k] = v.Name + roleIds[k] = v.Id + } + isSuperAdmin := false + service.SysUser.NotCheckAuthAdminIds.Iterator(func(v interface{}) bool { + if gconv.Uint64(v) == userId { + isSuperAdmin = true + return false + } + return true + }) + if isSuperAdmin { + permissions = []string{"*/*/*"} + } else { + permissions, err = service.SysUser.GetPermissions(roleIds) + } + rolesList = name + c.SusJsonExit(r, g.Map{ + "user": userInfo, + "roles": rolesList, + "permissions": permissions, + }) +} + +// GetRouters 获取用户菜单 +func (c *user) GetRouters(r *ghttp.Request) { + //获取用户信息 + userInfo := c.GetCurrentUser(r.Context()) + //是否超管 + isSuperAdmin := false + userId := userInfo.Id + //获取无需验证权限的用户id + service.SysUser.NotCheckAuthAdminIds.Iterator(func(v interface{}) bool { + if gconv.Uint64(v) == userId { + isSuperAdmin = true + return false + } + return true + }) + //获取用户角色信息 + allRoles, err := service.SysRole.GetRoleList() + if err != nil { + c.FailJsonExit(r, err.Error()) + } + roles, e := service.SysUser.GetAdminRole(userId, allRoles) + if e != nil { + c.FailJsonExit(r, e.Error()) + } + name := make([]string, len(roles)) + roleIds := make([]uint, len(roles)) + for k, v := range roles { + name[k] = v.Name + roleIds[k] = v.Id + } + var menuList []service.UserMenus + //获取菜单信息 + if isSuperAdmin { + //超管获取所有菜单 + menuList, err = service.SysUser.GetAllMenus() + } else { + menuList, err = service.SysUser.GetAdminMenusByRoleIds(roleIds) + } + if err != nil { + c.FailJsonExit(r, e.Error()) + } + if menuList == nil { + menuList = make([]service.UserMenus, 0) + } + adminMenus := make([]service.UserMenus, 0, len(menuList)) + //过滤非后台模块的菜单 + for _, v := range menuList { + if v.ModuleType == "sys_admin" { + adminMenus = append(adminMenus, v) + } + } + c.SusJsonExit(r, adminMenus) +} + +func (c *user) ResetUserPwd(r *ghttp.Request) { + var req *model.SysUserResetPwdReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + if err := service.SysUser.ResetUserPwd(req); err != nil { + c.FailJsonExit(r, err.Error()) + } else { + c.SusJsonExit(r, "用户密码重置成功") + } +} + +func (c *user) ChangeUserStatus(r *ghttp.Request) { + var req *model.SysUserStatusReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + if err := service.SysUser.ChangeUserStatus(req); err != nil { + c.FailJsonExit(r, err.Error()) + } else { + c.SusJsonExit(r, "用户状态设置成功") + } +} + +func (c *user) DeleteUser(r *ghttp.Request) { + ids := r.GetInts("ids") + if len(ids) > 0 { + err := service.SysUser.DeleteUser(r.GetCtx(), ids) + if err != nil { + g.Log().Error(err) + c.FailJsonExit(r, "删除失败") + } + } else { + c.FailJsonExit(r, "删除失败,参数错误") + } + + c.SusJsonExit(r, "删除成功") +} diff --git a/app/system/api/sys_user_online.go b/app/system/api/sys_user_online.go new file mode 100644 index 0000000..b2e0d54 --- /dev/null +++ b/app/system/api/sys_user_online.go @@ -0,0 +1,57 @@ +/* +* @desc:在线用户管理 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/13 15:10 + */ + +package api + +import ( + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type sysUserOnline struct { + systemBase +} + +var SysUserOnline = new(sysUserOnline) + +// List 在线用户列表 +func (c *sysUserOnline) List(r *ghttp.Request) { + var req *model.SysUserOnlineSearchReq + //获取参数 + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + total, page, list, err := service.Online.GetOnlineListPage(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + result := g.Map{ + "currentPage": page, + "total": total, + "list": list, + } + c.SusJsonExit(r, result) +} + +// ForceLogout 强退用户 +func (c *sysUserOnline) ForceLogout(r *ghttp.Request) { + ids := r.GetInts("ids") + if len(ids) == 0 { + c.FailJsonExit(r, "参数错误") + } + tokens, err := service.Online.ForceLogout(ids) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + for _, token := range tokens { + GfToken.RemoveToken(token) + } + c.SusJsonExit(r, "用户已退出") +} diff --git a/app/system/api/sys_web_set.go b/app/system/api/sys_web_set.go new file mode 100644 index 0000000..1db3dc5 --- /dev/null +++ b/app/system/api/sys_web_set.go @@ -0,0 +1,45 @@ +/* +* @desc:站点设置 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/6 15:41 + */ + +package api + +import ( + "gfast/app/common/global" + commonService "gfast/app/common/service" + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type sysWebSet struct { + systemBase +} + +var SysWebSet = new(sysWebSet) + +func (c *sysWebSet) Update(r *ghttp.Request) { + var req *model.SysWebSetUpdateReq + err := r.Parse(&req) + if err != nil { + c.FailJson(true, r, err.(gvalid.Error).FirstString()) + } + err = service.SysWebSet.UpdateSave(req) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + commonService.Cache.New().Remove(global.SysWebSet) + c.SusJsonExit(r, "更新成功!") +} + +func (c *sysWebSet) Get(r *ghttp.Request) { + data, err := service.SysWebSet.Get() + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, data) +} diff --git a/app/system/api/upload.go b/app/system/api/upload.go new file mode 100644 index 0000000..bb4f90f --- /dev/null +++ b/app/system/api/upload.go @@ -0,0 +1,33 @@ +/* +* @desc:后台上传 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/7 15:10 + */ + +package api + +import ( + "gfast/app/common/adapter" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" +) + +type upload struct { + systemBase +} + +var Upload = new(upload) + +// UpImg 单图上传 +func (c *upload) UpImg(r *ghttp.Request) { + upFile := r.GetUploadFile("file") + info, err := adapter.Upload.UpImg(upFile) + if err != nil { + c.FailJsonExit(r, "上传失败,"+err.Error()) + } + res := g.Map{ + "fileInfo": info, + } + c.SusJsonExit(r, res) +} diff --git a/app/system/api/user_Profile.go b/app/system/api/user_Profile.go new file mode 100644 index 0000000..8664a3e --- /dev/null +++ b/app/system/api/user_Profile.go @@ -0,0 +1,82 @@ +/* +* @desc:个人中心 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/12 22:14 + */ + +package api + +import ( + "gfast/app/common/adapter" + "gfast/app/system/model" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/util/gvalid" +) + +type userProfile struct { + systemBase +} + +var UserProfile = new(userProfile) + +// Profile 获取个人信息 +func (c *userProfile) Profile(r *ghttp.Request) { + //获取用户信息 + user, err := service.SysUser.GetUserInfoById(c.GetCurrentUser(r.GetCtx()).GetUserId()) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + userInfo, err := service.SysUser.GetUserRoleDeptPost(user) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, userInfo) +} + +// Avatar 修改头像 +func (c *userProfile) Avatar(r *ghttp.Request) { + upFile := r.GetUploadFile("avatarfile") + info, err := adapter.Upload.UpImg(upFile) + if err != nil { + c.FailJsonExit(r, "上传失败,"+err.Error()) + } + res := g.Map{ + "fileInfo": info, + } + userId := c.GetCurrentUser(r.GetCtx()).GetUserId() + err = service.SysUser.SetAvatar(userId, info.FileUrl) + if err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, res) +} + +// Edit 修改个人信息 +func (c *userProfile) Edit(r *ghttp.Request) { + var req *model.ProfileUpReq + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + req.UserId = c.GetCurrentUser(r.GetCtx()).GetUserId() + if err := service.SysUser.ProfileEdit(req); err != nil { + c.FailJsonExit(r, err.Error()) + } + c.SusJsonExit(r, "修改成功") +} + +// UpdatePwd 修改密码 +func (c *userProfile) UpdatePwd(r *ghttp.Request) { + var req *model.ProfileUpdatePwdReq + if err := r.Parse(&req); err != nil { + c.FailJsonExit(r, err.(gvalid.Error).FirstString()) + } + req.UserId = c.GetCurrentUser(r.GetCtx()).GetUserId() + if err := service.SysUser.ProfileUpdatePwd(req); err != nil { + c.FailJsonExit(r, err.Error()) + } else { + c.SusJsonExit(r, "修改成功") + } +} diff --git a/app/system/dao/.gitkeep b/app/system/dao/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/system/dao/context.go b/app/system/dao/context.go new file mode 100644 index 0000000..3a25e92 --- /dev/null +++ b/app/system/dao/context.go @@ -0,0 +1,41 @@ +package dao + +import ( + "gfast/app/system/model" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" +) + +const ( + // CtxKey 上下文变量存储键名,前后端系统共享 + CtxKey = "GFastContext" +) + +// Context 请求上下文结构 +type Context struct { + Session *ghttp.Session // 当前Session管理对象 + User *CtxUser // 上下文用户信息 + Data g.Map // 自定KV变量,业务模块根据需要设置,不固定 +} + +// CtxUser 请求上下文中的用户信息 +type CtxUser struct { + Id uint64 `json:"id"` // 用户id + UserName string `json:"userName"` // 用户名 + DeptId uint64 `json:"deptId"` // 部门id + UserNickname string `json:"userNickname"` // 用户昵称 + UserStatus uint `json:"userStatus"` // 用户状态;0:禁用,1:正常,2:未验证 + IsAdmin int `json:"isAdmin"` // 是否后台管理员 1 是 0 否 + Avatar string `json:"avatar"` //头像 +} + +// GetUserId 获取登录用户id +func (ctxUser *CtxUser) GetUserId() (id uint64) { + return ctxUser.Id +} + +// GetDept 获取登录用户所属部门 +func (ctxUser *CtxUser) GetDept() (err error, dept *model.SysDept) { + err = g.DB().Model(SysDept.Table).WherePri(ctxUser.DeptId).Scan(&dept) + return +} diff --git a/app/system/dao/internal/sys_auth_rule.go b/app/system/dao/internal/sys_auth_rule.go new file mode 100644 index 0000000..6868efc --- /dev/null +++ b/app/system/dao/internal/sys_auth_rule.go @@ -0,0 +1,420 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "context" + "database/sql" + "gfast/app/system/model" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" + "time" +) + +// SysAuthRuleDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysAuthRuleDao struct { + gmvc.M + DB gdb.DB + Table string + Columns sysAuthRuleColumns +} + +// SysAuthRuleColumns defines and stores column names for table sys_auth_rule. +type sysAuthRuleColumns struct { + Id string // + Pid string // 父ID + Name string // 规则名称 + Title string // 规则名称 + Icon string // 图标 + Condition string // 条件 + Remark string // 备注 + MenuType string // 类型 0目录 1菜单 2按钮 + Weigh string // 权重 + Status string // 状态 + AlwaysShow string // 显示状态 + Path string // 路由地址 + JumpPath string // 跳转路由 + Component string // 组件路径 + IsFrame string // 是否外链 1是 0否 + ModuleType string // 所属模块 + ModelId string // 模型ID + CreatedAt string // 创建日期 + UpdatedAt string // 修改日期 + DeletedAt string // 删除日期 +} + +var ( + // SysAuthRule is globally public accessible object for table sys_auth_rule operations. + SysAuthRule = SysAuthRuleDao{ + M: g.DB("default").Model("sys_auth_rule").Safe(), + DB: g.DB("default"), + Table: "sys_auth_rule", + Columns: sysAuthRuleColumns{ + Id: "id", + Pid: "pid", + Name: "name", + Title: "title", + Icon: "icon", + Condition: "condition", + Remark: "remark", + MenuType: "menu_type", + Weigh: "weigh", + Status: "status", + AlwaysShow: "always_show", + Path: "path", + JumpPath: "jump_path", + Component: "component", + IsFrame: "is_frame", + ModuleType: "module_type", + ModelId: "model_id", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + }, + } +) + +// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy +// of current DB object and with given context in it. +// Note that this returned DB object can be used only once, so do not assign it to +// a global or package variable for long using. +func (d *SysAuthRuleDao) Ctx(ctx context.Context) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Ctx(ctx)} +} + +// As sets an alias name for current table. +func (d *SysAuthRuleDao) As(as string) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.As(as)} +} + +// TX sets the transaction for current operation. +func (d *SysAuthRuleDao) TX(tx *gdb.TX) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.TX(tx)} +} + +// Master marks the following operation on master node. +func (d *SysAuthRuleDao) Master() *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Master()} +} + +// Slave marks the following operation on slave node. +// Note that it makes sense only if there's any slave node configured. +func (d *SysAuthRuleDao) Slave() *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Slave()} +} + +// Args sets custom arguments for model operation. +func (d *SysAuthRuleDao) Args(args ...interface{}) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Args(args...)} +} + +// LeftJoin does "LEFT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysAuthRuleDao) LeftJoin(table ...string) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.LeftJoin(table...)} +} + +// RightJoin does "RIGHT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysAuthRuleDao) RightJoin(table ...string) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.RightJoin(table...)} +} + +// InnerJoin does "INNER JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysAuthRuleDao) InnerJoin(table ...string) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.InnerJoin(table...)} +} + +// Fields sets the operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysAuthRuleDao) Fields(fieldNamesOrMapStruct ...interface{}) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Fields(fieldNamesOrMapStruct...)} +} + +// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysAuthRuleDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)} +} + +// Option sets the extra operation option for the model. +func (d *SysAuthRuleDao) Option(option int) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Option(option)} +} + +// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers +// the data and where attributes for empty values. +func (d *SysAuthRuleDao) OmitEmpty() *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.OmitEmpty()} +} + +// Filter marks filtering the fields which does not exist in the fields of the operated table. +func (d *SysAuthRuleDao) Filter() *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Filter()} +} + +// Where sets the condition statement for the model. The parameter can be type of +// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times, +// multiple conditions will be joined into where statement using "AND". +// Eg: +// Where("uid=10000") +// Where("uid", 10000) +// Where("money>? AND name like ?", 99999, "vip_%") +// Where("uid", 1).Where("name", "john") +// Where("status IN (?)", g.Slice{1,2,3}) +// Where("age IN(?,?)", 18, 50) +// Where(User{ Id : 1, UserName : "john"}) +func (d *SysAuthRuleDao) Where(where interface{}, args ...interface{}) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Where(where, args...)} +} + +// WherePri does the same logic as M.Where except that if the parameter +// is a single condition like int/string/float/slice, it treats the condition as the primary +// key value. That is, if primary key is "id" and given parameter as "123", the +// WherePri function treats the condition as "id=123", but M.Where treats the condition +// as string "123". +func (d *SysAuthRuleDao) WherePri(where interface{}, args ...interface{}) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.WherePri(where, args...)} +} + +// And adds "AND" condition to the where statement. +func (d *SysAuthRuleDao) And(where interface{}, args ...interface{}) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.And(where, args...)} +} + +// Or adds "OR" condition to the where statement. +func (d *SysAuthRuleDao) Or(where interface{}, args ...interface{}) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Or(where, args...)} +} + +// Group sets the "GROUP BY" statement for the model. +func (d *SysAuthRuleDao) Group(groupBy string) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Group(groupBy)} +} + +// Order sets the "ORDER BY" statement for the model. +func (d *SysAuthRuleDao) Order(orderBy ...string) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Order(orderBy...)} +} + +// Limit sets the "LIMIT" statement for the model. +// The parameter can be either one or two number, if passed two number is passed, +// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]" +// statement. +func (d *SysAuthRuleDao) Limit(limit ...int) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Limit(limit...)} +} + +// Offset sets the "OFFSET" statement for the model. +// It only makes sense for some databases like SQLServer, PostgreSQL, etc. +func (d *SysAuthRuleDao) Offset(offset int) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Offset(offset)} +} + +// Page sets the paging number for the model. +// The parameter is started from 1 for paging. +// Note that, it differs that the Limit function start from 0 for "LIMIT" statement. +func (d *SysAuthRuleDao) Page(page, limit int) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Page(page, limit)} +} + +// Batch sets the batch operation number for the model. +func (d *SysAuthRuleDao) Batch(batch int) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Batch(batch)} +} + +// Cache sets the cache feature for the model. It caches the result of the sql, which means +// if there's another same sql request, it just reads and returns the result from cache, it +// but not committed and executed into the database. +// +// If the parameter < 0, which means it clear the cache with given . +// If the parameter = 0, which means it never expires. +// If the parameter > 0, which means it expires after . +// +// The optional parameter is used to bind a name to the cache, which means you can later +// control the cache like changing the or clearing the cache with specified . +// +// Note that, the cache feature is disabled if the model is operating on a transaction. +func (d *SysAuthRuleDao) Cache(duration time.Duration, name ...string) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Cache(duration, name...)} +} + +// Data sets the operation data for the model. +// The parameter can be type of string/map/gmap/slice/struct/*struct, etc. +// Eg: +// Data("uid=10000") +// Data("uid", 10000) +// Data(g.Map{"uid": 10000, "name":"john"}) +// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) +func (d *SysAuthRuleDao) Data(data ...interface{}) *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Data(data...)} +} + +// All does "SELECT FROM ..." statement for the model. +// It retrieves the records from table and returns the result as []*model.SysAuthRule. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysAuthRuleDao) All(where ...interface{}) ([]*model.SysAuthRule, error) { + all, err := d.M.All(where...) + if err != nil { + return nil, err + } + var entities []*model.SysAuthRule + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// One retrieves one record from table and returns the result as *model.SysAuthRule. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysAuthRuleDao) One(where ...interface{}) (*model.SysAuthRule, error) { + one, err := d.M.One(where...) + if err != nil { + return nil, err + } + var entity *model.SysAuthRule + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindOne retrieves and returns a single Record by M.WherePri and M.One. +// Also see M.WherePri and M.One. +func (d *SysAuthRuleDao) FindOne(where ...interface{}) (*model.SysAuthRule, error) { + one, err := d.M.FindOne(where...) + if err != nil { + return nil, err + } + var entity *model.SysAuthRule + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindAll retrieves and returns Result by by M.WherePri and M.All. +// Also see M.WherePri and M.All. +func (d *SysAuthRuleDao) FindAll(where ...interface{}) ([]*model.SysAuthRule, error) { + all, err := d.M.FindAll(where...) + if err != nil { + return nil, err + } + var entities []*model.SysAuthRule + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// Struct retrieves one record from table and converts it into given struct. +// The parameter should be type of *struct/**struct. If type **struct is given, +// it can create the struct internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Struct(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Struct(&user) +func (d *SysAuthRuleDao) Struct(pointer interface{}, where ...interface{}) error { + return d.M.Struct(pointer, where...) +} + +// Structs retrieves records from table and converts them into given struct slice. +// The parameter should be type of *[]struct/*[]*struct. It can create and fill the struct +// slice internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not empty. +// +// Eg: +// users := ([]User)(nil) +// err := dao.User.Structs(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Structs(&users) +func (d *SysAuthRuleDao) Structs(pointer interface{}, where ...interface{}) error { + return d.M.Structs(pointer, where...) +} + +// Scan automatically calls Struct or Structs function according to the type of parameter . +// It calls function Struct if is type of *struct/**struct. +// It calls function Structs if is type of *[]struct/*[]*struct. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Scan(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Scan(&user) +// +// users := ([]User)(nil) +// err := dao.User.Scan(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Scan(&users) +func (d *SysAuthRuleDao) Scan(pointer interface{}, where ...interface{}) error { + return d.M.Scan(pointer, where...) +} + +// Chunk iterates the table with given size and callback function. +func (d *SysAuthRuleDao) Chunk(limit int, callback func(entities []*model.SysAuthRule, err error) bool) { + d.M.Chunk(limit, func(result gdb.Result, err error) bool { + var entities []*model.SysAuthRule + err = result.Structs(&entities) + if err == sql.ErrNoRows { + return false + } + return callback(entities, err) + }) +} + +// LockUpdate sets the lock for update for current operation. +func (d *SysAuthRuleDao) LockUpdate() *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.LockUpdate()} +} + +// LockShared sets the lock in share mode for current operation. +func (d *SysAuthRuleDao) LockShared() *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.LockShared()} +} + +// Unscoped enables/disables the soft deleting feature. +func (d *SysAuthRuleDao) Unscoped() *SysAuthRuleDao { + return &SysAuthRuleDao{M: d.M.Unscoped()} +} diff --git a/app/system/dao/internal/sys_dept.go b/app/system/dao/internal/sys_dept.go new file mode 100644 index 0000000..5ea8ecc --- /dev/null +++ b/app/system/dao/internal/sys_dept.go @@ -0,0 +1,65 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysDeptDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysDeptDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + C sysDeptColumns // C is the short type for Columns, which contains all the column names of Table for convenient usage. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the underlying table name of the DAO. +} + +// SysDeptColumns defines and stores column names for table sys_dept. +type sysDeptColumns struct { + DeptId string // 部门id + ParentId string // 父部门id + Ancestors string // 祖级列表 + DeptName string // 部门名称 + OrderNum string // 显示顺序 + Leader string // 负责人 + Phone string // 联系电话 + Email string // 邮箱 + Status string // 部门状态(0正常 1停用) + DelFlag string // 删除标志(0代表存在 2代表删除) + CreatedBy string // 创建人 + UpdatedBy string // 修改人 + CreatedAt string // 创建时间 + UpdatedAt string // 修改时间 + DeletedAt string // 删除时间 +} + +// NewSysDeptDao creates and returns a new DAO object for table data access. +func NewSysDeptDao() *SysDeptDao { + columns := sysDeptColumns{ + DeptId: "dept_id", + ParentId: "parent_id", + Ancestors: "ancestors", + DeptName: "dept_name", + OrderNum: "order_num", + Leader: "leader", + Phone: "phone", + Email: "email", + Status: "status", + DelFlag: "del_flag", + CreatedBy: "created_by", + UpdatedBy: "updated_by", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + } + return &SysDeptDao{ + C: columns, + M: g.DB("default").Model("sys_dept").Safe(), + DB: g.DB("default"), + Table: "sys_dept", + } +} diff --git a/app/system/dao/internal/sys_dict_data.go b/app/system/dao/internal/sys_dict_data.go new file mode 100644 index 0000000..69cf33a --- /dev/null +++ b/app/system/dao/internal/sys_dict_data.go @@ -0,0 +1,411 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "context" + "database/sql" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" + "time" + + "gfast/app/system/model" +) + +// SysDictDataDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysDictDataDao struct { + gmvc.M + DB gdb.DB + Table string + Columns sysDictDataColumns +} + +// SysDictDataColumns defines and stores column names for table sys_dict_data. +type sysDictDataColumns struct { + DictCode string // 字典编码 + DictSort string // 字典排序 + DictLabel string // 字典标签 + DictValue string // 字典键值 + DictType string // 字典类型 + CssClass string // 样式属性(其他样式扩展) + ListClass string // 表格回显样式 + IsDefault string // 是否默认(1是 0否) + Status string // 状态(0正常 1停用) + CreateBy string // 创建者 + UpdateBy string // 更新者 + Remark string // 备注 + CreatedAt string // 创建时间 + UpdatedAt string // 修改时间 + DeletedAt string // 删除时间 +} + +var ( + // SysDictData is globally public accessible object for table sys_dict_data operations. + SysDictData = SysDictDataDao{ + M: g.DB("default").Model("sys_dict_data").Safe(), + DB: g.DB("default"), + Table: "sys_dict_data", + Columns: sysDictDataColumns{ + DictCode: "dict_code", + DictSort: "dict_sort", + DictLabel: "dict_label", + DictValue: "dict_value", + DictType: "dict_type", + CssClass: "css_class", + ListClass: "list_class", + IsDefault: "is_default", + Status: "status", + CreateBy: "create_by", + UpdateBy: "update_by", + Remark: "remark", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + }, + } +) + +// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy +// of current DB object and with given context in it. +// Note that this returned DB object can be used only once, so do not assign it to +// a global or package variable for long using. +func (d *SysDictDataDao) Ctx(ctx context.Context) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Ctx(ctx)} +} + +// As sets an alias name for current table. +func (d *SysDictDataDao) As(as string) *SysDictDataDao { + return &SysDictDataDao{M: d.M.As(as)} +} + +// TX sets the transaction for current operation. +func (d *SysDictDataDao) TX(tx *gdb.TX) *SysDictDataDao { + return &SysDictDataDao{M: d.M.TX(tx)} +} + +// Master marks the following operation on master node. +func (d *SysDictDataDao) Master() *SysDictDataDao { + return &SysDictDataDao{M: d.M.Master()} +} + +// Slave marks the following operation on slave node. +// Note that it makes sense only if there's any slave node configured. +func (d *SysDictDataDao) Slave() *SysDictDataDao { + return &SysDictDataDao{M: d.M.Slave()} +} + +// Args sets custom arguments for model operation. +func (d *SysDictDataDao) Args(args ...interface{}) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Args(args...)} +} + +// LeftJoin does "LEFT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysDictDataDao) LeftJoin(table ...string) *SysDictDataDao { + return &SysDictDataDao{M: d.M.LeftJoin(table...)} +} + +// RightJoin does "RIGHT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysDictDataDao) RightJoin(table ...string) *SysDictDataDao { + return &SysDictDataDao{M: d.M.RightJoin(table...)} +} + +// InnerJoin does "INNER JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysDictDataDao) InnerJoin(table ...string) *SysDictDataDao { + return &SysDictDataDao{M: d.M.InnerJoin(table...)} +} + +// Fields sets the operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysDictDataDao) Fields(fieldNamesOrMapStruct ...interface{}) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Fields(fieldNamesOrMapStruct...)} +} + +// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysDictDataDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *SysDictDataDao { + return &SysDictDataDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)} +} + +// Option sets the extra operation option for the model. +func (d *SysDictDataDao) Option(option int) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Option(option)} +} + +// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers +// the data and where attributes for empty values. +func (d *SysDictDataDao) OmitEmpty() *SysDictDataDao { + return &SysDictDataDao{M: d.M.OmitEmpty()} +} + +// Filter marks filtering the fields which does not exist in the fields of the operated table. +func (d *SysDictDataDao) Filter() *SysDictDataDao { + return &SysDictDataDao{M: d.M.Filter()} +} + +// Where sets the condition statement for the model. The parameter can be type of +// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times, +// multiple conditions will be joined into where statement using "AND". +// Eg: +// Where("uid=10000") +// Where("uid", 10000) +// Where("money>? AND name like ?", 99999, "vip_%") +// Where("uid", 1).Where("name", "john") +// Where("status IN (?)", g.Slice{1,2,3}) +// Where("age IN(?,?)", 18, 50) +// Where(User{ Id : 1, UserName : "john"}) +func (d *SysDictDataDao) Where(where interface{}, args ...interface{}) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Where(where, args...)} +} + +// WherePri does the same logic as M.Where except that if the parameter +// is a single condition like int/string/float/slice, it treats the condition as the primary +// key value. That is, if primary key is "id" and given parameter as "123", the +// WherePri function treats the condition as "id=123", but M.Where treats the condition +// as string "123". +func (d *SysDictDataDao) WherePri(where interface{}, args ...interface{}) *SysDictDataDao { + return &SysDictDataDao{M: d.M.WherePri(where, args...)} +} + +// And adds "AND" condition to the where statement. +func (d *SysDictDataDao) And(where interface{}, args ...interface{}) *SysDictDataDao { + return &SysDictDataDao{M: d.M.And(where, args...)} +} + +// Or adds "OR" condition to the where statement. +func (d *SysDictDataDao) Or(where interface{}, args ...interface{}) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Or(where, args...)} +} + +// Group sets the "GROUP BY" statement for the model. +func (d *SysDictDataDao) Group(groupBy string) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Group(groupBy)} +} + +// Order sets the "ORDER BY" statement for the model. +func (d *SysDictDataDao) Order(orderBy ...string) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Order(orderBy...)} +} + +// Limit sets the "LIMIT" statement for the model. +// The parameter can be either one or two number, if passed two number is passed, +// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]" +// statement. +func (d *SysDictDataDao) Limit(limit ...int) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Limit(limit...)} +} + +// Offset sets the "OFFSET" statement for the model. +// It only makes sense for some databases like SQLServer, PostgreSQL, etc. +func (d *SysDictDataDao) Offset(offset int) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Offset(offset)} +} + +// Page sets the paging number for the model. +// The parameter is started from 1 for paging. +// Note that, it differs that the Limit function start from 0 for "LIMIT" statement. +func (d *SysDictDataDao) Page(page, limit int) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Page(page, limit)} +} + +// Batch sets the batch operation number for the model. +func (d *SysDictDataDao) Batch(batch int) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Batch(batch)} +} + +// Cache sets the cache feature for the model. It caches the result of the sql, which means +// if there's another same sql request, it just reads and returns the result from cache, it +// but not committed and executed into the database. +// +// If the parameter < 0, which means it clear the cache with given . +// If the parameter = 0, which means it never expires. +// If the parameter > 0, which means it expires after . +// +// The optional parameter is used to bind a name to the cache, which means you can later +// control the cache like changing the or clearing the cache with specified . +// +// Note that, the cache feature is disabled if the model is operating on a transaction. +func (d *SysDictDataDao) Cache(duration time.Duration, name ...string) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Cache(duration, name...)} +} + +// Data sets the operation data for the model. +// The parameter can be type of string/map/gmap/slice/struct/*struct, etc. +// Eg: +// Data("uid=10000") +// Data("uid", 10000) +// Data(g.Map{"uid": 10000, "name":"john"}) +// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) +func (d *SysDictDataDao) Data(data ...interface{}) *SysDictDataDao { + return &SysDictDataDao{M: d.M.Data(data...)} +} + +// All does "SELECT FROM ..." statement for the model. +// It retrieves the records from table and returns the result as []*model.SysDictData. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysDictDataDao) All(where ...interface{}) ([]*model.SysDictData, error) { + all, err := d.M.All(where...) + if err != nil { + return nil, err + } + var entities []*model.SysDictData + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// One retrieves one record from table and returns the result as *model.SysDictData. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysDictDataDao) One(where ...interface{}) (*model.SysDictData, error) { + one, err := d.M.One(where...) + if err != nil { + return nil, err + } + var entity *model.SysDictData + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindOne retrieves and returns a single Record by M.WherePri and M.One. +// Also see M.WherePri and M.One. +func (d *SysDictDataDao) FindOne(where ...interface{}) (*model.SysDictData, error) { + one, err := d.M.FindOne(where...) + if err != nil { + return nil, err + } + var entity *model.SysDictData + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindAll retrieves and returns Result by by M.WherePri and M.All. +// Also see M.WherePri and M.All. +func (d *SysDictDataDao) FindAll(where ...interface{}) ([]*model.SysDictData, error) { + all, err := d.M.FindAll(where...) + if err != nil { + return nil, err + } + var entities []*model.SysDictData + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// Struct retrieves one record from table and converts it into given struct. +// The parameter should be type of *struct/**struct. If type **struct is given, +// it can create the struct internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Struct(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Struct(&user) +func (d *SysDictDataDao) Struct(pointer interface{}, where ...interface{}) error { + return d.M.Struct(pointer, where...) +} + +// Structs retrieves records from table and converts them into given struct slice. +// The parameter should be type of *[]struct/*[]*struct. It can create and fill the struct +// slice internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not empty. +// +// Eg: +// users := ([]User)(nil) +// err := dao.User.Structs(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Structs(&users) +func (d *SysDictDataDao) Structs(pointer interface{}, where ...interface{}) error { + return d.M.Structs(pointer, where...) +} + +// Scan automatically calls Struct or Structs function according to the type of parameter . +// It calls function Struct if is type of *struct/**struct. +// It calls function Structs if is type of *[]struct/*[]*struct. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Scan(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Scan(&user) +// +// users := ([]User)(nil) +// err := dao.User.Scan(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Scan(&users) +func (d *SysDictDataDao) Scan(pointer interface{}, where ...interface{}) error { + return d.M.Scan(pointer, where...) +} + +// Chunk iterates the table with given size and callback function. +func (d *SysDictDataDao) Chunk(limit int, callback func(entities []*model.SysDictData, err error) bool) { + d.M.Chunk(limit, func(result gdb.Result, err error) bool { + var entities []*model.SysDictData + err = result.Structs(&entities) + if err == sql.ErrNoRows { + return false + } + return callback(entities, err) + }) +} + +// LockUpdate sets the lock for update for current operation. +func (d *SysDictDataDao) LockUpdate() *SysDictDataDao { + return &SysDictDataDao{M: d.M.LockUpdate()} +} + +// LockShared sets the lock in share mode for current operation. +func (d *SysDictDataDao) LockShared() *SysDictDataDao { + return &SysDictDataDao{M: d.M.LockShared()} +} + +// Unscoped enables/disables the soft deleting feature. +func (d *SysDictDataDao) Unscoped() *SysDictDataDao { + return &SysDictDataDao{M: d.M.Unscoped()} +} diff --git a/app/system/dao/internal/sys_dict_type.go b/app/system/dao/internal/sys_dict_type.go new file mode 100644 index 0000000..5576bc4 --- /dev/null +++ b/app/system/dao/internal/sys_dict_type.go @@ -0,0 +1,401 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "context" + "database/sql" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" + "time" + + "gfast/app/system/model" +) + +// SysDictTypeDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysDictTypeDao struct { + gmvc.M + DB gdb.DB + Table string + Columns sysDictTypeColumns +} + +// SysDictTypeColumns defines and stores column names for table sys_dict_type. +type sysDictTypeColumns struct { + DictId string // 字典主键 + DictName string // 字典名称 + DictType string // 字典类型 + Status string // 状态(0正常 1停用) + CreateBy string // 创建者 + UpdateBy string // 更新者 + Remark string // 备注 + CreatedAt string // 创建日期 + UpdatedAt string // 修改日期 + DeletedAt string // 删除日期 +} + +var ( + // SysDictType is globally public accessible object for table sys_dict_type operations. + SysDictType = SysDictTypeDao{ + M: g.DB("default").Model("sys_dict_type").Safe(), + DB: g.DB("default"), + Table: "sys_dict_type", + Columns: sysDictTypeColumns{ + DictId: "dict_id", + DictName: "dict_name", + DictType: "dict_type", + Status: "status", + CreateBy: "create_by", + UpdateBy: "update_by", + Remark: "remark", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + }, + } +) + +// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy +// of current DB object and with given context in it. +// Note that this returned DB object can be used only once, so do not assign it to +// a global or package variable for long using. +func (d *SysDictTypeDao) Ctx(ctx context.Context) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Ctx(ctx)} +} + +// As sets an alias name for current table. +func (d *SysDictTypeDao) As(as string) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.As(as)} +} + +// TX sets the transaction for current operation. +func (d *SysDictTypeDao) TX(tx *gdb.TX) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.TX(tx)} +} + +// Master marks the following operation on master node. +func (d *SysDictTypeDao) Master() *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Master()} +} + +// Slave marks the following operation on slave node. +// Note that it makes sense only if there's any slave node configured. +func (d *SysDictTypeDao) Slave() *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Slave()} +} + +// Args sets custom arguments for model operation. +func (d *SysDictTypeDao) Args(args ...interface{}) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Args(args...)} +} + +// LeftJoin does "LEFT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysDictTypeDao) LeftJoin(table ...string) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.LeftJoin(table...)} +} + +// RightJoin does "RIGHT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysDictTypeDao) RightJoin(table ...string) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.RightJoin(table...)} +} + +// InnerJoin does "INNER JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysDictTypeDao) InnerJoin(table ...string) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.InnerJoin(table...)} +} + +// Fields sets the operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysDictTypeDao) Fields(fieldNamesOrMapStruct ...interface{}) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Fields(fieldNamesOrMapStruct...)} +} + +// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysDictTypeDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)} +} + +// Option sets the extra operation option for the model. +func (d *SysDictTypeDao) Option(option int) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Option(option)} +} + +// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers +// the data and where attributes for empty values. +func (d *SysDictTypeDao) OmitEmpty() *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.OmitEmpty()} +} + +// Filter marks filtering the fields which does not exist in the fields of the operated table. +func (d *SysDictTypeDao) Filter() *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Filter()} +} + +// Where sets the condition statement for the model. The parameter can be type of +// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times, +// multiple conditions will be joined into where statement using "AND". +// Eg: +// Where("uid=10000") +// Where("uid", 10000) +// Where("money>? AND name like ?", 99999, "vip_%") +// Where("uid", 1).Where("name", "john") +// Where("status IN (?)", g.Slice{1,2,3}) +// Where("age IN(?,?)", 18, 50) +// Where(User{ Id : 1, UserName : "john"}) +func (d *SysDictTypeDao) Where(where interface{}, args ...interface{}) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Where(where, args...)} +} + +// WherePri does the same logic as M.Where except that if the parameter +// is a single condition like int/string/float/slice, it treats the condition as the primary +// key value. That is, if primary key is "id" and given parameter as "123", the +// WherePri function treats the condition as "id=123", but M.Where treats the condition +// as string "123". +func (d *SysDictTypeDao) WherePri(where interface{}, args ...interface{}) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.WherePri(where, args...)} +} + +// And adds "AND" condition to the where statement. +func (d *SysDictTypeDao) And(where interface{}, args ...interface{}) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.And(where, args...)} +} + +// Or adds "OR" condition to the where statement. +func (d *SysDictTypeDao) Or(where interface{}, args ...interface{}) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Or(where, args...)} +} + +// Group sets the "GROUP BY" statement for the model. +func (d *SysDictTypeDao) Group(groupBy string) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Group(groupBy)} +} + +// Order sets the "ORDER BY" statement for the model. +func (d *SysDictTypeDao) Order(orderBy ...string) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Order(orderBy...)} +} + +// Limit sets the "LIMIT" statement for the model. +// The parameter can be either one or two number, if passed two number is passed, +// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]" +// statement. +func (d *SysDictTypeDao) Limit(limit ...int) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Limit(limit...)} +} + +// Offset sets the "OFFSET" statement for the model. +// It only makes sense for some databases like SQLServer, PostgreSQL, etc. +func (d *SysDictTypeDao) Offset(offset int) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Offset(offset)} +} + +// Page sets the paging number for the model. +// The parameter is started from 1 for paging. +// Note that, it differs that the Limit function start from 0 for "LIMIT" statement. +func (d *SysDictTypeDao) Page(page, limit int) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Page(page, limit)} +} + +// Batch sets the batch operation number for the model. +func (d *SysDictTypeDao) Batch(batch int) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Batch(batch)} +} + +// Cache sets the cache feature for the model. It caches the result of the sql, which means +// if there's another same sql request, it just reads and returns the result from cache, it +// but not committed and executed into the database. +// +// If the parameter < 0, which means it clear the cache with given . +// If the parameter = 0, which means it never expires. +// If the parameter > 0, which means it expires after . +// +// The optional parameter is used to bind a name to the cache, which means you can later +// control the cache like changing the or clearing the cache with specified . +// +// Note that, the cache feature is disabled if the model is operating on a transaction. +func (d *SysDictTypeDao) Cache(duration time.Duration, name ...string) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Cache(duration, name...)} +} + +// Data sets the operation data for the model. +// The parameter can be type of string/map/gmap/slice/struct/*struct, etc. +// Eg: +// Data("uid=10000") +// Data("uid", 10000) +// Data(g.Map{"uid": 10000, "name":"john"}) +// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) +func (d *SysDictTypeDao) Data(data ...interface{}) *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Data(data...)} +} + +// All does "SELECT FROM ..." statement for the model. +// It retrieves the records from table and returns the result as []*model.SysDictType. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysDictTypeDao) All(where ...interface{}) ([]*model.SysDictType, error) { + all, err := d.M.All(where...) + if err != nil { + return nil, err + } + var entities []*model.SysDictType + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// One retrieves one record from table and returns the result as *model.SysDictType. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysDictTypeDao) One(where ...interface{}) (*model.SysDictType, error) { + one, err := d.M.One(where...) + if err != nil { + return nil, err + } + var entity *model.SysDictType + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindOne retrieves and returns a single Record by M.WherePri and M.One. +// Also see M.WherePri and M.One. +func (d *SysDictTypeDao) FindOne(where ...interface{}) (*model.SysDictType, error) { + one, err := d.M.FindOne(where...) + if err != nil { + return nil, err + } + var entity *model.SysDictType + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindAll retrieves and returns Result by by M.WherePri and M.All. +// Also see M.WherePri and M.All. +func (d *SysDictTypeDao) FindAll(where ...interface{}) ([]*model.SysDictType, error) { + all, err := d.M.FindAll(where...) + if err != nil { + return nil, err + } + var entities []*model.SysDictType + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// Struct retrieves one record from table and converts it into given struct. +// The parameter should be type of *struct/**struct. If type **struct is given, +// it can create the struct internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Struct(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Struct(&user) +func (d *SysDictTypeDao) Struct(pointer interface{}, where ...interface{}) error { + return d.M.Struct(pointer, where...) +} + +// Structs retrieves records from table and converts them into given struct slice. +// The parameter should be type of *[]struct/*[]*struct. It can create and fill the struct +// slice internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not empty. +// +// Eg: +// users := ([]User)(nil) +// err := dao.User.Structs(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Structs(&users) +func (d *SysDictTypeDao) Structs(pointer interface{}, where ...interface{}) error { + return d.M.Structs(pointer, where...) +} + +// Scan automatically calls Struct or Structs function according to the type of parameter . +// It calls function Struct if is type of *struct/**struct. +// It calls function Structs if is type of *[]struct/*[]*struct. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Scan(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Scan(&user) +// +// users := ([]User)(nil) +// err := dao.User.Scan(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Scan(&users) +func (d *SysDictTypeDao) Scan(pointer interface{}, where ...interface{}) error { + return d.M.Scan(pointer, where...) +} + +// Chunk iterates the table with given size and callback function. +func (d *SysDictTypeDao) Chunk(limit int, callback func(entities []*model.SysDictType, err error) bool) { + d.M.Chunk(limit, func(result gdb.Result, err error) bool { + var entities []*model.SysDictType + err = result.Structs(&entities) + if err == sql.ErrNoRows { + return false + } + return callback(entities, err) + }) +} + +// LockUpdate sets the lock for update for current operation. +func (d *SysDictTypeDao) LockUpdate() *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.LockUpdate()} +} + +// LockShared sets the lock in share mode for current operation. +func (d *SysDictTypeDao) LockShared() *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.LockShared()} +} + +// Unscoped enables/disables the soft deleting feature. +func (d *SysDictTypeDao) Unscoped() *SysDictTypeDao { + return &SysDictTypeDao{M: d.M.Unscoped()} +} diff --git a/app/system/dao/internal/sys_job.go b/app/system/dao/internal/sys_job.go new file mode 100644 index 0000000..9c1f9ae --- /dev/null +++ b/app/system/dao/internal/sys_job.go @@ -0,0 +1,65 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysJobDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysJobDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + C sysJobColumns // C is the short type for Columns, which contains all the column names of Table for convenient usage. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the underlying table name of the DAO. +} + +// SysJobColumns defines and stores column names for table sys_job. +type sysJobColumns struct { + JobId string // 任务ID + JobName string // 任务名称 + JobParams string // 参数 + JobGroup string // 任务组名 + InvokeTarget string // 调用目标字符串 + CronExpression string // cron执行表达式 + MisfirePolicy string // 计划执行策略(1多次执行 2执行一次) + Concurrent string // 是否并发执行(0允许 1禁止) + Status string // 状态(0正常 1暂停) + CreateBy string // 创建者 + UpdateBy string // 更新者 + Remark string // 备注信息 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 删除时间 +} + +// NewSysJobDao creates and returns a new DAO object for table data access. +func NewSysJobDao() *SysJobDao { + columns := sysJobColumns{ + JobId: "job_id", + JobName: "job_name", + JobParams: "job_params", + JobGroup: "job_group", + InvokeTarget: "invoke_target", + CronExpression: "cron_expression", + MisfirePolicy: "misfire_policy", + Concurrent: "concurrent", + Status: "status", + CreateBy: "create_by", + UpdateBy: "update_by", + Remark: "remark", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + } + return &SysJobDao{ + C: columns, + M: g.DB("default").Model("sys_job").Safe(), + DB: g.DB("default"), + Table: "sys_job", + } +} diff --git a/app/system/dao/internal/sys_login_log.go b/app/system/dao/internal/sys_login_log.go new file mode 100644 index 0000000..c043c68 --- /dev/null +++ b/app/system/dao/internal/sys_login_log.go @@ -0,0 +1,400 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "context" + "database/sql" + "gfast/app/system/model" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" + "time" +) + +// SysLoginLogDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysLoginLogDao struct { + gmvc.M + DB gdb.DB + Table string + Columns sysLoginLogColumns +} + +// SysLoginLogColumns defines and stores column names for table sys_login_log. +type sysLoginLogColumns struct { + InfoId string // 访问ID + LoginName string // 登录账号 + Ipaddr string // 登录IP地址 + LoginLocation string // 登录地点 + Browser string // 浏览器类型 + Os string // 操作系统 + Status string // 登录状态(0成功 1失败) + Msg string // 提示消息 + LoginTime string // 登录时间 + Module string // 登录模块 +} + +var ( + // SysLoginLog is globally public accessible object for table sys_login_log operations. + SysLoginLog = SysLoginLogDao{ + M: g.DB("default").Model("sys_login_log").Safe(), + DB: g.DB("default"), + Table: "sys_login_log", + Columns: sysLoginLogColumns{ + InfoId: "info_id", + LoginName: "login_name", + Ipaddr: "ipaddr", + LoginLocation: "login_location", + Browser: "browser", + Os: "os", + Status: "status", + Msg: "msg", + LoginTime: "login_time", + Module: "module", + }, + } +) + +// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy +// of current DB object and with given context in it. +// Note that this returned DB object can be used only once, so do not assign it to +// a global or package variable for long using. +func (d *SysLoginLogDao) Ctx(ctx context.Context) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Ctx(ctx)} +} + +// As sets an alias name for current table. +func (d *SysLoginLogDao) As(as string) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.As(as)} +} + +// TX sets the transaction for current operation. +func (d *SysLoginLogDao) TX(tx *gdb.TX) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.TX(tx)} +} + +// Master marks the following operation on master node. +func (d *SysLoginLogDao) Master() *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Master()} +} + +// Slave marks the following operation on slave node. +// Note that it makes sense only if there's any slave node configured. +func (d *SysLoginLogDao) Slave() *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Slave()} +} + +// Args sets custom arguments for model operation. +func (d *SysLoginLogDao) Args(args ...interface{}) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Args(args...)} +} + +// LeftJoin does "LEFT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysLoginLogDao) LeftJoin(table ...string) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.LeftJoin(table...)} +} + +// RightJoin does "RIGHT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysLoginLogDao) RightJoin(table ...string) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.RightJoin(table...)} +} + +// InnerJoin does "INNER JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysLoginLogDao) InnerJoin(table ...string) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.InnerJoin(table...)} +} + +// Fields sets the operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysLoginLogDao) Fields(fieldNamesOrMapStruct ...interface{}) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Fields(fieldNamesOrMapStruct...)} +} + +// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysLoginLogDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)} +} + +// Option sets the extra operation option for the model. +func (d *SysLoginLogDao) Option(option int) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Option(option)} +} + +// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers +// the data and where attributes for empty values. +func (d *SysLoginLogDao) OmitEmpty() *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.OmitEmpty()} +} + +// Filter marks filtering the fields which does not exist in the fields of the operated table. +func (d *SysLoginLogDao) Filter() *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Filter()} +} + +// Where sets the condition statement for the model. The parameter can be type of +// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times, +// multiple conditions will be joined into where statement using "AND". +// Eg: +// Where("uid=10000") +// Where("uid", 10000) +// Where("money>? AND name like ?", 99999, "vip_%") +// Where("uid", 1).Where("name", "john") +// Where("status IN (?)", g.Slice{1,2,3}) +// Where("age IN(?,?)", 18, 50) +// Where(User{ Id : 1, UserName : "john"}) +func (d *SysLoginLogDao) Where(where interface{}, args ...interface{}) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Where(where, args...)} +} + +// WherePri does the same logic as M.Where except that if the parameter +// is a single condition like int/string/float/slice, it treats the condition as the primary +// key value. That is, if primary key is "id" and given parameter as "123", the +// WherePri function treats the condition as "id=123", but M.Where treats the condition +// as string "123". +func (d *SysLoginLogDao) WherePri(where interface{}, args ...interface{}) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.WherePri(where, args...)} +} + +// And adds "AND" condition to the where statement. +func (d *SysLoginLogDao) And(where interface{}, args ...interface{}) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.And(where, args...)} +} + +// Or adds "OR" condition to the where statement. +func (d *SysLoginLogDao) Or(where interface{}, args ...interface{}) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Or(where, args...)} +} + +// Group sets the "GROUP BY" statement for the model. +func (d *SysLoginLogDao) Group(groupBy string) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Group(groupBy)} +} + +// Order sets the "ORDER BY" statement for the model. +func (d *SysLoginLogDao) Order(orderBy ...string) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Order(orderBy...)} +} + +// Limit sets the "LIMIT" statement for the model. +// The parameter can be either one or two number, if passed two number is passed, +// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]" +// statement. +func (d *SysLoginLogDao) Limit(limit ...int) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Limit(limit...)} +} + +// Offset sets the "OFFSET" statement for the model. +// It only makes sense for some databases like SQLServer, PostgreSQL, etc. +func (d *SysLoginLogDao) Offset(offset int) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Offset(offset)} +} + +// Page sets the paging number for the model. +// The parameter is started from 1 for paging. +// Note that, it differs that the Limit function start from 0 for "LIMIT" statement. +func (d *SysLoginLogDao) Page(page, limit int) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Page(page, limit)} +} + +// Batch sets the batch operation number for the model. +func (d *SysLoginLogDao) Batch(batch int) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Batch(batch)} +} + +// Cache sets the cache feature for the model. It caches the result of the sql, which means +// if there's another same sql request, it just reads and returns the result from cache, it +// but not committed and executed into the database. +// +// If the parameter < 0, which means it clear the cache with given . +// If the parameter = 0, which means it never expires. +// If the parameter > 0, which means it expires after . +// +// The optional parameter is used to bind a name to the cache, which means you can later +// control the cache like changing the or clearing the cache with specified . +// +// Note that, the cache feature is disabled if the model is operating on a transaction. +func (d *SysLoginLogDao) Cache(duration time.Duration, name ...string) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Cache(duration, name...)} +} + +// Data sets the operation data for the model. +// The parameter can be type of string/map/gmap/slice/struct/*struct, etc. +// Eg: +// Data("uid=10000") +// Data("uid", 10000) +// Data(g.Map{"uid": 10000, "name":"john"}) +// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) +func (d *SysLoginLogDao) Data(data ...interface{}) *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Data(data...)} +} + +// All does "SELECT FROM ..." statement for the model. +// It retrieves the records from table and returns the result as []*model.SysLoginLog. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysLoginLogDao) All(where ...interface{}) ([]*model.SysLoginLog, error) { + all, err := d.M.All(where...) + if err != nil { + return nil, err + } + var entities []*model.SysLoginLog + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// One retrieves one record from table and returns the result as *model.SysLoginLog. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysLoginLogDao) One(where ...interface{}) (*model.SysLoginLog, error) { + one, err := d.M.One(where...) + if err != nil { + return nil, err + } + var entity *model.SysLoginLog + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindOne retrieves and returns a single Record by M.WherePri and M.One. +// Also see M.WherePri and M.One. +func (d *SysLoginLogDao) FindOne(where ...interface{}) (*model.SysLoginLog, error) { + one, err := d.M.FindOne(where...) + if err != nil { + return nil, err + } + var entity *model.SysLoginLog + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindAll retrieves and returns Result by by M.WherePri and M.All. +// Also see M.WherePri and M.All. +func (d *SysLoginLogDao) FindAll(where ...interface{}) ([]*model.SysLoginLog, error) { + all, err := d.M.FindAll(where...) + if err != nil { + return nil, err + } + var entities []*model.SysLoginLog + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// Struct retrieves one record from table and converts it into given struct. +// The parameter should be type of *struct/**struct. If type **struct is given, +// it can create the struct internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Struct(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Struct(&user) +func (d *SysLoginLogDao) Struct(pointer interface{}, where ...interface{}) error { + return d.M.Struct(pointer, where...) +} + +// Structs retrieves records from table and converts them into given struct slice. +// The parameter should be type of *[]struct/*[]*struct. It can create and fill the struct +// slice internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not empty. +// +// Eg: +// users := ([]User)(nil) +// err := dao.User.Structs(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Structs(&users) +func (d *SysLoginLogDao) Structs(pointer interface{}, where ...interface{}) error { + return d.M.Structs(pointer, where...) +} + +// Scan automatically calls Struct or Structs function according to the type of parameter . +// It calls function Struct if is type of *struct/**struct. +// It calls function Structs if is type of *[]struct/*[]*struct. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Scan(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Scan(&user) +// +// users := ([]User)(nil) +// err := dao.User.Scan(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Scan(&users) +func (d *SysLoginLogDao) Scan(pointer interface{}, where ...interface{}) error { + return d.M.Scan(pointer, where...) +} + +// Chunk iterates the table with given size and callback function. +func (d *SysLoginLogDao) Chunk(limit int, callback func(entities []*model.SysLoginLog, err error) bool) { + d.M.Chunk(limit, func(result gdb.Result, err error) bool { + var entities []*model.SysLoginLog + err = result.Structs(&entities) + if err == sql.ErrNoRows { + return false + } + return callback(entities, err) + }) +} + +// LockUpdate sets the lock for update for current operation. +func (d *SysLoginLogDao) LockUpdate() *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.LockUpdate()} +} + +// LockShared sets the lock in share mode for current operation. +func (d *SysLoginLogDao) LockShared() *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.LockShared()} +} + +// Unscoped enables/disables the soft deleting feature. +func (d *SysLoginLogDao) Unscoped() *SysLoginLogDao { + return &SysLoginLogDao{M: d.M.Unscoped()} +} diff --git a/app/system/dao/internal/sys_model_info.go b/app/system/dao/internal/sys_model_info.go new file mode 100644 index 0000000..e9fc368 --- /dev/null +++ b/app/system/dao/internal/sys_model_info.go @@ -0,0 +1,69 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysModelInfoDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysModelInfoDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the table name of the DAO. + Columns sysModelInfoColumns // Columns contains all the columns of Table that for convenient usage. +} + +// SysModelInfoColumns defines and stores column names for table sys_model_info. +type sysModelInfoColumns struct { + ModelId string // 模型ID + ModelCategoryId string // 模板分类id + ModelName string // 模型标识 + ModelTitle string // 模型名称 + ModelPk string // 主键字段 + ModelOrder string // 默认排序字段 + ModelSort string // 表单字段排序 + ModelList string // 列表显示字段,为空显示全部 + ModelEdit string // 可编辑字段,为空则除主键外均可以编辑 + ModelIndexes string // 索引字段 + SearchList string // 高级搜索的字段 + CreateTime string // 创建时间 + UpdateTime string // 更新时间 + ModelStatus string // 状态 + ModelEngine string // 数据库引擎 + CreateBy string // 创建人 + UpdateBy string // 修改人 +} + +var ( + // SysModelInfo is globally public accessible object for table sys_model_info operations. + SysModelInfo = SysModelInfoDao{ + M: g.DB("default").Model("sys_model_info").Safe(), + DB: g.DB("default"), + Table: "sys_model_info", + Columns: sysModelInfoColumns{ + ModelId: "model_id", + ModelCategoryId: "model_category_id", + ModelName: "model_name", + ModelTitle: "model_title", + ModelPk: "model_pk", + ModelOrder: "model_order", + ModelSort: "model_sort", + ModelList: "model_list", + ModelEdit: "model_edit", + ModelIndexes: "model_indexes", + SearchList: "search_list", + CreateTime: "create_time", + UpdateTime: "update_time", + ModelStatus: "model_status", + ModelEngine: "model_engine", + CreateBy: "create_by", + UpdateBy: "update_by", + }, + } +) diff --git a/app/system/dao/internal/sys_oper_log.go b/app/system/dao/internal/sys_oper_log.go new file mode 100644 index 0000000..62d6aa6 --- /dev/null +++ b/app/system/dao/internal/sys_oper_log.go @@ -0,0 +1,67 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysOperLogDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysOperLogDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + C sysOperLogColumns // C is the short type for Columns, which contains all the column names of Table for convenient usage. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the underlying table name of the DAO. +} + +// SysOperLogColumns defines and stores column names for table sys_oper_log. +type sysOperLogColumns struct { + OperId string // 日志主键 + Title string // 模块标题 + BusinessType string // 业务类型(0其它 1新增 2修改 3删除) + Method string // 方法名称 + RequestMethod string // 请求方式 + OperatorType string // 操作类别(0其它 1后台用户 2手机端用户) + OperName string // 操作人员 + DeptName string // 部门名称 + OperUrl string // 请求URL + OperIp string // 主机地址 + OperLocation string // 操作地点 + OperParam string // 请求参数 + JsonResult string // 返回参数 + Status string // 操作状态(0正常 1异常) + ErrorMsg string // 错误消息 + OperTime string // 操作时间 +} + +// NewSysOperLogDao creates and returns a new DAO object for table data access. +func NewSysOperLogDao() *SysOperLogDao { + columns := sysOperLogColumns{ + OperId: "oper_id", + Title: "title", + BusinessType: "business_type", + Method: "method", + RequestMethod: "request_method", + OperatorType: "operator_type", + OperName: "oper_name", + DeptName: "dept_name", + OperUrl: "oper_url", + OperIp: "oper_ip", + OperLocation: "oper_location", + OperParam: "oper_param", + JsonResult: "json_result", + Status: "status", + ErrorMsg: "error_msg", + OperTime: "oper_time", + } + return &SysOperLogDao{ + C: columns, + M: g.DB("default").Model("sys_oper_log").Safe(), + DB: g.DB("default"), + Table: "sys_oper_log", + } +} diff --git a/app/system/dao/internal/sys_post.go b/app/system/dao/internal/sys_post.go new file mode 100644 index 0000000..ef6045c --- /dev/null +++ b/app/system/dao/internal/sys_post.go @@ -0,0 +1,57 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysPostDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysPostDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + C sysPostColumns // C is the short type for Columns, which contains all the column names of Table for convenient usage. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the underlying table name of the DAO. +} + +// SysPostColumns defines and stores column names for table sys_post. +type sysPostColumns struct { + PostId string // 岗位ID + PostCode string // 岗位编码 + PostName string // 岗位名称 + PostSort string // 显示顺序 + Status string // 状态(0正常 1停用) + Remark string // 备注 + CreatedBy string // 创建人 + UpdatedBy string // 修改人 + CreatedAt string // 创建时间 + UpdatedAt string // 修改时间 + DeletedAt string // 删除时间 +} + +// NewSysPostDao creates and returns a new DAO object for table data access. +func NewSysPostDao() *SysPostDao { + columns := sysPostColumns{ + PostId: "post_id", + PostCode: "post_code", + PostName: "post_name", + PostSort: "post_sort", + Status: "status", + Remark: "remark", + CreatedBy: "created_by", + UpdatedBy: "updated_by", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + } + return &SysPostDao{ + C: columns, + M: g.DB("default").Model("sys_post").Safe(), + DB: g.DB("default"), + Table: "sys_post", + } +} diff --git a/app/system/dao/internal/sys_role.go b/app/system/dao/internal/sys_role.go new file mode 100644 index 0000000..5bb4f86 --- /dev/null +++ b/app/system/dao/internal/sys_role.go @@ -0,0 +1,393 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "context" + "database/sql" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" + "time" + + "gfast/app/system/model" +) + +// SysRoleDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysRoleDao struct { + gmvc.M + DB gdb.DB + Table string + Columns sysRoleColumns +} + +// SysRoleColumns defines and stores column names for table sys_role. +type sysRoleColumns struct { + Id string // + Status string // 状态;0:禁用;1:正常 + ListOrder string // 排序 + Name string // 角色名称 + Remark string // 备注 + DataScope string // 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) +} + +var ( + // SysRole is globally public accessible object for table sys_role operations. + SysRole = SysRoleDao{ + M: g.DB("default").Model("sys_role").Safe(), + DB: g.DB("default"), + Table: "sys_role", + Columns: sysRoleColumns{ + Id: "id", + Status: "status", + ListOrder: "list_order", + Name: "name", + Remark: "remark", + DataScope: "data_scope", + }, + } +) + +// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy +// of current DB object and with given context in it. +// Note that this returned DB object can be used only once, so do not assign it to +// a global or package variable for long using. +func (d *SysRoleDao) Ctx(ctx context.Context) *SysRoleDao { + return &SysRoleDao{M: d.M.Ctx(ctx)} +} + +// As sets an alias name for current table. +func (d *SysRoleDao) As(as string) *SysRoleDao { + return &SysRoleDao{M: d.M.As(as)} +} + +// TX sets the transaction for current operation. +func (d *SysRoleDao) TX(tx *gdb.TX) *SysRoleDao { + return &SysRoleDao{M: d.M.TX(tx)} +} + +// Master marks the following operation on master node. +func (d *SysRoleDao) Master() *SysRoleDao { + return &SysRoleDao{M: d.M.Master()} +} + +// Slave marks the following operation on slave node. +// Note that it makes sense only if there's any slave node configured. +func (d *SysRoleDao) Slave() *SysRoleDao { + return &SysRoleDao{M: d.M.Slave()} +} + +// Args sets custom arguments for model operation. +func (d *SysRoleDao) Args(args ...interface{}) *SysRoleDao { + return &SysRoleDao{M: d.M.Args(args...)} +} + +// LeftJoin does "LEFT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysRoleDao) LeftJoin(table ...string) *SysRoleDao { + return &SysRoleDao{M: d.M.LeftJoin(table...)} +} + +// RightJoin does "RIGHT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysRoleDao) RightJoin(table ...string) *SysRoleDao { + return &SysRoleDao{M: d.M.RightJoin(table...)} +} + +// InnerJoin does "INNER JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysRoleDao) InnerJoin(table ...string) *SysRoleDao { + return &SysRoleDao{M: d.M.InnerJoin(table...)} +} + +// Fields sets the operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysRoleDao) Fields(fieldNamesOrMapStruct ...interface{}) *SysRoleDao { + return &SysRoleDao{M: d.M.Fields(fieldNamesOrMapStruct...)} +} + +// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysRoleDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *SysRoleDao { + return &SysRoleDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)} +} + +// Option sets the extra operation option for the model. +func (d *SysRoleDao) Option(option int) *SysRoleDao { + return &SysRoleDao{M: d.M.Option(option)} +} + +// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers +// the data and where attributes for empty values. +func (d *SysRoleDao) OmitEmpty() *SysRoleDao { + return &SysRoleDao{M: d.M.OmitEmpty()} +} + +// Filter marks filtering the fields which does not exist in the fields of the operated table. +func (d *SysRoleDao) Filter() *SysRoleDao { + return &SysRoleDao{M: d.M.Filter()} +} + +// Where sets the condition statement for the model. The parameter can be type of +// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times, +// multiple conditions will be joined into where statement using "AND". +// Eg: +// Where("uid=10000") +// Where("uid", 10000) +// Where("money>? AND name like ?", 99999, "vip_%") +// Where("uid", 1).Where("name", "john") +// Where("status IN (?)", g.Slice{1,2,3}) +// Where("age IN(?,?)", 18, 50) +// Where(User{ Id : 1, UserName : "john"}) +func (d *SysRoleDao) Where(where interface{}, args ...interface{}) *SysRoleDao { + return &SysRoleDao{M: d.M.Where(where, args...)} +} + +// WherePri does the same logic as M.Where except that if the parameter +// is a single condition like int/string/float/slice, it treats the condition as the primary +// key value. That is, if primary key is "id" and given parameter as "123", the +// WherePri function treats the condition as "id=123", but M.Where treats the condition +// as string "123". +func (d *SysRoleDao) WherePri(where interface{}, args ...interface{}) *SysRoleDao { + return &SysRoleDao{M: d.M.WherePri(where, args...)} +} + +// And adds "AND" condition to the where statement. +func (d *SysRoleDao) And(where interface{}, args ...interface{}) *SysRoleDao { + return &SysRoleDao{M: d.M.And(where, args...)} +} + +// Or adds "OR" condition to the where statement. +func (d *SysRoleDao) Or(where interface{}, args ...interface{}) *SysRoleDao { + return &SysRoleDao{M: d.M.Or(where, args...)} +} + +// Group sets the "GROUP BY" statement for the model. +func (d *SysRoleDao) Group(groupBy string) *SysRoleDao { + return &SysRoleDao{M: d.M.Group(groupBy)} +} + +// Order sets the "ORDER BY" statement for the model. +func (d *SysRoleDao) Order(orderBy ...string) *SysRoleDao { + return &SysRoleDao{M: d.M.Order(orderBy...)} +} + +// Limit sets the "LIMIT" statement for the model. +// The parameter can be either one or two number, if passed two number is passed, +// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]" +// statement. +func (d *SysRoleDao) Limit(limit ...int) *SysRoleDao { + return &SysRoleDao{M: d.M.Limit(limit...)} +} + +// Offset sets the "OFFSET" statement for the model. +// It only makes sense for some databases like SQLServer, PostgreSQL, etc. +func (d *SysRoleDao) Offset(offset int) *SysRoleDao { + return &SysRoleDao{M: d.M.Offset(offset)} +} + +// Page sets the paging number for the model. +// The parameter is started from 1 for paging. +// Note that, it differs that the Limit function start from 0 for "LIMIT" statement. +func (d *SysRoleDao) Page(page, limit int) *SysRoleDao { + return &SysRoleDao{M: d.M.Page(page, limit)} +} + +// Batch sets the batch operation number for the model. +func (d *SysRoleDao) Batch(batch int) *SysRoleDao { + return &SysRoleDao{M: d.M.Batch(batch)} +} + +// Cache sets the cache feature for the model. It caches the result of the sql, which means +// if there's another same sql request, it just reads and returns the result from cache, it +// but not committed and executed into the database. +// +// If the parameter < 0, which means it clear the cache with given . +// If the parameter = 0, which means it never expires. +// If the parameter > 0, which means it expires after . +// +// The optional parameter is used to bind a name to the cache, which means you can later +// control the cache like changing the or clearing the cache with specified . +// +// Note that, the cache feature is disabled if the model is operating on a transaction. +func (d *SysRoleDao) Cache(duration time.Duration, name ...string) *SysRoleDao { + return &SysRoleDao{M: d.M.Cache(duration, name...)} +} + +// Data sets the operation data for the model. +// The parameter can be type of string/map/gmap/slice/struct/*struct, etc. +// Eg: +// Data("uid=10000") +// Data("uid", 10000) +// Data(g.Map{"uid": 10000, "name":"john"}) +// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) +func (d *SysRoleDao) Data(data ...interface{}) *SysRoleDao { + return &SysRoleDao{M: d.M.Data(data...)} +} + +// All does "SELECT FROM ..." statement for the model. +// It retrieves the records from table and returns the result as []*model.SysRole. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysRoleDao) All(where ...interface{}) ([]*model.SysRole, error) { + all, err := d.M.All(where...) + if err != nil { + return nil, err + } + var entities []*model.SysRole + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// One retrieves one record from table and returns the result as *model.SysRole. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysRoleDao) One(where ...interface{}) (*model.SysRole, error) { + one, err := d.M.One(where...) + if err != nil { + return nil, err + } + var entity *model.SysRole + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindOne retrieves and returns a single Record by M.WherePri and M.One. +// Also see M.WherePri and M.One. +func (d *SysRoleDao) FindOne(where ...interface{}) (*model.SysRole, error) { + one, err := d.M.FindOne(where...) + if err != nil { + return nil, err + } + var entity *model.SysRole + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindAll retrieves and returns Result by by M.WherePri and M.All. +// Also see M.WherePri and M.All. +func (d *SysRoleDao) FindAll(where ...interface{}) ([]*model.SysRole, error) { + all, err := d.M.FindAll(where...) + if err != nil { + return nil, err + } + var entities []*model.SysRole + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// Struct retrieves one record from table and converts it into given struct. +// The parameter should be type of *struct/**struct. If type **struct is given, +// it can create the struct internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Struct(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Struct(&user) +func (d *SysRoleDao) Struct(pointer interface{}, where ...interface{}) error { + return d.M.Struct(pointer, where...) +} + +// Structs retrieves records from table and converts them into given struct slice. +// The parameter should be type of *[]struct/*[]*struct. It can create and fill the struct +// slice internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not empty. +// +// Eg: +// users := ([]User)(nil) +// err := dao.User.Structs(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Structs(&users) +func (d *SysRoleDao) Structs(pointer interface{}, where ...interface{}) error { + return d.M.Structs(pointer, where...) +} + +// Scan automatically calls Struct or Structs function according to the type of parameter . +// It calls function Struct if is type of *struct/**struct. +// It calls function Structs if is type of *[]struct/*[]*struct. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Scan(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Scan(&user) +// +// users := ([]User)(nil) +// err := dao.User.Scan(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Scan(&users) +func (d *SysRoleDao) Scan(pointer interface{}, where ...interface{}) error { + return d.M.Scan(pointer, where...) +} + +// Chunk iterates the table with given size and callback function. +func (d *SysRoleDao) Chunk(limit int, callback func(entities []*model.SysRole, err error) bool) { + d.M.Chunk(limit, func(result gdb.Result, err error) bool { + var entities []*model.SysRole + err = result.Structs(&entities) + if err == sql.ErrNoRows { + return false + } + return callback(entities, err) + }) +} + +// LockUpdate sets the lock for update for current operation. +func (d *SysRoleDao) LockUpdate() *SysRoleDao { + return &SysRoleDao{M: d.M.LockUpdate()} +} + +// LockShared sets the lock in share mode for current operation. +func (d *SysRoleDao) LockShared() *SysRoleDao { + return &SysRoleDao{M: d.M.LockShared()} +} + +// Unscoped enables/disables the soft deleting feature. +func (d *SysRoleDao) Unscoped() *SysRoleDao { + return &SysRoleDao{M: d.M.Unscoped()} +} diff --git a/app/system/dao/internal/sys_role_dept.go b/app/system/dao/internal/sys_role_dept.go new file mode 100644 index 0000000..32928fd --- /dev/null +++ b/app/system/dao/internal/sys_role_dept.go @@ -0,0 +1,39 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysRoleDeptDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysRoleDeptDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the table name of the DAO. + Columns sysRoleDeptColumns // Columns contains all the columns of Table that for convenient usage. +} + +// SysRoleDeptColumns defines and stores column names for table sys_role_dept. +type sysRoleDeptColumns struct { + RoleId string // 角色ID + DeptId string // 部门ID +} + +var ( + // SysRoleDept is globally public accessible object for table sys_role_dept operations. + SysRoleDept = SysRoleDeptDao{ + M: g.DB("default").Model("sys_role_dept").Safe(), + DB: g.DB("default"), + Table: "sys_role_dept", + Columns: sysRoleDeptColumns{ + RoleId: "role_id", + DeptId: "dept_id", + }, + } +) diff --git a/app/system/dao/internal/sys_user.go b/app/system/dao/internal/sys_user.go new file mode 100644 index 0000000..4e77f7d --- /dev/null +++ b/app/system/dao/internal/sys_user.go @@ -0,0 +1,424 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "context" + "database/sql" + "gfast/app/system/model" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" + "time" +) + +// SysUserDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysUserDao struct { + gmvc.M + DB gdb.DB + Table string + Columns sysUserColumns +} + +// SysUserColumns defines and stores column names for table sys_user. +type sysUserColumns struct { + Id string // + UserName string // 用户名 + Mobile string // 中国手机不带国家代码,国际手机号格式为:国家代码-手机号 + UserNickname string // 用户昵称 + Birthday string // 生日 + UserPassword string // 登录密码;cmf_password加密 + UserSalt string // 加密盐 + UserStatus string // 用户状态;0:禁用,1:正常,2:未验证 + UserEmail string // 用户登录邮箱 + Sex string // 性别;0:保密,1:男,2:女 + Avatar string // 用户头像 + DeptId string // 部门id + Remark string // 备注 + IsAdmin string // 是否后台管理员 1 是 0 否 + Address string // 联系地址 + Describe string // 描述信息 + PhoneNum string // 联系电话 + LastLoginIp string // 最后登录ip + LastLoginTime string // 最后登录时间 + CreatedAt string // 创建时间 + UpdatedAt string // 更新时间 + DeletedAt string // 删除时间 +} + +var ( + // SysUser is globally public accessible object for table sys_user operations. + SysUser = SysUserDao{ + M: g.DB("default").Model("sys_user").Safe(), + DB: g.DB("default"), + Table: "sys_user", + Columns: sysUserColumns{ + Id: "id", + UserName: "user_name", + Mobile: "mobile", + UserNickname: "user_nickname", + Birthday: "birthday", + UserPassword: "user_password", + UserSalt: "user_salt", + UserStatus: "user_status", + UserEmail: "user_email", + Sex: "sex", + Avatar: "avatar", + DeptId: "dept_id", + Remark: "remark", + IsAdmin: "is_admin", + Address: "address", + Describe: "describe", + PhoneNum: "phone_num", + LastLoginIp: "last_login_ip", + LastLoginTime: "last_login_time", + CreatedAt: "created_at", + UpdatedAt: "updated_at", + DeletedAt: "deleted_at", + }, + } +) + +// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy +// of current DB object and with given context in it. +// Note that this returned DB object can be used only once, so do not assign it to +// a global or package variable for long using. +func (d *SysUserDao) Ctx(ctx context.Context) *SysUserDao { + return &SysUserDao{M: d.M.Ctx(ctx)} +} + +// As sets an alias name for current table. +func (d *SysUserDao) As(as string) *SysUserDao { + return &SysUserDao{M: d.M.As(as)} +} + +// TX sets the transaction for current operation. +func (d *SysUserDao) TX(tx *gdb.TX) *SysUserDao { + return &SysUserDao{M: d.M.TX(tx)} +} + +// Master marks the following operation on master node. +func (d *SysUserDao) Master() *SysUserDao { + return &SysUserDao{M: d.M.Master()} +} + +// Slave marks the following operation on slave node. +// Note that it makes sense only if there's any slave node configured. +func (d *SysUserDao) Slave() *SysUserDao { + return &SysUserDao{M: d.M.Slave()} +} + +// Args sets custom arguments for model operation. +func (d *SysUserDao) Args(args ...interface{}) *SysUserDao { + return &SysUserDao{M: d.M.Args(args...)} +} + +// LeftJoin does "LEFT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysUserDao) LeftJoin(table ...string) *SysUserDao { + return &SysUserDao{M: d.M.LeftJoin(table...)} +} + +// RightJoin does "RIGHT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysUserDao) RightJoin(table ...string) *SysUserDao { + return &SysUserDao{M: d.M.RightJoin(table...)} +} + +// InnerJoin does "INNER JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysUserDao) InnerJoin(table ...string) *SysUserDao { + return &SysUserDao{M: d.M.InnerJoin(table...)} +} + +// Fields sets the operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysUserDao) Fields(fieldNamesOrMapStruct ...interface{}) *SysUserDao { + return &SysUserDao{M: d.M.Fields(fieldNamesOrMapStruct...)} +} + +// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysUserDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *SysUserDao { + return &SysUserDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)} +} + +// Option sets the extra operation option for the model. +func (d *SysUserDao) Option(option int) *SysUserDao { + return &SysUserDao{M: d.M.Option(option)} +} + +// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers +// the data and where attributes for empty values. +func (d *SysUserDao) OmitEmpty() *SysUserDao { + return &SysUserDao{M: d.M.OmitEmpty()} +} + +// Filter marks filtering the fields which does not exist in the fields of the operated table. +func (d *SysUserDao) Filter() *SysUserDao { + return &SysUserDao{M: d.M.Filter()} +} + +// Where sets the condition statement for the model. The parameter can be type of +// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times, +// multiple conditions will be joined into where statement using "AND". +// Eg: +// Where("uid=10000") +// Where("uid", 10000) +// Where("money>? AND name like ?", 99999, "vip_%") +// Where("uid", 1).Where("name", "john") +// Where("status IN (?)", g.Slice{1,2,3}) +// Where("age IN(?,?)", 18, 50) +// Where(User{ Id : 1, UserName : "john"}) +func (d *SysUserDao) Where(where interface{}, args ...interface{}) *SysUserDao { + return &SysUserDao{M: d.M.Where(where, args...)} +} + +// WherePri does the same logic as M.Where except that if the parameter +// is a single condition like int/string/float/slice, it treats the condition as the primary +// key value. That is, if primary key is "id" and given parameter as "123", the +// WherePri function treats the condition as "id=123", but M.Where treats the condition +// as string "123". +func (d *SysUserDao) WherePri(where interface{}, args ...interface{}) *SysUserDao { + return &SysUserDao{M: d.M.WherePri(where, args...)} +} + +// And adds "AND" condition to the where statement. +func (d *SysUserDao) And(where interface{}, args ...interface{}) *SysUserDao { + return &SysUserDao{M: d.M.And(where, args...)} +} + +// Or adds "OR" condition to the where statement. +func (d *SysUserDao) Or(where interface{}, args ...interface{}) *SysUserDao { + return &SysUserDao{M: d.M.Or(where, args...)} +} + +// Group sets the "GROUP BY" statement for the model. +func (d *SysUserDao) Group(groupBy string) *SysUserDao { + return &SysUserDao{M: d.M.Group(groupBy)} +} + +// Order sets the "ORDER BY" statement for the model. +func (d *SysUserDao) Order(orderBy ...string) *SysUserDao { + return &SysUserDao{M: d.M.Order(orderBy...)} +} + +// Limit sets the "LIMIT" statement for the model. +// The parameter can be either one or two number, if passed two number is passed, +// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]" +// statement. +func (d *SysUserDao) Limit(limit ...int) *SysUserDao { + return &SysUserDao{M: d.M.Limit(limit...)} +} + +// Offset sets the "OFFSET" statement for the model. +// It only makes sense for some databases like SQLServer, PostgreSQL, etc. +func (d *SysUserDao) Offset(offset int) *SysUserDao { + return &SysUserDao{M: d.M.Offset(offset)} +} + +// Page sets the paging number for the model. +// The parameter is started from 1 for paging. +// Note that, it differs that the Limit function start from 0 for "LIMIT" statement. +func (d *SysUserDao) Page(page, limit int) *SysUserDao { + return &SysUserDao{M: d.M.Page(page, limit)} +} + +// Batch sets the batch operation number for the model. +func (d *SysUserDao) Batch(batch int) *SysUserDao { + return &SysUserDao{M: d.M.Batch(batch)} +} + +// Cache sets the cache feature for the model. It caches the result of the sql, which means +// if there's another same sql request, it just reads and returns the result from cache, it +// but not committed and executed into the database. +// +// If the parameter < 0, which means it clear the cache with given . +// If the parameter = 0, which means it never expires. +// If the parameter > 0, which means it expires after . +// +// The optional parameter is used to bind a name to the cache, which means you can later +// control the cache like changing the or clearing the cache with specified . +// +// Note that, the cache feature is disabled if the model is operating on a transaction. +func (d *SysUserDao) Cache(duration time.Duration, name ...string) *SysUserDao { + return &SysUserDao{M: d.M.Cache(duration, name...)} +} + +// Data sets the operation data for the model. +// The parameter can be type of string/map/gmap/slice/struct/*struct, etc. +// Eg: +// Data("uid=10000") +// Data("uid", 10000) +// Data(g.Map{"uid": 10000, "name":"john"}) +// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) +func (d *SysUserDao) Data(data ...interface{}) *SysUserDao { + return &SysUserDao{M: d.M.Data(data...)} +} + +// All does "SELECT FROM ..." statement for the model. +// It retrieves the records from table and returns the result as []*model.SysUser. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysUserDao) All(where ...interface{}) ([]*model.SysUser, error) { + all, err := d.M.All(where...) + if err != nil { + return nil, err + } + var entities []*model.SysUser + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// One retrieves one record from table and returns the result as *model.SysUser. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysUserDao) One(where ...interface{}) (*model.SysUser, error) { + one, err := d.M.One(where...) + if err != nil { + return nil, err + } + var entity *model.SysUser + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindOne retrieves and returns a single Record by M.WherePri and M.One. +// Also see M.WherePri and M.One. +func (d *SysUserDao) FindOne(where ...interface{}) (*model.SysUser, error) { + one, err := d.M.FindOne(where...) + if err != nil { + return nil, err + } + var entity *model.SysUser + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindAll retrieves and returns Result by by M.WherePri and M.All. +// Also see M.WherePri and M.All. +func (d *SysUserDao) FindAll(where ...interface{}) ([]*model.SysUser, error) { + all, err := d.M.FindAll(where...) + if err != nil { + return nil, err + } + var entities []*model.SysUser + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// Struct retrieves one record from table and converts it into given struct. +// The parameter should be type of *struct/**struct. If type **struct is given, +// it can create the struct internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Struct(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Struct(&user) +func (d *SysUserDao) Struct(pointer interface{}, where ...interface{}) error { + return d.M.Struct(pointer, where...) +} + +// Structs retrieves records from table and converts them into given struct slice. +// The parameter should be type of *[]struct/*[]*struct. It can create and fill the struct +// slice internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not empty. +// +// Eg: +// users := ([]User)(nil) +// err := dao.User.Structs(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Structs(&users) +func (d *SysUserDao) Structs(pointer interface{}, where ...interface{}) error { + return d.M.Structs(pointer, where...) +} + +// Scan automatically calls Struct or Structs function according to the type of parameter . +// It calls function Struct if is type of *struct/**struct. +// It calls function Structs if is type of *[]struct/*[]*struct. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Scan(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Scan(&user) +// +// users := ([]User)(nil) +// err := dao.User.Scan(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Scan(&users) +func (d *SysUserDao) Scan(pointer interface{}, where ...interface{}) error { + return d.M.Scan(pointer, where...) +} + +// Chunk iterates the table with given size and callback function. +func (d *SysUserDao) Chunk(limit int, callback func(entities []*model.SysUser, err error) bool) { + d.M.Chunk(limit, func(result gdb.Result, err error) bool { + var entities []*model.SysUser + err = result.Structs(&entities) + if err == sql.ErrNoRows { + return false + } + return callback(entities, err) + }) +} + +// LockUpdate sets the lock for update for current operation. +func (d *SysUserDao) LockUpdate() *SysUserDao { + return &SysUserDao{M: d.M.LockUpdate()} +} + +// LockShared sets the lock in share mode for current operation. +func (d *SysUserDao) LockShared() *SysUserDao { + return &SysUserDao{M: d.M.LockShared()} +} + +// Unscoped enables/disables the soft deleting feature. +func (d *SysUserDao) Unscoped() *SysUserDao { + return &SysUserDao{M: d.M.Unscoped()} +} diff --git a/app/system/dao/internal/sys_user_online.go b/app/system/dao/internal/sys_user_online.go new file mode 100644 index 0000000..a2641f3 --- /dev/null +++ b/app/system/dao/internal/sys_user_online.go @@ -0,0 +1,397 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "context" + "database/sql" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" + "time" + + "gfast/app/system/model" +) + +// SysUserOnlineDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysUserOnlineDao struct { + gmvc.M + DB gdb.DB + Table string + Columns sysUserOnlineColumns +} + +// SysUserOnlineColumns defines and stores column names for table sys_user_online. +type sysUserOnlineColumns struct { + Id string // + Uuid string // 用户标识 + Token string // 用户token + CreateTime string // 登录时间 + UserName string // 用户名 + Ip string // 登录ip + Explorer string // 浏览器 + Os string // 操作系统 +} + +var ( + // SysUserOnline is globally public accessible object for table sys_user_online operations. + SysUserOnline = SysUserOnlineDao{ + M: g.DB("default").Model("sys_user_online").Safe(), + DB: g.DB("default"), + Table: "sys_user_online", + Columns: sysUserOnlineColumns{ + Id: "id", + Uuid: "uuid", + Token: "token", + CreateTime: "create_time", + UserName: "user_name", + Ip: "ip", + Explorer: "explorer", + Os: "os", + }, + } +) + +// Ctx is a chaining function, which creates and returns a new DB that is a shallow copy +// of current DB object and with given context in it. +// Note that this returned DB object can be used only once, so do not assign it to +// a global or package variable for long using. +func (d *SysUserOnlineDao) Ctx(ctx context.Context) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Ctx(ctx)} +} + +// As sets an alias name for current table. +func (d *SysUserOnlineDao) As(as string) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.As(as)} +} + +// TX sets the transaction for current operation. +func (d *SysUserOnlineDao) TX(tx *gdb.TX) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.TX(tx)} +} + +// Master marks the following operation on master node. +func (d *SysUserOnlineDao) Master() *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Master()} +} + +// Slave marks the following operation on slave node. +// Note that it makes sense only if there's any slave node configured. +func (d *SysUserOnlineDao) Slave() *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Slave()} +} + +// Args sets custom arguments for model operation. +func (d *SysUserOnlineDao) Args(args ...interface{}) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Args(args...)} +} + +// LeftJoin does "LEFT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").LeftJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").LeftJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysUserOnlineDao) LeftJoin(table ...string) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.LeftJoin(table...)} +} + +// RightJoin does "RIGHT JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").RightJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").RightJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysUserOnlineDao) RightJoin(table ...string) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.RightJoin(table...)} +} + +// InnerJoin does "INNER JOIN ... ON ..." statement on the model. +// The parameter
can be joined table and its joined condition, +// and also with its alias name, like: +// Table("user").InnerJoin("user_detail", "user_detail.uid=user.uid") +// Table("user", "u").InnerJoin("user_detail", "ud", "ud.uid=u.uid") +func (d *SysUserOnlineDao) InnerJoin(table ...string) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.InnerJoin(table...)} +} + +// Fields sets the operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysUserOnlineDao) Fields(fieldNamesOrMapStruct ...interface{}) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Fields(fieldNamesOrMapStruct...)} +} + +// FieldsEx sets the excluded operation fields of the model, multiple fields joined using char ','. +// The parameter can be type of string/map/*map/struct/*struct. +func (d *SysUserOnlineDao) FieldsEx(fieldNamesOrMapStruct ...interface{}) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.FieldsEx(fieldNamesOrMapStruct...)} +} + +// Option sets the extra operation option for the model. +func (d *SysUserOnlineDao) Option(option int) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Option(option)} +} + +// OmitEmpty sets OPTION_OMITEMPTY option for the model, which automatically filers +// the data and where attributes for empty values. +func (d *SysUserOnlineDao) OmitEmpty() *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.OmitEmpty()} +} + +// Filter marks filtering the fields which does not exist in the fields of the operated table. +func (d *SysUserOnlineDao) Filter() *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Filter()} +} + +// Where sets the condition statement for the model. The parameter can be type of +// string/map/gmap/slice/struct/*struct, etc. Note that, if it's called more than one times, +// multiple conditions will be joined into where statement using "AND". +// Eg: +// Where("uid=10000") +// Where("uid", 10000) +// Where("money>? AND name like ?", 99999, "vip_%") +// Where("uid", 1).Where("name", "john") +// Where("status IN (?)", g.Slice{1,2,3}) +// Where("age IN(?,?)", 18, 50) +// Where(User{ Id : 1, UserName : "john"}) +func (d *SysUserOnlineDao) Where(where interface{}, args ...interface{}) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Where(where, args...)} +} + +// WherePri does the same logic as M.Where except that if the parameter +// is a single condition like int/string/float/slice, it treats the condition as the primary +// key value. That is, if primary key is "id" and given parameter as "123", the +// WherePri function treats the condition as "id=123", but M.Where treats the condition +// as string "123". +func (d *SysUserOnlineDao) WherePri(where interface{}, args ...interface{}) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.WherePri(where, args...)} +} + +// And adds "AND" condition to the where statement. +func (d *SysUserOnlineDao) And(where interface{}, args ...interface{}) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.And(where, args...)} +} + +// Or adds "OR" condition to the where statement. +func (d *SysUserOnlineDao) Or(where interface{}, args ...interface{}) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Or(where, args...)} +} + +// Group sets the "GROUP BY" statement for the model. +func (d *SysUserOnlineDao) Group(groupBy string) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Group(groupBy)} +} + +// Order sets the "ORDER BY" statement for the model. +func (d *SysUserOnlineDao) Order(orderBy ...string) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Order(orderBy...)} +} + +// Limit sets the "LIMIT" statement for the model. +// The parameter can be either one or two number, if passed two number is passed, +// it then sets "LIMIT limit[0],limit[1]" statement for the model, or else it sets "LIMIT limit[0]" +// statement. +func (d *SysUserOnlineDao) Limit(limit ...int) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Limit(limit...)} +} + +// Offset sets the "OFFSET" statement for the model. +// It only makes sense for some databases like SQLServer, PostgreSQL, etc. +func (d *SysUserOnlineDao) Offset(offset int) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Offset(offset)} +} + +// Page sets the paging number for the model. +// The parameter is started from 1 for paging. +// Note that, it differs that the Limit function start from 0 for "LIMIT" statement. +func (d *SysUserOnlineDao) Page(page, limit int) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Page(page, limit)} +} + +// Batch sets the batch operation number for the model. +func (d *SysUserOnlineDao) Batch(batch int) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Batch(batch)} +} + +// Cache sets the cache feature for the model. It caches the result of the sql, which means +// if there's another same sql request, it just reads and returns the result from cache, it +// but not committed and executed into the database. +// +// If the parameter < 0, which means it clear the cache with given . +// If the parameter = 0, which means it never expires. +// If the parameter > 0, which means it expires after . +// +// The optional parameter is used to bind a name to the cache, which means you can later +// control the cache like changing the or clearing the cache with specified . +// +// Note that, the cache feature is disabled if the model is operating on a transaction. +func (d *SysUserOnlineDao) Cache(duration time.Duration, name ...string) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Cache(duration, name...)} +} + +// Data sets the operation data for the model. +// The parameter can be type of string/map/gmap/slice/struct/*struct, etc. +// Eg: +// Data("uid=10000") +// Data("uid", 10000) +// Data(g.Map{"uid": 10000, "name":"john"}) +// Data(g.Slice{g.Map{"uid": 10000, "name":"john"}, g.Map{"uid": 20000, "name":"smith"}) +func (d *SysUserOnlineDao) Data(data ...interface{}) *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Data(data...)} +} + +// All does "SELECT FROM ..." statement for the model. +// It retrieves the records from table and returns the result as []*model.SysUserOnline. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysUserOnlineDao) All(where ...interface{}) ([]*model.SysUserOnline, error) { + all, err := d.M.All(where...) + if err != nil { + return nil, err + } + var entities []*model.SysUserOnline + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// One retrieves one record from table and returns the result as *model.SysUserOnline. +// It returns nil if there's no record retrieved with the given conditions from table. +// +// The optional parameter is the same as the parameter of M.Where function, +// see M.Where. +func (d *SysUserOnlineDao) One(where ...interface{}) (*model.SysUserOnline, error) { + one, err := d.M.One(where...) + if err != nil { + return nil, err + } + var entity *model.SysUserOnline + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindOne retrieves and returns a single Record by M.WherePri and M.One. +// Also see M.WherePri and M.One. +func (d *SysUserOnlineDao) FindOne(where ...interface{}) (*model.SysUserOnline, error) { + one, err := d.M.FindOne(where...) + if err != nil { + return nil, err + } + var entity *model.SysUserOnline + if err = one.Struct(&entity); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entity, nil +} + +// FindAll retrieves and returns Result by by M.WherePri and M.All. +// Also see M.WherePri and M.All. +func (d *SysUserOnlineDao) FindAll(where ...interface{}) ([]*model.SysUserOnline, error) { + all, err := d.M.FindAll(where...) + if err != nil { + return nil, err + } + var entities []*model.SysUserOnline + if err = all.Structs(&entities); err != nil && err != sql.ErrNoRows { + return nil, err + } + return entities, nil +} + +// Struct retrieves one record from table and converts it into given struct. +// The parameter should be type of *struct/**struct. If type **struct is given, +// it can create the struct internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Struct(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Struct(&user) +func (d *SysUserOnlineDao) Struct(pointer interface{}, where ...interface{}) error { + return d.M.Struct(pointer, where...) +} + +// Structs retrieves records from table and converts them into given struct slice. +// The parameter should be type of *[]struct/*[]*struct. It can create and fill the struct +// slice internally during converting. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved with the given conditions +// from table and is not empty. +// +// Eg: +// users := ([]User)(nil) +// err := dao.User.Structs(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Structs(&users) +func (d *SysUserOnlineDao) Structs(pointer interface{}, where ...interface{}) error { + return d.M.Structs(pointer, where...) +} + +// Scan automatically calls Struct or Structs function according to the type of parameter . +// It calls function Struct if is type of *struct/**struct. +// It calls function Structs if is type of *[]struct/*[]*struct. +// +// The optional parameter is the same as the parameter of Model.Where function, +// see Model.Where. +// +// Note that it returns sql.ErrNoRows if there's no record retrieved and given pointer is not empty or nil. +// +// Eg: +// user := new(User) +// err := dao.User.Where("id", 1).Scan(user) +// +// user := (*User)(nil) +// err := dao.User.Where("id", 1).Scan(&user) +// +// users := ([]User)(nil) +// err := dao.User.Scan(&users) +// +// users := ([]*User)(nil) +// err := dao.User.Scan(&users) +func (d *SysUserOnlineDao) Scan(pointer interface{}, where ...interface{}) error { + return d.M.Scan(pointer, where...) +} + +// Chunk iterates the table with given size and callback function. +func (d *SysUserOnlineDao) Chunk(limit int, callback func(entities []*model.SysUserOnline, err error) bool) { + d.M.Chunk(limit, func(result gdb.Result, err error) bool { + var entities []*model.SysUserOnline + err = result.Structs(&entities) + if err == sql.ErrNoRows { + return false + } + return callback(entities, err) + }) +} + +// LockUpdate sets the lock for update for current operation. +func (d *SysUserOnlineDao) LockUpdate() *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.LockUpdate()} +} + +// LockShared sets the lock in share mode for current operation. +func (d *SysUserOnlineDao) LockShared() *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.LockShared()} +} + +// Unscoped enables/disables the soft deleting feature. +func (d *SysUserOnlineDao) Unscoped() *SysUserOnlineDao { + return &SysUserOnlineDao{M: d.M.Unscoped()} +} diff --git a/app/system/dao/internal/sys_user_post.go b/app/system/dao/internal/sys_user_post.go new file mode 100644 index 0000000..ced930d --- /dev/null +++ b/app/system/dao/internal/sys_user_post.go @@ -0,0 +1,39 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysUserPostDao is the manager for logic model data accessing +// and custom defined data operations functions management. +type SysUserPostDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the table name of the DAO. + Columns sysUserPostColumns // Columns contains all the columns of Table that for convenient usage. +} + +// SysUserPostColumns defines and stores column names for table sys_user_post. +type sysUserPostColumns struct { + UserId string // 用户ID + PostId string // 岗位ID +} + +var ( + // SysUserPost is globally public accessible object for table sys_user_post operations. + SysUserPost = SysUserPostDao{ + M: g.DB("default").Model("sys_user_post").Safe(), + DB: g.DB("default"), + Table: "sys_user_post", + Columns: sysUserPostColumns{ + UserId: "user_id", + PostId: "post_id", + }, + } +) diff --git a/app/system/dao/internal/sys_web_set.go b/app/system/dao/internal/sys_web_set.go new file mode 100644 index 0000000..82f05ed --- /dev/null +++ b/app/system/dao/internal/sys_web_set.go @@ -0,0 +1,39 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// SysWebSetDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysWebSetDao struct { + gmvc.M // M is the core and embedded struct that inherits all chaining operations from gdb.Model. + C sysWebSetColumns // C is the short type for Columns, which contains all the column names of Table for convenient usage. + DB gdb.DB // DB is the raw underlying database management object. + Table string // Table is the underlying table name of the DAO. +} + +// SysWebSetColumns defines and stores column names for table sys_web_set. +type sysWebSetColumns struct { + WebId string // 主键 + WebContent string // 站点信息 +} + +// NewSysWebSetDao creates and returns a new DAO object for table data access. +func NewSysWebSetDao() *SysWebSetDao { + columns := sysWebSetColumns{ + WebId: "web_id", + WebContent: "web_content", + } + return &SysWebSetDao{ + C: columns, + M: g.DB("default").Model("sys_web_set").Safe(), + DB: g.DB("default"), + Table: "sys_web_set", + } +} diff --git a/app/system/dao/sys_auth_rule.go b/app/system/dao/sys_auth_rule.go new file mode 100644 index 0000000..e5711a9 --- /dev/null +++ b/app/system/dao/sys_auth_rule.go @@ -0,0 +1,70 @@ +// ============================================================================ +// This is auto-generated by gf cli tool only once. Fill this file as you wish. +// ============================================================================ + +package dao + +import ( + "gfast/app/system/dao/internal" + "gfast/app/system/model" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/frame/gmvc" +) + +// sysAuthRuleDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysAuthRuleDao struct { + internal.SysAuthRuleDao +} + +var ( + // SysAuthRule is globally public accessible object for table sys_auth_rule operations. + SysAuthRule = sysAuthRuleDao{ + internal.SysAuthRule, + } +) + +func (d *sysAuthRuleDao) Scope(f func(m gmvc.M) gmvc.M) *sysAuthRuleDao { + nd := *d + if m := f(d.M); m != nil { + nd.M = m + } + return &nd +} + +// Fill with you ideas below. +func (d *sysAuthRuleDao) GetMenuList() (list []*model.SysAuthRuleInfoRes, err error) { + + err = d.Fields(model.SysAuthRuleInfoRes{}).Order("weigh desc,id asc").Scan(&list) + return +} + +func (d *sysAuthRuleDao) CheckMenuNameUnique(name string, id int) bool { + + m := d.Where("name=?", name) + if id != 0 { + m = m.And("id!=?", id) + } + c, err := m.Count() + if err != nil { + g.Log().Error(err) + return false + } + return c == 0 +} + +//检查菜单路由地址是否已经存在 +func (d *sysAuthRuleDao) CheckMenuPathUnique(path string, id int) bool { + + model := d.Where("path=?", path).Where("menu_type<>?", 2) + if id != 0 { + model = model.And("id!=?", id) + } + c, err := model.Count() + if err != nil { + g.Log().Error(err) + return false + } + return c == 0 +} diff --git a/app/system/dao/sys_dept.go b/app/system/dao/sys_dept.go new file mode 100644 index 0000000..7381a56 --- /dev/null +++ b/app/system/dao/sys_dept.go @@ -0,0 +1,58 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "gfast/app/system/dao/internal" + "gfast/app/system/model" +) + +// sysDeptDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysDeptDao struct { + *internal.SysDeptDao +} + +var ( + // SysDept is globally public accessible object for table sys_dept operations. + SysDept sysDeptDao +) + +func init() { + SysDept = sysDeptDao{ + internal.NewSysDeptDao(), + } +} + +// Fill with you ideas below. + +type SysDeptSearchParams struct { + ExcludeId int64 `p:"excludeId"` + DeptName string `p:"deptName"` + Status string `p:"status"` +} + +type SysDeptTreeRes struct { + *model.SysDept + Children []*SysDeptTreeRes `json:"children"` +} + +type SysDeptAddParams struct { + ParentID int `json:"parentId" orm:"parent_id" p:"parentId" v:"required#父级不能为空"` + DeptName string `json:"deptName" orm:"dept_name" p:"deptName" v:"required#部门名称不能为空"` + OrderNum int `json:"orderNum" orm:"order_num" p:"orderNum" v:"required#排序不能为空"` + Leader string `json:"leader" orm:"leader" p:"leader" v:"required#负责人不能为空"` + Phone string `json:"phone" orm:"Phone" p:"phone" v:"required#电话不能为空"` + Email string `json:"email" orm:"email" p:"email" v:"required#邮箱不能为空"` + Status string `json:"status" orm:"status" p:"status" v:"required#状态必须"` + Ancestors string `json:"ancestors" p:"ancestors" orm:"ancestors"` + CreatedBy uint64 `json:"CreatedBy" orm:"created_by"` +} + +type EditParams struct { + DeptID int64 `json:"deptId" orm:"dept_id" p:"id" v:"integer|min:1#ID只能为整数|ID只能为正数"` + SysDeptAddParams + UpdatedBy uint64 `json:"updatedBy" orm:"updated_by"` +} diff --git a/app/system/dao/sys_dict_data.go b/app/system/dao/sys_dict_data.go new file mode 100644 index 0000000..02e911f --- /dev/null +++ b/app/system/dao/sys_dict_data.go @@ -0,0 +1,25 @@ +// ============================================================================ +// This is auto-generated by gf cli tool only once. Fill this file as you wish. +// ============================================================================ + +package dao + +import ( + "gfast/app/system/dao/internal" +) + +// sysDictDataDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysDictDataDao struct { + internal.SysDictDataDao +} + +var ( + // SysDictData is globally public accessible object for table sys_dict_data operations. + SysDictData = sysDictDataDao{ + internal.SysDictData, + } +) + +// Fill with you ideas below. diff --git a/app/system/dao/sys_dict_type.go b/app/system/dao/sys_dict_type.go new file mode 100644 index 0000000..fe6bc5a --- /dev/null +++ b/app/system/dao/sys_dict_type.go @@ -0,0 +1,23 @@ +// ============================================================================ +// This is auto-generated by gf cli tool only once. Fill this file as you wish. +// ============================================================================ + +package dao + +import ( + "gfast/app/system/dao/internal" +) + +// sysDictTypeDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysDictTypeDao struct { + internal.SysDictTypeDao +} + +var ( + // SysDictType is globally public accessible object for table sys_dict_type operations. + SysDictType = sysDictTypeDao{ + internal.SysDictType, + } +) diff --git a/app/system/dao/sys_job.go b/app/system/dao/sys_job.go new file mode 100644 index 0000000..3124fc7 --- /dev/null +++ b/app/system/dao/sys_job.go @@ -0,0 +1,58 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/dao/internal" +) + +// sysJobDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysJobDao struct { + *internal.SysJobDao +} + +var ( + // SysJob is globally public accessible object for table sys_job operations. + SysJob sysJobDao +) + +func init() { + SysJob = sysJobDao{ + internal.NewSysJobDao(), + } +} + +// Fill with you ideas below. + +// SysJobSearchReq 分页请求参数 +type SysJobSearchReq struct { + JobName string `p:"jobName"` //任务名称 + JobGroup string `p:"jobGroup"` //任务组名 + Status string `p:"status"` //状态(0正常 1暂停) + comModel.PageReq +} + +// SysJobAddReq 添加操作请求参数 +type SysJobAddReq struct { + JobName string `p:"jobName" v:"required#任务名称不能为空"` + JobParams string `p:"jobParams"` // 任务参数 + JobGroup string `p:"jobGroup" ` + InvokeTarget string `p:"invokeTarget" v:"required#执行方法不能为空"` + CronExpression string `p:"cronExpression" v:"required#任务表达式不能为空"` + MisfirePolicy int `p:"misfirePolicy"` + Concurrent int `p:"concurrent" ` + Status int `p:"status" v:"required#状态(0正常 1暂停)不能为空"` + Remark string `p:"remark" ` + CreateBy uint64 +} + +// SysJobEditReq 修改操作请求参数 +type SysJobEditReq struct { + JobId int64 `p:"job_id" v:"min:1#任务id不能为空"` + SysJobAddReq + UpdateBy uint64 +} diff --git a/app/system/dao/sys_login_log.go b/app/system/dao/sys_login_log.go new file mode 100644 index 0000000..5cfdb8e --- /dev/null +++ b/app/system/dao/sys_login_log.go @@ -0,0 +1,35 @@ +// ============================================================================ +// This is auto-generated by gf cli tool only once. Fill this file as you wish. +// ============================================================================ + +package dao + +import ( + "gfast/app/system/dao/internal" + "gfast/app/system/model" + "github.com/gogf/gf/frame/g" +) + +// sysLoginLogDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysLoginLogDao struct { + internal.SysLoginLogDao +} + +var ( + // SysLoginLog is globally public accessible object for table sys_login_log operations. + SysLoginLog = sysLoginLogDao{ + internal.SysLoginLog, + } +) + +// Fill with you ideas below. + +// SaveLog 保存日志信息 +func (d sysLoginLogDao) SaveLog(data *model.SysLoginLog) { + _, err := d.Insert(data) + if err != nil { + g.Log().Error(err) + } +} diff --git a/app/system/dao/sys_model_info.go b/app/system/dao/sys_model_info.go new file mode 100644 index 0000000..1443ccd --- /dev/null +++ b/app/system/dao/sys_model_info.go @@ -0,0 +1,39 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "fmt" + "gfast/app/system/dao/internal" + "gfast/app/system/model" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" +) + +// sysModelInfoDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysModelInfoDao struct { + internal.SysModelInfoDao +} + +var ( + // SysModelInfo is globally public accessible object for table sys_model_info operations. + SysModelInfo = sysModelInfoDao{ + internal.SysModelInfo, + } +) + +// Fill with you ideas below. +func (i *sysModelInfoDao) GetModelsByCateIds(cateIds []int) (models []*model.SysModelInfo, err error) { + err = i.Fields(fmt.Sprintf("%s,%s,%s", i.Columns.ModelId, i.Columns.ModelName, i.Columns.ModelTitle)). + Where(i.Columns.ModelCategoryId+" in(?)", cateIds). + Order(i.Columns.ModelId + " ASC ").Scan(&models) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取模型信息失败") + } + return +} diff --git a/app/system/dao/sys_oper_log.go b/app/system/dao/sys_oper_log.go new file mode 100644 index 0000000..1b52a2b --- /dev/null +++ b/app/system/dao/sys_oper_log.go @@ -0,0 +1,54 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/dao/internal" + "gfast/app/system/model" + "github.com/gogf/gf/frame/g" + "net/url" +) + +// sysOperLogDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysOperLogDao struct { + *internal.SysOperLogDao +} + +var ( + // SysOperLog is globally public accessible object for table sys_oper_log operations. + SysOperLog sysOperLogDao +) + +func init() { + SysOperLog = sysOperLogDao{ + internal.NewSysOperLogDao(), + } +} + +// Fill with you ideas below. + +// SysOperLogAdd 添加操作日志参数 +type SysOperLogAdd struct { + User *CtxUser + Menu *model.SysAuthRuleInfoRes + Url *url.URL + Params g.Map + Method string + ClientIp string + OperatorType int +} + +// SysOperLogSearchReq 查询列表请求参数 +type SysOperLogSearchReq struct { + Title string `p:"title"` //系统模块 + OperName string `p:"operName"` //操作人员 + Status string `p:"status"` //操作状态 + SortName string `p:"orderByColumn"` //排序字段 + SortOrder string `p:"isAsc"` //排序方式 + RequestMethod string `p:"requestMethod"` //操作类型 + comModel.PageReq +} diff --git a/app/system/dao/sys_post.go b/app/system/dao/sys_post.go new file mode 100644 index 0000000..48d1a63 --- /dev/null +++ b/app/system/dao/sys_post.go @@ -0,0 +1,54 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/dao/internal" +) + +// sysPostDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysPostDao struct { + *internal.SysPostDao +} + +var ( + // SysPost is globally public accessible object for table sys_post operations. + SysPost sysPostDao +) + +func init() { + SysPost = sysPostDao{ + internal.NewSysPostDao(), + } +} + +// Fill with you ideas below. + +// SysPostSearchParams 搜索参数 +type SysPostSearchParams struct { + PostCode string `p:"postCode"` //岗位编码 + PostName string `p:"postName"` //岗位名称 + Status string `p:"status"` //状态 + comModel.PageReq +} + +// SysPostAddParams 添加岗位参数 +type SysPostAddParams struct { + PostCode string `p:"postCode" v:"required#岗位编码不能为空"` + PostName string `p:"postName" v:"required#岗位名称不能为空"` + PostSort int `p:"postSort" v:"required#岗位排序不能为空"` + Status string `p:"status" v:"required#状态不能为空"` + Remark string `p:"remark"` + CreatedBy uint64 +} + +// SysPostEditParams 修改岗位参数 +type SysPostEditParams struct { + PostId int64 `p:"postId" v:"required#id必须"` + SysPostAddParams + UpdatedBy uint64 +} diff --git a/app/system/dao/sys_role.go b/app/system/dao/sys_role.go new file mode 100644 index 0000000..a45142a --- /dev/null +++ b/app/system/dao/sys_role.go @@ -0,0 +1,25 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "gfast/app/system/dao/internal" +) + +// sysRoleDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysRoleDao struct { + internal.SysRoleDao +} + +var ( + // SysRole is globally public accessible object for table sys_role operations. + SysRole = sysRoleDao{ + internal.SysRole, + } +) + +// Fill with you ideas below. diff --git a/app/system/dao/sys_role_dept.go b/app/system/dao/sys_role_dept.go new file mode 100644 index 0000000..f7a9a1c --- /dev/null +++ b/app/system/dao/sys_role_dept.go @@ -0,0 +1,25 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "gfast/app/system/dao/internal" +) + +// sysRoleDeptDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysRoleDeptDao struct { + internal.SysRoleDeptDao +} + +var ( + // SysRoleDept is globally public accessible object for table sys_role_dept operations. + SysRoleDept = sysRoleDeptDao{ + internal.SysRoleDept, + } +) + +// Fill with you ideas below. diff --git a/app/system/dao/sys_user.go b/app/system/dao/sys_user.go new file mode 100644 index 0000000..bd67a50 --- /dev/null +++ b/app/system/dao/sys_user.go @@ -0,0 +1,52 @@ +// ============================================================================ +// This is auto-generated by gf cli tool only once. Fill this file as you wish. +// ============================================================================ + +package dao + +import ( + "context" + "gfast/app/system/dao/internal" + "gfast/app/system/model" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/gtime" +) + +// sysUserDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysUserDao struct { + internal.SysUserDao +} + +var ( + // SysUser is globally public accessible object for table sys_user operations. + SysUser = sysUserDao{ + internal.SysUser, + } +) + +// Fill with you ideas below. + +//通过用户名获取用户信息 +func (d *sysUserDao) FindByUsername(ctx context.Context, username string) (user *model.LoginUserRes, err error) { + user = &model.LoginUserRes{} + err = d.Ctx(ctx).Fields(user).Where(d.Columns.UserName, username).Scan(user) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取用户信息失败") + } + return +} + +//更新用户登陆信息 +func (d *sysUserDao) UpLoginInfo(id uint64, ip string) { + _, err := d.WherePri(id).Unscoped().Update(g.Map{ + d.Columns.LastLoginIp: ip, + d.Columns.LastLoginTime: gtime.Now(), + }) + if err != nil { + g.Log().Error(err) + } +} diff --git a/app/system/dao/sys_user_online.go b/app/system/dao/sys_user_online.go new file mode 100644 index 0000000..00e77fa --- /dev/null +++ b/app/system/dao/sys_user_online.go @@ -0,0 +1,49 @@ +// ============================================================================ +// This is auto-generated by gf cli tool only once. Fill this file as you wish. +// ============================================================================ + +package dao + +import ( + "gfast/app/system/dao/internal" + "gfast/app/system/model" + "github.com/gogf/gf/frame/g" +) + +// sysUserOnlineDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysUserOnlineDao struct { + internal.SysUserOnlineDao +} + +var ( + // SysUserOnline is globally public accessible object for table sys_user_online operations. + SysUserOnline = sysUserOnlineDao{ + internal.SysUserOnline, + } +) + +// Fill with you ideas below. + +// SaveOnline 保存登录用户在线状态 +func (d sysUserOnlineDao) SaveOnline(params *model.SysUserOnline) { + //查询是否已存在当前用户 + info, err := d.Fields(d.Columns.Id).FindOne(d.Columns.Token, params.Token) + if err != nil { + g.Log().Error(err) + return + } + //若已存在则更新 + if info != nil { + _, err := SysUserOnline.Where(SysUserOnline.Columns.Id, info.Id).FieldsEx(SysUserOnline.Columns.Id).Update(params) + if err != nil { + g.Log().Error(err) + } + } else { //否则新增 + _, err := SysUserOnline.FieldsEx(SysUserOnline.Columns.Id).Insert(params) + if err != nil { + g.Log().Error(err) + } + } +} diff --git a/app/system/dao/sys_user_post.go b/app/system/dao/sys_user_post.go new file mode 100644 index 0000000..6006c56 --- /dev/null +++ b/app/system/dao/sys_user_post.go @@ -0,0 +1,25 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "gfast/app/system/dao/internal" +) + +// sysUserPostDao is the manager for logic model data accessing +// and custom defined data operations functions management. You can define +// methods on it to extend its functionality as you wish. +type sysUserPostDao struct { + internal.SysUserPostDao +} + +var ( + // SysUserPost is globally public accessible object for table sys_user_post operations. + SysUserPost = sysUserPostDao{ + internal.SysUserPost, + } +) + +// Fill with you ideas below. diff --git a/app/system/dao/sys_web_set.go b/app/system/dao/sys_web_set.go new file mode 100644 index 0000000..900724f --- /dev/null +++ b/app/system/dao/sys_web_set.go @@ -0,0 +1,28 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package dao + +import ( + "gfast/app/system/dao/internal" +) + +// sysWebSetDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysWebSetDao struct { + *internal.SysWebSetDao +} + +var ( + // SysWebSet is globally public accessible object for table sys_web_set operations. + SysWebSet sysWebSetDao +) + +func init() { + SysWebSet = sysWebSetDao{ + internal.NewSysWebSetDao(), + } +} + +// Fill with you ideas below. diff --git a/app/system/model/.gitkeep b/app/system/model/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/system/model/internal/sys_auth_rule.go b/app/system/model/internal/sys_auth_rule.go new file mode 100644 index 0000000..893e13e --- /dev/null +++ b/app/system/model/internal/sys_auth_rule.go @@ -0,0 +1,33 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysAuthRule is the golang structure for table sys_auth_rule. +type SysAuthRule struct { + Id uint `orm:"id,primary" json:"id"` // + Pid uint `orm:"pid" json:"pid"` // 父ID + Name string `orm:"name,unique" json:"name"` // 规则名称 + Title string `orm:"title" json:"title"` // 规则名称 + Icon string `orm:"icon" json:"icon"` // 图标 + Condition string `orm:"condition" json:"condition"` // 条件 + Remark string `orm:"remark" json:"remark"` // 备注 + MenuType uint `orm:"menu_type" json:"menuType"` // 类型 0目录 1菜单 2按钮 + Weigh int `orm:"weigh" json:"weigh"` // 权重 + Status uint `orm:"status" json:"status"` // 状态 + AlwaysShow uint `orm:"always_show" json:"alwaysShow"` // 显示状态 + Path string `orm:"path" json:"path"` // 路由地址 + JumpPath string `orm:"jump_path" json:"jumpPath"` // 跳转路由 + Component string `orm:"component" json:"component"` // 组件路径 + IsFrame uint `orm:"is_frame" json:"isFrame"` // 是否外链 1是 0否 + ModuleType string `orm:"module_type" json:"moduleType"` // 所属模块 + ModelId uint `orm:"model_id" json:"modelId"` // 模型ID + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建日期 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 修改日期 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除日期 +} diff --git a/app/system/model/internal/sys_dict_data.go b/app/system/model/internal/sys_dict_data.go new file mode 100644 index 0000000..9de05ee --- /dev/null +++ b/app/system/model/internal/sys_dict_data.go @@ -0,0 +1,28 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysDictData is the golang structure for table sys_dict_data. +type SysDictData struct { + DictCode int64 `orm:"dict_code,primary" json:"dictCode"` // 字典编码 + DictSort int `orm:"dict_sort" json:"dictSort"` // 字典排序 + DictLabel string `orm:"dict_label" json:"dictLabel"` // 字典标签 + DictValue string `orm:"dict_value" json:"dictValue"` // 字典键值 + DictType string `orm:"dict_type" json:"dictType"` // 字典类型 + CssClass string `orm:"css_class" json:"cssClass"` // 样式属性(其他样式扩展) + ListClass string `orm:"list_class" json:"listClass"` // 表格回显样式 + IsDefault int `orm:"is_default" json:"isDefault"` // 是否默认(1是 0否) + Status int `orm:"status" json:"status"` // 状态(0正常 1停用) + CreateBy uint64 `orm:"create_by" json:"createBy"` // 创建者 + UpdateBy uint64 `orm:"update_by" json:"updateBy"` // 更新者 + Remark string `orm:"remark" json:"remark"` // 备注 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 修改时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除时间 +} diff --git a/app/system/model/internal/sys_dict_type.go b/app/system/model/internal/sys_dict_type.go new file mode 100644 index 0000000..f789d96 --- /dev/null +++ b/app/system/model/internal/sys_dict_type.go @@ -0,0 +1,23 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysDictType is the golang structure for table sys_dict_type. +type SysDictType struct { + DictId uint64 `orm:"dict_id,primary" json:"dictId"` // 字典主键 + DictName string `orm:"dict_name" json:"dictName"` // 字典名称 + DictType string `orm:"dict_type,unique" json:"dictType"` // 字典类型 + Status uint `orm:"status" json:"status"` // 状态(0正常 1停用) + CreateBy uint `orm:"create_by" json:"createBy"` // 创建者 + UpdateBy uint `orm:"update_by" json:"updateBy"` // 更新者 + Remark string `orm:"remark" json:"remark"` // 备注 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建日期 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 修改日期 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除日期 +} diff --git a/app/system/model/internal/sys_login_log.go b/app/system/model/internal/sys_login_log.go new file mode 100644 index 0000000..aea00b1 --- /dev/null +++ b/app/system/model/internal/sys_login_log.go @@ -0,0 +1,23 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysLoginLog is the golang structure for table sys_login_log. +type SysLoginLog struct { + InfoId int64 `orm:"info_id,primary" json:"infoId"` // 访问ID + LoginName string `orm:"login_name" json:"loginName"` // 登录账号 + Ipaddr string `orm:"ipaddr" json:"ipaddr"` // 登录IP地址 + LoginLocation string `orm:"login_location" json:"loginLocation"` // 登录地点 + Browser string `orm:"browser" json:"browser"` // 浏览器类型 + Os string `orm:"os" json:"os"` // 操作系统 + Status int `orm:"status" json:"status"` // 登录状态(0成功 1失败) + Msg string `orm:"msg" json:"msg"` // 提示消息 + LoginTime *gtime.Time `orm:"login_time" json:"loginTime"` // 登录时间 + Module string `orm:"module" json:"module"` // 登录模块 +} diff --git a/app/system/model/internal/sys_model_info.go b/app/system/model/internal/sys_model_info.go new file mode 100644 index 0000000..9b6e995 --- /dev/null +++ b/app/system/model/internal/sys_model_info.go @@ -0,0 +1,26 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +// SysModelInfo is the golang structure for table sys_model_info. +type SysModelInfo struct { + ModelId uint `orm:"model_id,primary" json:"modelId"` // 模型ID + ModelCategoryId uint `orm:"model_category_id" json:"modelCategoryId"` // 模板分类id + ModelName string `orm:"model_name,unique" json:"modelName"` // 模型标识 + ModelTitle string `orm:"model_title" json:"modelTitle"` // 模型名称 + ModelPk string `orm:"model_pk" json:"modelPk"` // 主键字段 + ModelOrder string `orm:"model_order" json:"modelOrder"` // 默认排序字段 + ModelSort string `orm:"model_sort" json:"modelSort"` // 表单字段排序 + ModelList string `orm:"model_list" json:"modelList"` // 列表显示字段,为空显示全部 + ModelEdit string `orm:"model_edit" json:"modelEdit"` // 可编辑字段,为空则除主键外均可以编辑 + ModelIndexes string `orm:"model_indexes" json:"modelIndexes"` // 索引字段 + SearchList string `orm:"search_list" json:"searchList"` // 高级搜索的字段 + CreateTime uint64 `orm:"create_time" json:"createTime"` // 创建时间 + UpdateTime uint64 `orm:"update_time" json:"updateTime"` // 更新时间 + ModelStatus uint `orm:"model_status" json:"modelStatus"` // 状态 + ModelEngine string `orm:"model_engine" json:"modelEngine"` // 数据库引擎 + CreateBy uint64 `orm:"create_by" json:"createBy"` // 创建人 + UpdateBy uint64 `orm:"update_by" json:"updateBy"` // 修改人 +} diff --git a/app/system/model/internal/sys_role.go b/app/system/model/internal/sys_role.go new file mode 100644 index 0000000..11572b4 --- /dev/null +++ b/app/system/model/internal/sys_role.go @@ -0,0 +1,15 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +// SysRole is the golang structure for table sys_role. +type SysRole struct { + Id uint `orm:"id,primary" json:"id"` // + Status uint `orm:"status" json:"status"` // 状态;0:禁用;1:正常 + ListOrder float64 `orm:"list_order" json:"listOrder"` // 排序 + Name string `orm:"name" json:"name"` // 角色名称 + Remark string `orm:"remark" json:"remark"` // 备注 + DataScope uint `orm:"data_scope" json:"dataScope"` // 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) +} diff --git a/app/system/model/internal/sys_role_dept.go b/app/system/model/internal/sys_role_dept.go new file mode 100644 index 0000000..e9de358 --- /dev/null +++ b/app/system/model/internal/sys_role_dept.go @@ -0,0 +1,11 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +// SysRoleDept is the golang structure for table sys_role_dept. +type SysRoleDept struct { + RoleId int64 `orm:"role_id,primary" json:"roleId"` // 角色ID + DeptId int64 `orm:"dept_id,primary" json:"deptId"` // 部门ID +} diff --git a/app/system/model/internal/sys_user.go b/app/system/model/internal/sys_user.go new file mode 100644 index 0000000..d71e3f2 --- /dev/null +++ b/app/system/model/internal/sys_user.go @@ -0,0 +1,35 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysUser is the golang structure for table sys_user. +type SysUser struct { + Id uint64 `orm:"id,primary" json:"id"` // + UserName string `orm:"user_name,unique" json:"userName"` // 用户名 + Mobile string `orm:"mobile,unique" json:"mobile"` // 中国手机不带国家代码,国际手机号格式为:国家代码-手机号 + UserNickname string `orm:"user_nickname" json:"userNickname"` // 用户昵称 + Birthday int `orm:"birthday" json:"birthday"` // 生日 + UserPassword string `orm:"user_password" json:"userPassword"` // 登录密码;cmf_password加密 + UserSalt string `orm:"user_salt" json:"userSalt"` // 加密盐 + UserStatus uint `orm:"user_status" json:"userStatus"` // 用户状态;0:禁用,1:正常,2:未验证 + UserEmail string `orm:"user_email" json:"userEmail"` // 用户登录邮箱 + Sex int `orm:"sex" json:"sex"` // 性别;0:保密,1:男,2:女 + Avatar string `orm:"avatar" json:"avatar"` // 用户头像 + DeptId uint64 `orm:"dept_id" json:"deptId"` // 部门id + Remark string `orm:"remark" json:"remark"` // 备注 + IsAdmin int `orm:"is_admin" json:"isAdmin"` // 是否后台管理员 1 是 0 否 + Address string `orm:"address" json:"address"` // 联系地址 + Describe string `orm:"describe" json:"describe"` // 描述信息 + PhoneNum string `orm:"phone_num" json:"phoneNum"` // 联系电话 + LastLoginIp string `orm:"last_login_ip" json:"lastLoginIp"` // 最后登录ip + LastLoginTime *gtime.Time `orm:"last_login_time" json:"lastLoginTime"` // 最后登录时间 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 更新时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除时间 +} diff --git a/app/system/model/internal/sys_user_online.go b/app/system/model/internal/sys_user_online.go new file mode 100644 index 0000000..11672ef --- /dev/null +++ b/app/system/model/internal/sys_user_online.go @@ -0,0 +1,21 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. DO NOT EDIT THIS FILE MANUALLY. +// ========================================================================== + +package internal + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysUserOnline is the golang structure for table sys_user_online. +type SysUserOnline struct { + Id uint64 `orm:"id,primary" json:"id"` // + Uuid string `orm:"uuid" json:"uuid"` // 用户标识 + Token string `orm:"token,unique" json:"token"` // 用户token + CreateTime *gtime.Time `orm:"create_time" json:"createTime"` // 登录时间 + UserName string `orm:"user_name" json:"userName"` // 用户名 + Ip string `orm:"ip" json:"ip"` // 登录ip + Explorer string `orm:"explorer" json:"explorer"` // 浏览器 + Os string `orm:"os" json:"os"` // 操作系统 +} diff --git a/app/system/model/internal/sys_user_post.go b/app/system/model/internal/sys_user_post.go new file mode 100644 index 0000000..1d8bc95 --- /dev/null +++ b/app/system/model/internal/sys_user_post.go @@ -0,0 +1,11 @@ +// ========================================================================== +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ========================================================================== + +package internal + +// SysUserPost is the golang structure for table sys_user_post. +type SysUserPost struct { + UserId int64 `orm:"user_id,primary" json:"userId"` // 用户ID + PostId int64 `orm:"post_id,primary" json:"postId"` // 岗位ID +} diff --git a/app/system/model/sys_auth_rule.go b/app/system/model/sys_auth_rule.go new file mode 100644 index 0000000..53d4572 --- /dev/null +++ b/app/system/model/sys_auth_rule.go @@ -0,0 +1,67 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. Fill this file as you wish. +// ========================================================================== + +package model + +import ( + "gfast/app/system/model/internal" +) + +// SysAuthRule is the golang structure for table sys_auth_rule. +type SysAuthRule internal.SysAuthRule + +// Fill with you ideas below. +type SysAuthRuleInfoRes struct { + Id uint `orm:"id,primary" json:"id"` // + Pid uint `orm:"pid" json:"pid"` // 父ID + Name string `orm:"name,unique" json:"name"` // 规则名称 + Title string `orm:"title" json:"title"` // 规则名称 + Icon string `orm:"icon" json:"icon"` // 图标 + Condition string `orm:"condition" json:"condition"` // 条件 + Remark string `orm:"remark" json:"remark"` // 备注 + MenuType uint `orm:"menu_type" json:"menuType"` // 类型 0目录 1菜单 2按钮 + Weigh int `orm:"weigh" json:"weigh"` // 权重 + Status uint `orm:"status" json:"status"` // 状态 + AlwaysShow uint `orm:"always_show" json:"alwaysShow"` // 显示状态 + Path string `orm:"path" json:"path"` // 路由地址 + JumpPath string `orm:"jump_path" json:"jumpPath"` // 跳转路由 + Component string `orm:"component" json:"component"` // 组件路径 + IsFrame uint `orm:"is_frame" json:"isFrame"` // 是否外链 1是 0否 + ModuleType string `orm:"module_type" json:"moduleType"` // 所属模块 + ModelId uint `orm:"model_id" json:"modelId"` // 模型ID +} + +type SysAuthRuleReqSearch struct { + Status string `p:"status" ` + Title string `p:"menuName" ` +} + +// SysAuthRuleTreeRes 菜单树形结构 +type SysAuthRuleTreeRes struct { + *SysAuthRuleInfoRes + Children []*SysAuthRuleTreeRes `json:"children"` +} + +func (req *SysAuthRuleReqSearch) IsEmpty() bool { + return req.Status == "" && req.Title == "" +} + +//菜单对象 +type MenuReq struct { + MenuType uint `orm:"menu_type" p:"menuType" v:"min:0|max:2#菜单类型最小值为:min|菜单类型最大值为:max"` + Pid uint `orm:"pid" p:"parentId" v:"min:0"` + Name string `orm:"name,unique" p:"name" v:"required#请填写规则名称"` + Title string `orm:"title" p:"menuName" v:"required|length:1,100#请填写标题|标题长度在:min到:max位"` + Icon string `orm:"icon" p:"icon"` + Weigh int `orm:"weigh" p:"orderNum" ` + Condition string `orm:"condition" p:"condition" ` + Remark string `orm:"remark" p:"remark" ` + Status uint `orm:"status" p:"status" ` + AlwaysShow uint `orm:"always_show" p:"visible"` + Path string `orm:"path" p:"path"` + Component string `orm:"component" p:"component" v:"required-if:menuType,1#组件路径不能为空"` + IsFrame uint `orm:"is_frame" p:"is_frame"` + ModuleType string `orm:"module_type" p:"moduleType"` + ModelId uint `orm:"model_id" p:"modelId"` +} diff --git a/app/system/model/sys_dept.go b/app/system/model/sys_dept.go new file mode 100644 index 0000000..9aa9f02 --- /dev/null +++ b/app/system/model/sys_dept.go @@ -0,0 +1,27 @@ +// ================================================================================= +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package model + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysDept is the golang structure for table sys_dept. +type SysDept struct { + DeptId int64 `orm:"dept_id,primary" json:"deptId"` // 部门id + ParentId int64 `orm:"parent_id" json:"parentId"` // 父部门id + Ancestors string `orm:"ancestors" json:"ancestors"` // 祖级列表 + DeptName string `orm:"dept_name" json:"deptName"` // 部门名称 + OrderNum int `orm:"order_num" json:"orderNum"` // 显示顺序 + Leader string `orm:"leader" json:"leader"` // 负责人 + Phone string `orm:"phone" json:"phone"` // 联系电话 + Email string `orm:"email" json:"email"` // 邮箱 + Status string `orm:"status" json:"status"` // 部门状态(0正常 1停用) + CreatedBy uint64 `orm:"created_by" json:"createdBy"` // 创建人 + UpdatedBy int64 `orm:"updated_by" json:"updatedBy"` // 修改人 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 修改时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除时间 +} diff --git a/app/system/model/sys_dict_data.go b/app/system/model/sys_dict_data.go new file mode 100644 index 0000000..1c3dd8a --- /dev/null +++ b/app/system/model/sys_dict_data.go @@ -0,0 +1,71 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. Fill this file as you wish. +// ========================================================================== + +package model + +import ( + "context" + comModel "gfast/app/common/model" + "gfast/app/system/model/internal" +) + +// SysDictData is the golang structure for table sys_dict_data. +type SysDictData internal.SysDictData + +// Fill with you ideas below. + +// SelectDictPageReq 分页请求参数 +type SelectDictPageReq struct { + DictType string `p:"dictType"` //字典类型 + DictLabel string `p:"dictLabel"` //字典标签 + Status string `p:"status"` //状态 + comModel.PageReq +} + +// GetDictReq 获取字典信息请求参数 +type GetDictReq struct { + DictType string `p:"dictType" v:"required#字典类型不能为空"` + DefaultValue string `p:"defaultValue"` + Ctx context.Context +} + +// DictRes 完整的一个字典信息 +type DictRes struct { + Info *DictTypeRes `json:"info"` + Values []*DictDataRes `json:"values"` +} + +type DictTypeRes struct { + DictName string `json:"name"` + Remark string `json:"remark"` +} + +// DictDataRes 字典数据 +type DictDataRes struct { + DictValue string `json:"key"` + DictLabel string `json:"value"` + IsDefault int `json:"isDefault"` + Remark string `json:"remark"` +} + +// DictDataAddReq 新增操作请求参数 +type DictDataAddReq struct { + DictLabel string `p:"dictLabel" v:"required#字典标签不能为空"` + DictValue string `p:"dictValue" v:"required#字典键值不能为空"` + DictType string `p:"dictType" v:"required#字典类型不能为空"` + DictSort int `p:"dictSort" v:"integer#排序只能为整数"` + CssClass string `p:"cssClass"` + ListClass string `p:"listClass"` + IsDefault int `p:"isDefault" v:"required|in:0,1#系统默认不能为空|默认值只能为0或1"` + Status int `p:"status" v:"required|in:0,1#状态不能为空|状态只能为0或1"` + Remark string `p:"remark"` + CreateBy uint64 +} + +// EditDictDataReq 修改字典数据操作请求参数 +type EditDictDataReq struct { + DictCode int `p:"dictCode" v:"required|min:1#主键ID不能为空|主键ID不能小于1"` + UpdateBy uint64 + DictDataAddReq +} diff --git a/app/system/model/sys_dict_type.go b/app/system/model/sys_dict_type.go new file mode 100644 index 0000000..a291b60 --- /dev/null +++ b/app/system/model/sys_dict_type.go @@ -0,0 +1,47 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. Fill this file as you wish. +// ========================================================================== + +package model + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/model/internal" + "github.com/gogf/gf/os/gtime" +) + +// SysDictType is the golang structure for table sys_dict_type. +type SysDictType internal.SysDictType + +// Fill with you ideas below. + +type ListSysDictTypeReq struct { + DictName string `p:"dictName"` //字典名称 + DictType string `p:"dictType"` //字典类型 + Status string `p:"status"` //字典状态 + comModel.PageReq +} + +// SysDictTypeAddReq 新增操作请求参数 +type SysDictTypeAddReq struct { + DictName string `p:"dictName" v:"required#字典名称不能为空"` + DictType string `p:"dictType" v:"required#字典类型不能为空"` + Status uint `p:"status" v:"required|in:0,1#状态不能为空|状态只能为0或1"` + Remark string `p:"remark"` + CreateBy uint64 +} + +type SysDictTypeEditReq struct { + SysDictTypeAddReq + DictId int64 `p:dictId v:required|min:1#主键ID不能为空|主键ID必须为大于0的值` + UpdateBy uint64 +} + +type SysDictTypeInfoRes struct { + DictId uint64 `orm:"dict_id,primary" json:"dictId"` // 字典主键 + DictName string `orm:"dict_name" json:"dictName"` // 字典名称 + DictType string `orm:"dict_type,unique" json:"dictType"` // 字典类型 + Status uint `orm:"status" json:"status"` // 状态(0正常 1停用) + Remark string `orm:"remark" json:"remark"` // 备注 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建日期 +} diff --git a/app/system/model/sys_job.go b/app/system/model/sys_job.go new file mode 100644 index 0000000..3080401 --- /dev/null +++ b/app/system/model/sys_job.go @@ -0,0 +1,28 @@ +// ================================================================================= +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package model + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysJob is the golang structure for table sys_job. +type SysJob struct { + JobId int64 `orm:"job_id,primary" json:"jobId"` // 任务ID + JobName string `orm:"job_name,primary" json:"jobName"` // 任务名称 + JobParams string `orm:"job_params" json:"jobParams"` // 参数 + JobGroup string `orm:"job_group,primary" json:"jobGroup"` // 任务组名 + InvokeTarget string `orm:"invoke_target" json:"invokeTarget"` // 调用目标字符串 + CronExpression string `orm:"cron_expression" json:"cronExpression"` // cron执行表达式 + MisfirePolicy int `orm:"misfire_policy" json:"misfirePolicy"` // 计划执行策略(1多次执行 2执行一次) + Concurrent int `orm:"concurrent" json:"concurrent"` // 是否并发执行(0允许 1禁止) + Status int `orm:"status" json:"status"` // 状态(0正常 1暂停) + CreateBy uint64 `orm:"create_by" json:"createBy"` // 创建者 + UpdateBy uint64 `orm:"update_by" json:"updateBy"` // 更新者 + Remark string `orm:"remark" json:"remark"` // 备注信息 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 更新时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除时间 +} diff --git a/app/system/model/sys_login_log.go b/app/system/model/sys_login_log.go new file mode 100644 index 0000000..f3d617f --- /dev/null +++ b/app/system/model/sys_login_log.go @@ -0,0 +1,36 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. Fill this file as you wish. +// ========================================================================== + +package model + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/model/internal" +) + +// SysLoginLog is the golang structure for table sys_login_log. +type SysLoginLog internal.SysLoginLog + +// Fill with you ideas below. + +// LoginLogParams 登录日志写入参数 +type LoginLogParams struct { + Status int + Username string + Ip string + UserAgent string + Msg string + Module string +} + +// SysLoginLogSearchReq 查询列表请求参数 +type SysLoginLogSearchReq struct { + LoginName string `p:"userName"` //登陆名 + Status string `p:"status"` //状态 + Ipaddr string `p:"ipaddr"` //登录地址 + SortName string `p:"orderByColumn"` //排序字段 + SortOrder string `p:"isAsc"` //排序方式 + LoginLocation string `p:"loginLocation"` //登录地点 + comModel.PageReq +} diff --git a/app/system/model/sys_model_info.go b/app/system/model/sys_model_info.go new file mode 100644 index 0000000..b498242 --- /dev/null +++ b/app/system/model/sys_model_info.go @@ -0,0 +1,14 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package model + +import ( + "gfast/app/system/model/internal" +) + +// SysModelInfo is the golang structure for table sys_model_info. +type SysModelInfo internal.SysModelInfo + +// Fill with you ideas below. diff --git a/app/system/model/sys_oper_log.go b/app/system/model/sys_oper_log.go new file mode 100644 index 0000000..acbae08 --- /dev/null +++ b/app/system/model/sys_oper_log.go @@ -0,0 +1,29 @@ +// ================================================================================= +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package model + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysOperLog is the golang structure for table sys_oper_log. +type SysOperLog struct { + OperId uint64 `orm:"oper_id,primary" json:"operId"` // 日志主键 + Title string `orm:"title" json:"title"` // 模块标题 + BusinessType int `orm:"business_type" json:"businessType"` // 业务类型(0其它 1新增 2修改 3删除) + Method string `orm:"method" json:"method"` // 方法名称 + RequestMethod string `orm:"request_method" json:"requestMethod"` // 请求方式 + OperatorType int `orm:"operator_type" json:"operatorType"` // 操作类别(0其它 1后台用户 2手机端用户) + OperName string `orm:"oper_name" json:"operName"` // 操作人员 + DeptName string `orm:"dept_name" json:"deptName"` // 部门名称 + OperUrl string `orm:"oper_url" json:"operUrl"` // 请求URL + OperIp string `orm:"oper_ip" json:"operIp"` // 主机地址 + OperLocation string `orm:"oper_location" json:"operLocation"` // 操作地点 + OperParam string `orm:"oper_param" json:"operParam"` // 请求参数 + JsonResult string `orm:"json_result" json:"jsonResult"` // 返回参数 + Status int `orm:"status" json:"status"` // 操作状态(0正常 1异常) + ErrorMsg string `orm:"error_msg" json:"errorMsg"` // 错误消息 + OperTime *gtime.Time `orm:"oper_time" json:"operTime"` // 操作时间 +} diff --git a/app/system/model/sys_post.go b/app/system/model/sys_post.go new file mode 100644 index 0000000..659e490 --- /dev/null +++ b/app/system/model/sys_post.go @@ -0,0 +1,24 @@ +// ================================================================================= +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package model + +import ( + "github.com/gogf/gf/os/gtime" +) + +// SysPost is the golang structure for table sys_post. +type SysPost struct { + PostId int64 `orm:"post_id,primary" json:"postId"` // 岗位ID + PostCode string `orm:"post_code" json:"postCode"` // 岗位编码 + PostName string `orm:"post_name" json:"postName"` // 岗位名称 + PostSort int `orm:"post_sort" json:"postSort"` // 显示顺序 + Status string `orm:"status" json:"status"` // 状态(0正常 1停用) + Remark string `orm:"remark" json:"remark"` // 备注 + CreatedBy uint64 `orm:"created_by" json:"createdBy"` // 创建人 + UpdatedBy uint64 `orm:"updated_by" json:"updatedBy"` // 修改人 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 修改时间 + DeletedAt *gtime.Time `orm:"deleted_at" json:"deletedAt"` // 删除时间 +} diff --git a/app/system/model/sys_role.go b/app/system/model/sys_role.go new file mode 100644 index 0000000..a848cea --- /dev/null +++ b/app/system/model/sys_role.go @@ -0,0 +1,34 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package model + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/model/internal" +) + +// SysRole is the golang structure for table sys_role. +type SysRole internal.SysRole + +// Fill with you ideas below. +//分页请求参数 +type SelectPageReq struct { + RoleName string `p:"roleName"` //参数名称 + Status string `p:"status"` //状态 + comModel.PageReq +} + +//修改状态参数 +type StatusSetReq struct { + RoleId uint `p:"roleId" v:"required#角色ID不能为空"` + Status uint `p:"status" v:"required#状态不能为空"` +} + +//角色数据授权参数 +type DataScopeReq struct { + RoleId uint `p:"roleId" v:"required#角色ID不能为空"` + DataScope uint `p:"dataScope" v:"required#权限范围不能为空"` + DeptIds []uint `p:"deptIds"` +} diff --git a/app/system/model/sys_role_dept.go b/app/system/model/sys_role_dept.go new file mode 100644 index 0000000..2190bce --- /dev/null +++ b/app/system/model/sys_role_dept.go @@ -0,0 +1,14 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package model + +import ( + "gfast/app/system/model/internal" +) + +// SysRoleDept is the golang structure for table sys_role_dept. +type SysRoleDept internal.SysRoleDept + +// Fill with you ideas below. diff --git a/app/system/model/sys_user.go b/app/system/model/sys_user.go new file mode 100644 index 0000000..f97eb55 --- /dev/null +++ b/app/system/model/sys_user.go @@ -0,0 +1,114 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. Fill this file as you wish. +// ========================================================================== + +package model + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/model/internal" +) + +// SysUser is the golang structure for table sys_user. +type SysUser internal.SysUser + +// Fill with you ideas below. + +// LoginParamsReq 登陆参数 +type LoginParamsReq struct { + Username string `p:"username" v:"required#用户名不能为空"` + Password string `p:"password" v:"required#密码不能为空"` + VerifyCode string `p:"verifyCode" v:"required#验证码不能为空"` + VerifyKey string `p:"verifyKey"` +} + +// LoginUserRes 登录返回 +type LoginUserRes struct { + Id uint64 `orm:"id,primary" json:"id"` // + UserName string `orm:"user_name,unique" json:"userName"` // 用户名 + UserNickname string `orm:"user_nickname" json:"userNickname"` // 用户昵称 + UserPassword string `orm:"user_password" json:"userPassword"` // 登录密码;cmf_password加密 + UserSalt string `orm:"user_salt" json:"userSalt"` // 加密盐 + UserStatus uint `orm:"user_status" json:"userStatus"` // 用户状态;0:禁用,1:正常,2:未验证 + IsAdmin int `orm:"is_admin" json:"isAdmin"` // 是否后台管理员 1 是 0 否 + Avatar string `orm:"avatar" json:"avatar"` //头像 + DeptId uint64 `orm:"dept_id" json:"deptId"` //部门id +} + +// SysUserSearchReq 用户搜索请求参数 +type SysUserSearchReq struct { + DeptId string `p:"deptId"` //部门id + DeptIds []int64 //所属部门id数据 + Phonenumber string `p:"phonenumber"` + Status string `p:"status"` + KeyWords string `p:"userName"` + comModel.PageReq +} + +// SetUserReq 添加修改用户公用请求字段 +type SetUserReq struct { + DeptId uint64 `p:"deptId" v:"required#用户部门不能为空"` //所属部门 + Email string `p:"email" v:"email#邮箱格式错误"` //邮箱 + NickName string `p:"nickName" v:"required#用户昵称不能为空"` + Phonenumber string `p:"phonenumber" v:"required|phone#手机号不能为空|手机号格式错误"` + PostIds []int64 `p:"postIds"` + Remark string `p:"remark"` + RoleIds []int64 `p:"roleIds"` + Sex int `p:"sex"` + Status uint `p:"status"` + IsAdmin int `p:"isAdmin"` // 是否后台管理员 1 是 0 否 +} + +// AddUserReq 添加用户参数 +type AddUserReq struct { + SetUserReq + UserName string `p:"userName" v:"required#用户账号不能为空"` + Password string `p:"password" v:"required|password#密码不能为空|密码以字母开头,只能包含字母、数字和下划线,长度在6~18之间"` + UserSalt string +} + +type EditUserReq struct { + SetUserReq + UserId int `p:"userId" v:"required#用户id不能为空"` +} + +type SysUserRoleDeptRes struct { + *SysUser + Dept *SysDept `json:"dept"` + RoleInfo []*struct { + RoleId uint `json:"roleId"` + Name string `json:"name"` + } `json:"roleInfo"` + Post []*struct { + PostId int64 `json:"postId"` + PostName string `json:"postName"` + } `json:"post"` +} + +// SysUserResetPwdReq 重置用户密码状态参数 +type SysUserResetPwdReq struct { + Id uint64 `p:"userId" v:"required#用户id不能为空"` + Password string `p:"password" v:"required|password#密码不能为空|密码以字母开头,只能包含字母、数字和下划线,长度在6~18之间"` +} + +// SysUserStatusReq 设置用户状态参数 +type SysUserStatusReq struct { + Id uint64 `p:"userId" v:"required#用户id不能为空"` + UserStatus uint `p:"status" v:"required#用户状态不能为空"` +} + +// ProfileUpReq 个人中心修改用户信息参数 +type ProfileUpReq struct { + UserId uint64 + UserNickname string `p:"userNickname" v:"required#用户昵称不能为空" orm:"user_nickname"` // 用户昵称 + Mobile string `p:"mobile" v:"required|phone#手机号不能为空|手机号格式错误" orm:"mobile,unique"` + UserEmail string `p:"userEmail" v:"email#邮箱格式错误" orm:"user_email"` + Sex int `p:"sex" orm:"sex"` +} + +// ProfileUpdatePwdReq 个人中心修改用户密码 +type ProfileUpdatePwdReq struct { + UserId uint64 + OldPassword string `p:"oldPassword" v:"required#旧密码不能为空"` + NewPassword string `p:"newPassword" v:"required#新密码不能为空"` +} diff --git a/app/system/model/sys_user_online.go b/app/system/model/sys_user_online.go new file mode 100644 index 0000000..56d6ecf --- /dev/null +++ b/app/system/model/sys_user_online.go @@ -0,0 +1,22 @@ +// ========================================================================== +// This is auto-generated by gf cli tool. Fill this file as you wish. +// ========================================================================== + +package model + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/model/internal" +) + +// SysUserOnline is the golang structure for table sys_user_online. +type SysUserOnline internal.SysUserOnline + +// Fill with you ideas below. + +// SysUserOnlineSearchReq 列表搜索参数 +type SysUserOnlineSearchReq struct { + Username string `p:"userName"` + Ip string `p:"ipaddr"` + comModel.PageReq +} diff --git a/app/system/model/sys_user_post.go b/app/system/model/sys_user_post.go new file mode 100644 index 0000000..0fea080 --- /dev/null +++ b/app/system/model/sys_user_post.go @@ -0,0 +1,14 @@ +// ================================================================================= +// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. +// ================================================================================= + +package model + +import ( + "gfast/app/system/model/internal" +) + +// SysUserPost is the golang structure for table sys_user_post. +type SysUserPost internal.SysUserPost + +// Fill with you ideas below. diff --git a/app/system/model/sys_web_set.go b/app/system/model/sys_web_set.go new file mode 100644 index 0000000..8c6ac0f --- /dev/null +++ b/app/system/model/sys_web_set.go @@ -0,0 +1,19 @@ +// ================================================================================= +// Code generated by GoFrame CLI tool. DO NOT EDIT. +// ================================================================================= + +package model + +import "github.com/gogf/gf/frame/g" + +// SysWebSet is the golang structure for table sys_web_set. +type SysWebSet struct { + WebId int `orm:"web_id,primary" json:"webId"` // 主键 + WebContent string `orm:"web_content" json:"webContent"` // 站点信息 +} + +// updateReq 用于存储页面更新(新增、修改)网址的信息 +type SysWebSetUpdateReq struct { + WebId int `p:"web_id"` + WebContent g.Map `p:"webContent" v:"required#站点信息不能为空"` // 站点信息 +} diff --git a/app/system/router/router.go b/app/system/router/router.go new file mode 100644 index 0000000..55ee524 --- /dev/null +++ b/app/system/router/router.go @@ -0,0 +1,152 @@ +/* +* @desc: admin router +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/3/11 10:55 + */ + +package router + +import ( + "gfast/app/system/api" + "gfast/middleware" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" +) + +func init() { + s := g.Server() + s.Group("/", func(group *ghttp.RouterGroup) { + group.Group("/system", func(group *ghttp.RouterGroup) { + //gToken拦截器 + api.GfToken.Middleware(group) + //context拦截器 + group.Middleware(middleware.Ctx, middleware.Auth) + //后台操作日志记录 + group.Hook("/*", ghttp.HookAfterOutput, api.SysOperLog.OperationLog) + //后台上传 + group.Group("/upload", func(group *ghttp.RouterGroup) { + //单图上传 + group.POST("/upImg", api.Upload.UpImg) + }) + //用户相关 + group.Group("/user", func(group *ghttp.RouterGroup) { + //获取用户信息 + group.GET("/getInfo", api.User.GetInfo) + //获取用户菜单 + group.GET("/getRouters", api.User.GetRouters) + //个人中心 + group.GET("/profile", api.UserProfile.Profile) + //头像上传 + group.POST("/avatar", api.UserProfile.Avatar) + //修改用户信息 + group.PUT("/edit", api.UserProfile.Edit) + //修改密码 + group.PUT("/updatePwd", api.UserProfile.UpdatePwd) + }) + //配置相关 + group.Group("/config", func(group *ghttp.RouterGroup) { + //获取字典分类列表 + group.GET("/dict/type/list", api.DictType.List) + group.POST("/dict/type/add", api.DictType.Add) + group.GET("/dict/type/one", api.DictType.Get) + group.PUT("/dict/type/edit", api.DictType.Edit) + group.DELETE("/dict/type/delete", api.DictType.Delete) + //字典数据 + group.GET("/dict/data/GetDictData", api.DictData.GetDictData) + group.GET("/dict/data/list", api.DictData.List) + group.POST("/dict/data/add", api.DictData.Add) + group.GET("/dict/data/one", api.DictData.Get) + group.PUT("/dict/data/edit", api.DictData.Edit) + group.DELETE("/dict/data/delete", api.DictData.Delete) + //系统参数管理 + group.GET("/sysConfig/list", api.SysConfig.List) + group.POST("/sysConfig/add", api.SysConfig.Add) + group.GET("/sysConfig/one", api.SysConfig.Get) + group.PUT("/sysConfig/edit", api.SysConfig.Edit) + group.DELETE("/sysConfig/delete", api.SysConfig.Delete) + //站点设置 + group.GET("/sysWebSet", api.SysWebSet.Get) + group.POST("/sysWebSet/update", api.SysWebSet.Update) + }) + // 权限管理 + group.Group("/auth", func(group *ghttp.RouterGroup) { + //菜单管理 + group.GET("menuList", api.AuthRule.MenuList) + group.GET("getMenus", api.AuthRule.GetMenus) + group.POST("addMenu", api.AuthRule.AddMenuPost) + group.GET("modelOptions", api.AuthRule.ModelOptions) + group.GET("menu", api.AuthRule.GetMenu) + group.PUT("editMenu", api.AuthRule.EditPost) + group.DELETE("deleteMenu", api.AuthRule.DeleteMenu) + //角色管理 + group.GET("roleList", api.SysRole.RoleList) + group.GET("addRole", api.SysRole.GetRoleMenu) + group.POST("addRole", api.SysRole.AddRole) + group.GET("editRole", api.SysRole.GetRole) + group.PUT("editRole", api.SysRole.EditRole) + group.PUT("statusSetRole", api.SysRole.StatusSetRole) + group.PUT("roleDataScope", api.SysRole.RoleDataScope) + group.DELETE("deleteRole", api.SysRole.DeleteRole) + // 部门管理 + group.GET("deptList", api.Dept.List) + group.POST("deptAdd", api.Dept.Add) + group.GET("deptGet", api.Dept.Get) + group.PUT("deptEdit", api.Dept.Edit) + group.DELETE("deptDelete", api.Dept.Delete) + group.GET("deptTreeSelect", api.Dept.TreeSelect) + group.GET("roleDeptTreeSelect", api.Dept.RoleDeptTreeSelect) + //岗位管理 + group.GET("postList", api.SysPost.List) + group.GET("postGet", api.SysPost.Get) + group.POST("postAdd", api.SysPost.Add) + group.PUT("postEdit", api.SysPost.Edit) + group.DELETE("postDelete", api.SysPost.Delete) + //用户管理 + group.GET("userList", api.User.UserList) + group.GET("userGet", api.User.Get) + group.POST("addUser", api.User.AddUser) + group.GET("getEditUser", api.User.GetEditUser) + group.PUT("editUser", api.User.EditUser) + group.PUT("resetUserPwd", api.User.ResetUserPwd) + group.PUT("changeUserStatus", api.User.ChangeUserStatus) + group.DELETE("deleteUser", api.User.DeleteUser) + }) + //系统监控 + group.Group("/monitor", func(group *ghttp.RouterGroup) { + //在线用户管理 + group.Group("/online", func(group *ghttp.RouterGroup) { + group.GET("list", api.SysUserOnline.List) + group.PUT("forceLogout", api.SysUserOnline.ForceLogout) + }) + //定时任务管理 + group.Group("/job", func(group *ghttp.RouterGroup) { + group.GET("list", api.SysJob.List) + group.POST("add", api.SysJob.Add) + group.GET("get", api.SysJob.Get) + group.PUT("edit", api.SysJob.Edit) + group.PUT("start", api.SysJob.Start) + group.PUT("stop", api.SysJob.Stop) + group.DELETE("delete", api.SysJob.Delete) + }) + //服务监控 + group.Group("/server", func(group *ghttp.RouterGroup) { + group.GET("info", api.SysMonitor.Info) + }) + //登录日志 + group.Group("/loginLog", func(group *ghttp.RouterGroup) { + group.GET("list", api.SysLoginLog.List) + group.DELETE("delete", api.SysLoginLog.Delete) + group.DELETE("clear", api.SysLoginLog.Clear) + }) + //操作日志 + group.Group("/operLog", func(group *ghttp.RouterGroup) { + group.GET("list", api.SysOperLog.List) + group.GET("detail", api.SysOperLog.Detail) + group.DELETE("delete", api.SysOperLog.Delete) + group.DELETE("clear", api.SysOperLog.Clear) + }) + }) + }) + }) +} diff --git a/app/system/service/.gitkeep b/app/system/service/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/app/system/service/context.go b/app/system/service/context.go new file mode 100644 index 0000000..c502b7d --- /dev/null +++ b/app/system/service/context.go @@ -0,0 +1,34 @@ +package service + +import ( + "context" + "gfast/app/system/dao" + "github.com/gogf/gf/net/ghttp" +) + +// Context 上下文管理服务 +var Context = new(contextService) + +type contextService struct{} + +// Init 初始化上下文对象指针到上下文对象中,以便后续的请求流程中可以修改。 +func (s *contextService) Init(r *ghttp.Request, customCtx *dao.Context) { + r.SetCtxVar(dao.CtxKey, customCtx) +} + +// Get 获得上下文变量,如果没有设置,那么返回nil +func (s *contextService) Get(ctx context.Context) *dao.Context { + value := ctx.Value(dao.CtxKey) + if value == nil { + return nil + } + if localCtx, ok := value.(*dao.Context); ok { + return localCtx + } + return nil +} + +// SetUser 将上下文信息设置到上下文请求中,注意是完整覆盖 +func (s *contextService) SetUser(ctx context.Context, ctxUser *dao.CtxUser) { + s.Get(ctx).User = ctxUser +} diff --git a/app/system/service/sys_auth_rule.go b/app/system/service/sys_auth_rule.go new file mode 100644 index 0000000..7fe06e1 --- /dev/null +++ b/app/system/service/sys_auth_rule.go @@ -0,0 +1,230 @@ +package service + +import ( + "gfast/app/common/global" + "gfast/app/common/service" + "gfast/app/system/dao" + "gfast/app/system/model" + "github.com/gogf/gf/frame/gmvc" + "github.com/gogf/gf/util/gconv" +) + +type rule struct { +} + +var Rule = new(rule) + +//获取status==1的菜单列表 +func (s *rule) GetMenuIsStatusList() ([]*model.SysAuthRuleInfoRes, error) { + list, err := s.GetMenuList() + if err != nil { + return nil, err + } + var gList = make([]*model.SysAuthRuleInfoRes, 0, len(list)) + for _, v := range list { + if (v.MenuType == 0 || v.MenuType == 1) && v.Status == 1 { + gList = append(gList, v) + } + } + return gList, nil +} + +//获取所有菜单 +func (s *rule) GetMenuList() (list []*model.SysAuthRuleInfoRes, err error) { + cache := service.Cache.New() + //从缓存获取 + iList := cache.Get(global.SysAuthMenu) + if iList != nil { + err = gconv.Struct(iList, &list) + return + } + //从数据库获取 + list, err = dao.SysAuthRule.GetMenuList() + if err != nil || list == nil { + return + } + //缓存菜单 + cache.Set(global.SysAuthMenu, list, 0, global.SysAuthTag) + return +} + +func (s *rule) GetMenuListSearch(req *model.SysAuthRuleReqSearch) (list []*model.SysAuthRuleInfoRes, err error) { + list, err = dao.SysAuthRule.Scope(func(m gmvc.M) gmvc.M { + if req != nil && !req.IsEmpty() { + if req.Title != "" { + m = m.Where("title like ?", "%"+req.Title+"%") + } + + if req.Status != "" { + m = m.Where("status = ?", req.Status) + } + } + return m + }).GetMenuList() + if err != nil || list == nil { + return + } + return +} + +func (s *rule) GetMenuListTree(pid uint, list []*model.SysAuthRuleInfoRes) []*model.SysAuthRuleTreeRes { + tree := make([]*model.SysAuthRuleTreeRes, 0, len(list)) + for _, menu := range list { + if menu.Pid == pid { + t := &model.SysAuthRuleTreeRes{ + SysAuthRuleInfoRes: menu, + } + child := s.GetMenuListTree(menu.Id, list) + if child != nil { + t.Children = child + } + tree = append(tree, t) + } + } + return tree +} + +// GetIsButtonStatusList 获取所有按钮isMenu=2 且status=1的菜单列表 +func (s *rule) GetIsButtonStatusList() ([]*model.SysAuthRuleInfoRes, error) { + list, err := s.GetMenuList() + if err != nil { + return nil, err + } + var gList = make([]*model.SysAuthRuleInfoRes, 0, len(list)) + for _, v := range list { + if v.MenuType == 2 && v.Status == 1 { + gList = append(gList, v) + } + } + return gList, nil +} + +func (s *rule) GetIsMenuList() ([]*model.SysAuthRuleInfoRes, error) { + list, err := s.GetMenuList() + if err != nil { + return nil, err + } + var gList = make([]*model.SysAuthRuleInfoRes, 0) + for _, v := range list { + if v.MenuType == 0 || v.MenuType == 1 { + gList = append(gList, v) + } + } + return gList, nil +} + +//检查菜单规则是否存在 +func (s *rule) CheckMenuNameUnique(name string, id int) bool { + return dao.SysAuthRule.CheckMenuNameUnique(name, id) +} + +//检查菜单路由地址是否已经存在 +func (s *rule) CheckMenuPathUnique(path string, id int) bool { + return dao.SysAuthRule.CheckMenuPathUnique(path, id) +} + +func (s *rule) AddMenu(req *model.MenuReq) (err error, insertId int64) { + result, e := dao.SysAuthRule.Save(req) + if e != nil { + return e, 0 + } + lastId, e := result.LastInsertId() + if e != nil { + return e, 0 + } + return nil, lastId +} + +//获取分类模型选项 +func (s *rule) ModelOptions(module string) (models []*model.SysModelInfo, err error) { + dictType := "" + switch module { + case "gov_work": + //政务平台 + dictType = "gov_cate_models" + } + + if dictType != "" { + //栏目模型分类 + //var modelOptions g.Map + modelOptions, e := SysDictData.GetDictWithDataByType(&model.GetDictReq{ + DictType: dictType, + }) + if e != nil { + err = e + return + } + values := gconv.SliceAny(modelOptions.Values) + keys := make([]int, len(values)) + for k, val := range values { + data := gconv.Map(val) + keys[k] = gconv.Int(data["key"]) + } + //获取对应模型 + models, err = SysInfo.GetModelsByCateIds(keys) + if err != nil { + return + } + } + return +} + +func (s *rule) One(id uint64) (*model.SysAuthRule, error) { + return dao.SysAuthRule.Where("id = ?", id).FindOne() +} + +func (s *rule) EditMenu(req *model.MenuReq, id int) (err error, rows int64) { + result, e := dao.SysAuthRule.Where("id = ?", id).Update(req) + if e != nil { + err = e + return + } + r, e := result.RowsAffected() + if e != nil { + err = e + return + } + return nil, r +} + +func (s *rule) DeleteMenuByIds(ids []int) (err error) { + var list []*model.SysAuthRuleInfoRes + list, err = s.GetMenuList() + if err != nil { + return + } + childrenIds := make([]int, 0, len(list)) + for _, id := range ids { + rules := s.FindSonByParentId(list, gconv.Uint(id)) + for _, child := range rules { + childrenIds = append(childrenIds, gconv.Int(child.Id)) + } + } + ids = append(ids, childrenIds...) + _, err = dao.SysAuthRule.Where("id in (?)", ids).Delete() + return +} + +func (s *rule) ParentSonSort(list []*model.SysAuthRuleInfoRes, pid uint) []*model.SysAuthRuleInfoRes { + newList := make([]*model.SysAuthRuleInfoRes, 0, len(list)) + for _, v := range list { + if pid == v.Pid { + newList = append(newList, v) + newList2 := s.ParentSonSort(list, v.Id) + newList = append(newList, newList2...) + } + } + return newList +} + +func (s *rule) FindSonByParentId(list []*model.SysAuthRuleInfoRes, pid uint) []*model.SysAuthRuleInfoRes { + children := make([]*model.SysAuthRuleInfoRes, 0, len(list)) + for _, v := range list { + if v.Pid == pid { + children = append(children, v) + fChildren := s.FindSonByParentId(list, v.Id) + children = append(children, fChildren...) + } + } + return children +} diff --git a/app/system/service/sys_dept.go b/app/system/service/sys_dept.go new file mode 100644 index 0000000..61ba8a2 --- /dev/null +++ b/app/system/service/sys_dept.go @@ -0,0 +1,110 @@ +package service + +import ( + "gfast/app/system/dao" + "gfast/app/system/model" +) + +type dept struct { +} + +var Dept = new(dept) + +func (s *dept) GetList(searchParams *dao.SysDeptSearchParams) ([]*model.SysDept, error) { + deptModel := dao.SysDept.M + if searchParams.DeptName != "" { + deptModel = deptModel.Where("dept_name like ?", "%"+searchParams.DeptName+"%") + } + if searchParams.Status != "" { + deptModel = deptModel.Where("status", searchParams.Status) + } + depts := ([]*model.SysDept)(nil) + if err := deptModel.Scan(&depts); err != nil { + return nil, err + } + list := make([]*model.SysDept, 0, len(depts)) + if searchParams.ExcludeId != 0 { + for _, v := range depts { + if searchParams.ExcludeId != v.DeptId { + list = append(list, v) + } + } + return list, nil + } else { + return depts, nil + } +} + +func (s *dept) GetRoleDepts(roleId int64) ([]int64, error) { + var entitys []*model.SysRoleDept + err := dao.SysRoleDept.Where("role_id", roleId).Scan(&entitys) + if err != nil { + return nil, err + } + result := make([]int64, 0) + for _, v := range entitys { + result = append(result, v.DeptId) + } + return result, nil +} + +func (s *dept) FindSonByParentId(depts []*model.SysDept, deptId int64) []*model.SysDept { + children := make([]*model.SysDept, 0, len(depts)) + for _, v := range depts { + if v.ParentId == deptId { + children = append(children, v) + fChildren := s.FindSonByParentId(depts, v.DeptId) + children = append(children, fChildren...) + } + } + return children +} + +func (s *dept) GetDeptListTree(pid int64, list []*model.SysDept) []*dao.SysDeptTreeRes { + tree := make([]*dao.SysDeptTreeRes, 0, len(list)) + for _, v := range list { + if v.ParentId == pid { + t := &dao.SysDeptTreeRes{ + SysDept: v, + } + child := s.GetDeptListTree(v.DeptId, list) + if child != nil && len(child) > 0 { + t.Children = child + } + tree = append(tree, t) + } + } + return tree +} + +func (s *dept) AddDept(params *dao.SysDeptAddParams) (err error) { + _, err = dao.SysDept.Insert(params) + return +} + +func (s *dept) GetDeptById(id uint64) (dept *model.SysDept, err error) { + err = dao.SysDept.Where("dept_id", id).Scan(&dept) + return +} + +func (s *dept) EditDept(params *dao.EditParams) error { + _, err := dao.SysDept.FieldsEx(dao.SysDept.C.DeptId, dao.SysDept.C.CreatedBy).WherePri(params.DeptID). + Update(params) + return err +} + +func (s *dept) DelDept(id int64) error { + var list []*model.SysDept + err := dao.SysDept.Scan(&list) + if err != nil { + return err + } + children := s.FindSonByParentId(list, id) + ids := make([]int64, 0, len(list)) + for _, v := range children { + ids = append(ids, v.DeptId) + } + ids = append(ids, id) + _, err = dao.SysDept.Where(dao.SysDept.C.DeptId+" in (?)", ids).Delete() + return err +} diff --git a/app/system/service/sys_dict_data.go b/app/system/service/sys_dict_data.go new file mode 100644 index 0000000..42a50ae --- /dev/null +++ b/app/system/service/sys_dict_data.go @@ -0,0 +1,167 @@ +/* +* @desc:字典数据 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/4/3 12:00 + */ + +package service + +import ( + "database/sql" + "gfast/app/common/global" + comModel "gfast/app/common/model" + comService "gfast/app/common/service" + "gfast/app/system/dao" + "gfast/app/system/model" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gconv" +) + +type sysDictData struct{} + +var SysDictData = new(sysDictData) + +func (s sysDictData) DictDataList(req *model.SelectDictPageReq) (total, page int, list []*model.SysDictData, err error) { + d := dao.SysDictData.Ctx(req.Ctx) + if req != nil { + if req.DictLabel != "" { + d = d.Where(dao.SysDictData.Columns.DictLabel+" like ?", "%"+req.DictLabel+"%") + } + if req.Status != "" { + d = d.Where(dao.SysDictData.Columns.Status+" = ", gconv.Int(req.Status)) + } + if req.DictType != "" { + d = d.Where(dao.SysDictData.Columns.DictType+" = ?", req.DictType) + } + total, err = d.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + if req.PageNum == 0 { + req.PageNum = 1 + } + } + page = req.PageNum + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + list, err = d.Page(page, req.PageSize).Order(dao.SysDictData.Columns.DictSort + " asc," + + dao.SysDictData.Columns.DictCode + " asc").All() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + return + } + return +} + +// GetDictWithDataByType 通过字典键类型获取选项 +func (s sysDictData) GetDictWithDataByType(req *model.GetDictReq) (dict *model.DictRes, + err error) { + cache := comService.Cache.New() + cacheKey := global.SysDict + "_" + req.DictType + //从缓存获取 + iDict := cache.Get(cacheKey) + if iDict != nil { + err = gconv.Struct(iDict, &dict) + if err != nil { + return + } + } else { + //从数据库获取 + dict = &model.DictRes{} + //获取类型数据 + err = dao.SysDictType.Ctx(req.Ctx).Where(dao.SysDictType.Columns.DictType, req.DictType). + And(dao.SysDictType.Columns.Status, 1).Fields(model.DictTypeRes{}).Scan(&dict.Info) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取字典类型失败") + } + err = dao.SysDictData.Ctx(req.Ctx).Fields(model.DictDataRes{}). + Where(dao.SysDictData.Columns.DictType, req.DictType). + Order(dao.SysDictData.Columns.DictSort + " asc," + + dao.SysDictData.Columns.DictCode + " asc"). + Scan(&dict.Values) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取字典数据失败") + } + //缓存菜单 + if dict.Info != nil && dict.Values != nil { + cache.Set(cacheKey, dict, 0, global.SysDictTag) + } + } + //设置给定的默认值 + for _, v := range dict.Values { + if req.DefaultValue != "" { + if gstr.Equal(req.DefaultValue, v.DictValue) { + v.IsDefault = 1 + } else { + v.IsDefault = 0 + } + } + } + return +} + +// CheckDictTypeUniqueAll 检查字典类型是否唯一 +func (s *sysDictData) CheckDictTypeUniqueAll(dictType string) bool { + dict, err := dao.SysDictData.FindOne(dao.SysDictData.Columns.DictType+"=?", dictType) + if err != nil { + g.Log().Error(err) + return false + } + if dict != nil { + return false + } + return true +} + +// AddSave 添加保存字典数据 +func (s *sysDictData) AddSave(req *model.DictDataAddReq) (id int64, err error) { + var res sql.Result + res, err = dao.SysDictData.Data(req).Insert() + if err != nil { + g.Log().Error(err) + err = gerror.New("添加字典数据失败") + return + } + id, err = res.LastInsertId() + return +} + +// GetDictDataById 通过字典数据id获取字典数据 +func (s sysDictData) GetDictDataById(id int) (data *model.SysDictData, err error) { + data, err = dao.SysDictData.FindOne(dao.SysDictData.Columns.DictCode, id) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取字典数据失败") + return + } + if data == nil { + err = gerror.New("获取字典数据失败") + } + return +} + +// EditSaveData 修改字典数据 +func (s sysDictData) EditSaveData(req *model.EditDictDataReq) (err error) { + _, err = dao.SysDictData.FieldsEx(dao.SysDictData.Columns.DictCode, dao.SysDictData.Columns.CreateBy). + WherePri(req.DictCode).Update(req) + return +} + +// DeleteDictDataByIds 删除字典数据 +func (s sysDictData) DeleteDictDataByIds(ids []int) error { + _, err := dao.SysDictData.Where(dao.SysDictData.Columns.DictCode+" in(?)", ids).Delete() + if err != nil { + g.Log().Error(err) + return gerror.New("删除失败") + } + return nil +} diff --git a/app/system/service/sys_dict_type.go b/app/system/service/sys_dict_type.go new file mode 100644 index 0000000..c05e01a --- /dev/null +++ b/app/system/service/sys_dict_type.go @@ -0,0 +1,156 @@ +package service + +import ( + "context" + comModel "gfast/app/common/model" + "gfast/app/system/dao" + "gfast/app/system/model" + "github.com/gogf/gf/container/garray" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" +) + +type sysDictType struct { +} + +var SysDictType = new(sysDictType) + +func (s *sysDictType) SelectList(req *model.ListSysDictTypeReq) (total, page int, + list []*model.SysDictTypeInfoRes, err error) { + d := dao.SysDictType.Ctx(req.Ctx) + if req.DictName != "" { + d = d.Where(dao.SysDictType.Columns.DictName+" like ?", "%"+req.DictName+"%") + } + if req.DictType != "" { + d = d.Where(dao.SysDictType.Columns.DictType+" like ?", "%"+req.DictType+"%") + } + if req.Status != "" { + d = d.Where(dao.SysDictType.Columns.Status+" = ", gconv.Int(req.Status)) + } + if req.BeginTime != "" { + d = d.Where(dao.SysDictType.Columns.CreatedAt+" >=?", req.BeginTime) + } + if req.EndTime != "" { + d = d.Where(dao.SysDictType.Columns.CreatedAt+" <=?", req.EndTime) + } + total, err = d.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + if req.PageNum == 0 { + req.PageNum = 1 + } + page = req.PageNum + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + err = d.Fields(model.SysDictTypeInfoRes{}).Page(page, req.PageSize). + Order(dao.SysDictType.Columns.DictId + " asc").Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + } + return +} + +// ExistsDictType 检查类型是否已经存在 +func (s *sysDictType) ExistsDictType(dictType string, dictId ...int64) bool { + d := dao.SysDictType.Fields(dao.SysDictType.Columns.DictId). + Where(dao.SysDictType.Columns.DictType, dictType) + if len(dictId) > 0 { + d = d.And(dao.SysDictType.Columns.DictId+" !=? ", dictId) + } + dict, err := d.FindOne() + if err != nil { + g.Log().Error(err) + return false + } + if dict != nil { + return true + } + return false +} + +func (s *sysDictType) Add(req *model.SysDictTypeAddReq) error { + _, err := dao.SysDictType.Insert(req) + if err != nil { + g.Log().Debug(err) + err = gerror.New("保存到数据库失败") + } + return err +} + +func (s *sysDictType) Edit(ctx context.Context, req *model.SysDictTypeEditReq) error { + err := g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error { + dt, err := dao.SysDictType.Fields(dao.SysDictType.Columns.DictType).FindOne(req.DictId) + if err != nil { + return err + } + //修改字典类型 + _, err = dao.SysDictType.TX(tx).FieldsEx(dao.SysDictType.Columns.CreateBy, + dao.SysDictType.Columns.DictId).WherePri(req.DictId).Update(req) + if err != nil { + return err + } + //修改字段数据的类型 + _, err = dao.SysDictData.TX(tx).Data(g.Map{dao.SysDictData.Columns.DictType: req.DictType}). + Where(dao.SysDictData.Columns.DictType, dt.DictType).Update() + return nil + }) + if err != nil { + g.Log().Debug(err) + err = gerror.New("保存到数据库失败") + } + return err +} + +func (s *sysDictType) Delete(ctx context.Context, dictIds []int) (err error) { + discs := ([]*model.SysDictType)(nil) + discs, err = dao.SysDictType.Fields(dao.SysDictType.Columns.DictType). + Where(dao.SysDictType.Columns.DictId+" in (?) ", dictIds).All() + if err != nil { + g.Log().Error(err) + err = gerror.New("没有要删除的数据") + return + } + types := garray.NewStrArray() + for _, dt := range discs { + types.Append(dt.DictType) + } + if types.Len() > 0 { + err = g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error { + _, err = dao.SysDictType.TX(tx).Delete(dao.SysDictType.Columns.DictId+" in (?) ", dictIds) + if err != nil { + g.Log().Error(err) + err = gerror.New("删除类型失败") + return err + } + _, err = dao.SysDictData.TX(tx).Delete(dao.SysDictData.Columns.DictType+" in (?) ", types.Slice()) + if err != nil { + g.Log().Error(err) + err = gerror.New("删除字典数据失败") + return err + } + return nil + }) + } + return +} + +// GetDictById 获取字典类型 +func (s *sysDictType) GetDictById(id int) (dict *model.SysDictType, err error) { + dict, err = dao.SysDictType.FindOne(dao.SysDictType.Columns.DictId, id) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取字典类型失败") + return + } + if dict == nil { + err = gerror.New("不存在的字典类型") + } + return +} diff --git a/app/system/service/sys_info.go b/app/system/service/sys_info.go new file mode 100644 index 0000000..7c483d4 --- /dev/null +++ b/app/system/service/sys_info.go @@ -0,0 +1,15 @@ +package service + +import ( + "gfast/app/system/dao" + "gfast/app/system/model" +) + +type info struct { +} + +var SysInfo = new(info) + +func (i *info) GetModelsByCateIds(cateIds []int) (models []*model.SysModelInfo, err error) { + return dao.SysModelInfo.GetModelsByCateIds(cateIds) +} diff --git a/app/system/service/sys_job.go b/app/system/service/sys_job.go new file mode 100644 index 0000000..f33cb97 --- /dev/null +++ b/app/system/service/sys_job.go @@ -0,0 +1,176 @@ +/* +* @desc:定时任务处理 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/15 9:32 + */ + +package service + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/dao" + "gfast/app/system/model" + "github.com/gogf/gf/container/gset" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/gcron" + "github.com/gogf/gf/util/gconv" + "strings" +) + +type sysJob struct { +} + +var SysJob = new(sysJob) + +// JobList 获取任务列表 +func (s *sysJob) JobList(req *dao.SysJobSearchReq) (total, page int, list []*model.SysJob, err error) { + model := dao.SysJob.M + if req != nil { + if req.Status != "" { + model = model.Where("status", gconv.Int(req.Status)) + } + if req.JobGroup != "" { + model = model.Where("job_group", req.JobGroup) + } + if req.JobName != "" { + model = model.Where("job_name like ?", "%"+req.JobName+"%") + } + } + total, err = model.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + if req.PageNum == 0 { + req.PageNum = 1 + } + page = req.PageNum + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + err = model.Page(page, req.PageSize).Order("job_id asc").Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + } + return +} + +// GetJobs 获取已开启执行的任务 +func (s *sysJob) GetJobs() (jobs []*model.SysJob, err error) { + err = dao.SysJob.Where(dao.SysJob.C.Status, 0).Scan(&jobs) + return +} + +func (s *sysJob) AddJob(req *dao.SysJobAddReq) (err error) { + _, err = dao.SysJob.Insert(req) + return +} + +func (s *sysJob) GetJobInfoById(id int64) (job *model.SysJob, err error) { + if id == 0 { + err = gerror.New("参数错误") + return + } + err = dao.SysJob.Where("job_id", id).Scan(&job) + if err != nil { + g.Log().Error(err) + } + if job == nil || err != nil { + err = gerror.New("获取任务信息失败") + } + return +} + +func (s *sysJob) EditJob(req *dao.SysJobEditReq) error { + _, err := dao.SysJob.FieldsEx(dao.SysJob.C.JobId, dao.SysJob.C.CreateBy).Where(dao.SysJob.C.JobId, req.JobId). + Update(req) + return err +} + +// JobStart 启动任务 +func (s *sysJob) JobStart(job *model.SysJob) error { + //获取task目录下是否绑定对应的方法 + f := TimeTaskList.GetByName(job.InvokeTarget) + if f == nil { + return gerror.New("没有绑定对应的方法") + } + //传参 + paramArr := strings.Split(job.JobParams, "|") + TimeTaskList.EditParams(f.FuncName, paramArr) + rs := gcron.Search(job.InvokeTarget) + if rs == nil { + if job.MisfirePolicy == 1 { + t, err := gcron.AddSingleton(job.CronExpression, f.Run, job.InvokeTarget) + if err != nil { + return err + } + if t == nil { + return gerror.New("启动任务失败") + } + } else { + t, err := gcron.AddOnce(job.CronExpression, f.Run, job.InvokeTarget) + if err != nil { + return err + } + if t == nil { + return gerror.New("启动任务失败") + } + } + } + gcron.Start(job.InvokeTarget) + if job.MisfirePolicy == 1 { + job.Status = 0 + _, err := dao.SysJob.Where(dao.SysJob.C.JobId, job.JobId).Unscoped().Update(g.Map{ + dao.SysJob.C.Status: job.Status, + }) + return err + } + return nil +} + +// JobStop 停止任务 +func (s *sysJob) JobStop(job *model.SysJob) error { + //获取task目录下是否绑定对应的方法 + f := TimeTaskList.GetByName(job.InvokeTarget) + if f == nil { + return gerror.New("没有绑定对应的方法") + } + rs := gcron.Search(job.InvokeTarget) + if rs != nil { + gcron.Remove(job.InvokeTarget) + } + job.Status = 1 + _, err := dao.SysJob.Where(dao.SysJob.C.JobId, job.JobId).Unscoped().Update(g.Map{ + dao.SysJob.C.Status: job.Status, + }) + return err +} + +// DeleteJobByIds 删除任务 +func (s *sysJob) DeleteJobByIds(ids []int) (err error) { + if len(ids) == 0 { + err = gerror.New("参数错误") + } + gst := gset.NewFrom(ids) + var jobs []*model.SysJob + jobs, err = s.GetJobs() + if err != nil { + return + } + for _, job := range jobs { + if gst.Contains(int(job.JobId)) { + err = gerror.New("运行中的任务不能删除") + return + } + } + _, err = dao.SysJob.Delete(dao.SysJob.C.JobId+" in (?)", ids) + if err != nil { + g.Log().Error(err) + err = gerror.New("删除失败") + } + return +} diff --git a/app/system/service/sys_login_log.go b/app/system/service/sys_login_log.go new file mode 100644 index 0000000..6910a01 --- /dev/null +++ b/app/system/service/sys_login_log.go @@ -0,0 +1,107 @@ +/* +* @desc:登录日志 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/13 17:23 + */ + +package service + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/dao" + "gfast/app/system/model" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/grpool" + "github.com/gogf/gf/util/gconv" +) + +type sysLoginLog struct { + Pool *grpool.Pool +} + +var ( + SysLoginLog = &sysLoginLog{ + Pool: grpool.New(100), + } +) + +func (s *sysLoginLog) Invoke(data *model.LoginLogParams) { + s.Pool.Add(func() { + //写入日志数据 + SysUser.LoginLog(data) + }) +} + +func (s *sysLoginLog) LoginLogListByPage(req *model.SysLoginLogSearchReq) (total, page int, list []*model.SysLoginLog, err error) { + if req.PageNum == 0 { + req.PageNum = 1 + } + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + model := dao.SysLoginLog.M + page = req.PageNum + order := "info_id DESC" + if req.LoginName != "" { + model = model.Where("login_name like ?", "%"+req.LoginName+"%") + } + if req.Status != "" { + model = model.Where("status", gconv.Int(req.Status)) + } + if req.Ipaddr != "" { + model = model.Where("ipaddr like ?", "%"+req.Ipaddr+"%") + } + if req.LoginLocation != "" { + model = model.Where("login_location like ?", "%"+req.LoginLocation+"%") + } + if req.BeginTime != "" { + model = model.Where("login_time >=", req.BeginTime) + } + if req.EndTime != "" { + model = model.Where("login_time <=", req.EndTime) + } + if req.SortName != "" { + if req.SortOrder != "" { + order = req.SortName + " " + req.SortOrder + } else { + order = req.SortName + " DESC" + } + } + + total, err = model.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + err = model.Page(page, req.PageSize).Order(order).Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + } + return +} + +func (s *sysLoginLog) DeleteLoginLogByIds(ids []int) (err error) { + if len(ids) == 0 { + err = gerror.New("参数错误") + return + } + _, err = dao.SysLoginLog.Delete("info_id in (?)", ids) + if err != nil { + g.Log().Error(err) + err = gerror.New("删除失败") + } + return +} + +func (s *sysLoginLog) ClearLoginLog() (err error) { + _, err = g.DB().Exec("truncate " + dao.SysLoginLog.Table) + if err != nil { + g.Log().Error(err) + err = gerror.New("清除失败") + } + return +} diff --git a/app/system/service/sys_oper_log.go b/app/system/service/sys_oper_log.go new file mode 100644 index 0000000..ec08402 --- /dev/null +++ b/app/system/service/sys_oper_log.go @@ -0,0 +1,179 @@ +/* +* @desc:操作日志处理 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/19 14:58 + */ + +package service + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/dao" + "gfast/app/system/model" + "gfast/library" + "github.com/gogf/gf/encoding/gjson" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/grpool" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/util/gconv" +) + +type sysOperLog struct { + Pool *grpool.Pool +} + +var SysOperLog = &sysOperLog{ + Pool: grpool.New(100), +} + +func (s *sysOperLog) Invoke(data *dao.SysOperLogAdd) { + s.Pool.Add(func() { + //写入日志数据 + s.OperationLogAdd(data) + }) +} + +// OperationLogAdd 添加操作日志 +func (s sysOperLog) OperationLogAdd(data *dao.SysOperLogAdd) { + menuTitle := "" + if data.Menu != nil { + menuTitle = data.Menu.Title + } + err, dept := data.User.GetDept() + if err != nil { + g.Log().Error(err) + return + } + insertData := g.Map{ + dao.SysOperLog.C.Title: menuTitle, + dao.SysOperLog.C.Method: data.Url.Path, + dao.SysOperLog.C.RequestMethod: data.Method, + dao.SysOperLog.C.OperatorType: data.OperatorType, + dao.SysOperLog.C.OperName: data.User.UserName, + dao.SysOperLog.C.DeptName: dept.DeptName, + dao.SysOperLog.C.OperIp: data.ClientIp, + dao.SysOperLog.C.OperLocation: library.GetCityByIp(data.ClientIp), + dao.SysOperLog.C.OperTime: gtime.Now(), + } + rawQuery := data.Url.RawQuery + if rawQuery != "" { + rawQuery = "?" + rawQuery + } + insertData[dao.SysOperLog.C.OperUrl] = data.Url.Path + rawQuery + if data.Params != nil { + if v, ok := data.Params["apiReturnRes"]; ok { + res := gconv.Map(v) + if gconv.Int(res["code"]) == 0 { + insertData[dao.SysOperLog.C.Status] = 1 + } else { + insertData[dao.SysOperLog.C.Status] = 0 + } + if _, ok = res["data"]; ok { + delete(res, "data") + } + b, _ := gjson.Encode(res) + if len(b) > 0 { + insertData[dao.SysOperLog.C.JsonResult] = string(b) + } + delete(data.Params, "apiReturnRes") + } + b, _ := gjson.Encode(data.Params) + if len(b) > 0 { + insertData[dao.SysOperLog.C.OperParam] = string(b) + } + } + _, err = dao.SysOperLog.Insert(insertData) + if err != nil { + g.Log().Error(err) + } +} + +func (s *sysOperLog) OperationLogListByPage(req *dao.SysOperLogSearchReq) (total, page int, list []*model.SysOperLog, err error) { + model := dao.SysOperLog.M + order := "oper_id DESC" + if req != nil { + if req.OperName != "" { + model = model.Where("oper_name like ?", "%"+req.OperName+"%") + } + if req.Title != "" { + model = model.Where("title like ?", "%"+req.Title+"%") + } + if req.RequestMethod != "" { + model = model.Where("request_method = ?", req.RequestMethod) + } + if req.Status != "" { + model = model.Where("status", gconv.Int(req.Status)) + } + if req.BeginTime != "" { + model = model.Where("oper_time >=", req.BeginTime) + } + if req.EndTime != "" { + model = model.Where("oper_time <=", req.EndTime) + } + if req.SortName != "" { + if req.SortOrder != "" { + order = req.SortName + " " + req.SortOrder + } else { + order = req.SortName + " DESC" + } + } + } + total, err = model.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + if req.PageNum == 0 { + req.PageNum = 1 + } + page = req.PageNum + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + err = model.Page(page, req.PageSize).Order(order).Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + } + return +} + +func (s *sysOperLog) DeleteOperationLogByIds(ids []int) (err error) { + if len(ids) == 0 { + err = gerror.New("参数错误") + return + } + _, err = dao.SysOperLog.Delete("oper_id in (?)", ids) + if err != nil { + g.Log().Error(err) + err = gerror.New("删除失败") + } + return +} + +func (s *sysOperLog) GetOperationLogById(id int64) (log *model.SysOperLog, err error) { + if id == 0 { + err = gerror.New("参数错误") + return + } + err = dao.SysOperLog.Where("oper_id", id).Scan(&log) + if err != nil { + g.Log().Error(err) + } + if err != nil || log == nil { + err = gerror.New("获取操作日志失败") + } + return +} + +func (s *sysOperLog) ClearOperationLog() (err error) { + _, err = g.DB().Exec("truncate " + dao.SysOperLog.Table) + if err != nil { + g.Log().Error(err) + err = gerror.New("清除失败") + } + return +} diff --git a/app/system/service/sys_post.go b/app/system/service/sys_post.go new file mode 100644 index 0000000..071c97a --- /dev/null +++ b/app/system/service/sys_post.go @@ -0,0 +1,74 @@ +package service + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/dao" + "gfast/app/system/model" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" +) + +type sysPost struct{} + +var SysPost = new(sysPost) + +func (s *sysPost) List(req *dao.SysPostSearchParams) (total, page int, list []*model.SysPost, err error) { + model := dao.SysPost.M + if req != nil { + if req.PostCode != "" { + model.Where("post_code like ?", "%"+req.PostCode+"%") + } + + if req.PostName != "" { + model.Where("post_name like ?", "%"+req.PostName+"%") + } + + if req.Status != "" { + model.Where("status", req.Status) + } + } + + total, err = model.Count() + + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + } + + if req.PageNum == 0 { + req.PageNum = 1 + } + + page = req.PageNum + + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + err = model.Page(page, req.PageSize).Order("post_sort asc,post_id asc").Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + } + return +} + +func (s *sysPost) Add(params *dao.SysPostAddParams) error { + _, err := dao.SysPost.Insert(params) + return err +} + +func (s *sysPost) GetOneById(id int64) (post *model.SysPost, err error) { + err = dao.SysPost.WherePri(id).Scan(&post) + return +} + +func (s *sysPost) Edit(params *dao.SysPostEditParams) (err error) { + _, err = dao.SysPost.FieldsEx(dao.SysPost.C.PostId, dao.SysPost.C.CreatedBy). + WherePri(params.PostId).Update(params) + return err +} + +func (s *sysPost) Delete(ids []int) error { + _, err := dao.SysPost.Where(dao.SysPost.C.PostId+" in(?)", ids).Delete() + return err +} diff --git a/app/system/service/sys_role.go b/app/system/service/sys_role.go new file mode 100644 index 0000000..f99d402 --- /dev/null +++ b/app/system/service/sys_role.go @@ -0,0 +1,334 @@ +package service + +import ( + "database/sql" + "errors" + "fmt" + "gfast/app/common/global" + comModel "gfast/app/common/model" + "gfast/app/common/service" + "gfast/app/system/dao" + "gfast/app/system/model" + "gfast/library" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/gvalid" +) + +type sysRole struct{} + +var SysRole = new(sysRole) + +func (s *sysRole) DeleteByIds(ids []int) (err error) { + tx, err := g.DB("default").Begin() //开启事务 + if err != nil { + g.Log().Error(err) + err = gerror.New("事务处理失败") + return + } + + _, err = tx.Model(model.SysRole{}).Where("id in(?)", ids).Delete() + if err != nil { + g.Log().Error(err) + tx.Rollback() + err = gerror.New("删除失败") + return + } + //删除角色的权限和管理的部门数据权限 + enforcer, e := service.Casbin.GetEnforcer() + if e != nil { + tx.Rollback() + return e + } + for _, v := range ids { + _, err = enforcer.RemoveFilteredPolicy(0, fmt.Sprintf("%d", v)) + if err != nil { + tx.Rollback() + return err + } + _, err = tx.Model(model.SysRoleDept{}).Delete("role_id", v) + if err != nil { + tx.Rollback() + return err + } + } + tx.Commit() + //清除TAG缓存 + service.Cache.New().RemoveByTag(global.SysAuthTag) + return nil +} + +func (s *sysRole) One(id int) (*model.SysRole, error) { + return dao.SysRole.Where("id = ?", id).FindOne() +} + +// GetRoleList 获取角色列表 +func (s *sysRole) GetRoleList() (list []*model.SysRole, err error) { + cache := service.Cache.New() + //从缓存获取 + iList := cache.Get(global.SysRole) + if iList != nil { + err = gconv.Struct(iList, &list) + return + } + //从数据库获取 + list, err = dao.SysRole.Order(dao.SysRole.Columns.ListOrder + " asc," + dao.SysRole.Columns.Id + " asc").All() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取角色数据失败") + } + //缓存数据 + cache.Set(global.SysRole, list, 0, global.SysAuthTag) + iList = cache.Get(global.SysRole) + return +} + +func (s *sysRole) GetRoleListSearch(req *model.SelectPageReq) (total, page int, list []*model.SysRole, err error) { + model := dao.SysRole.M + if req.RoleName != "" { + model = model.Where("name like ?", "%"+req.RoleName+"%") + } + if req.Status != "" { + model = model.Where("status", gconv.Int(req.Status)) + } + if req.BeginTime != "" { + + model = model.Where("create_time >= ? ", library.StrToTimestamp(req.BeginTime)) + } + + if req.EndTime != "" { + model = model.Where("create_time<=?", library.StrToTimestamp(req.EndTime)) + } + total, err = model.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + if req.PageNum == 0 { + req.PageNum = 1 + } + page = req.PageNum + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + err = model.Page(page, req.PageSize).Order("id asc").Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + return + } + return +} + +//获取角色关联的菜单规则 +func (s *sysRole) GetFilteredNamedPolicy(id int) ([]int, error) { + enforcer, err := service.Casbin.GetEnforcer() + if err != nil { + g.Log().Error(err) + return nil, err + } + gp := enforcer.GetFilteredNamedPolicy("p", 0, fmt.Sprintf("%d", id)) + gpSlice := make([]int, len(gp)) + for k, v := range gp { + gpSlice[k] = gconv.Int(v[1]) + } + + return gpSlice, nil +} + +func (s *sysRole) AddRolePost(m map[string]interface{}) error { + tx, err := g.DB("default").Begin() //开启事务 + + if err != nil { + return err + } + //插入角色 + insertId, err := s.AddRole(tx, m) + if err != nil { + tx.Rollback() //回滚 + return err + } + //添加角色权限 + err = s.AddRoleRule(m["menuIds"], insertId) + + if err != nil { + tx.Rollback() //回滚 + g.Log().Error(err.Error()) + return err + } + + tx.Commit() + //清除TAG缓存 + service.Cache.New().RemoveByTag(global.SysAuthTag) + return nil +} + +// AddRoleRule 添加角色权限 +func (s *sysRole) AddRoleRule(iRule interface{}, roleId int64) (err error) { + enforcer, e := service.Casbin.GetEnforcer() + if e != nil { + err = e + return + } + rule := gconv.Strings(iRule) + for _, v := range rule { + _, err = enforcer.AddPolicy(fmt.Sprintf("%d", roleId), fmt.Sprintf("%s", v), "All") + if err != nil { + break + } + } + return +} + +//插入角色 +func (s *sysRole) AddRole(tx *gdb.TX, data map[string]interface{}) (InsId int64, err error) { + if e := s.checkRoleData(data); e != nil { + err = e.(gvalid.Error).Current() + return + } + //保存角色信息 + roleMap := gdb.Map{ + "status": data["status"], + "name": data["roleName"], + "list_order": data["roleSort"], + "remark": data["remark"], + } + var res sql.Result + res, err = tx.Model(model.SysRole{}).Data(roleMap).Save() + if err != nil { + return + } + InsId, _ = res.LastInsertId() + return +} + +func (s *sysRole) checkRoleData(params map[string]interface{}) error { + rules := []string{ + "roleName@required|length:1,20#请填写角色名称|名称应在:min到:max个字符之间", + } + + e := gvalid.CheckMap(nil, params, rules) + if e != nil { + return e + } + return nil +} + +// 修改角色信息 +func (s *sysRole) EditRole(tx *gdb.TX, data map[string]interface{}) error { + if _, k := data["roleId"]; !k { + return errors.New("缺少更新条件Id") + } + + if e := s.checkRoleData(data); e != nil { + return e.(gvalid.Error).Current() + } + + //保存角色信息 + roleMap := gdb.Map{ + "id": data["roleId"], + "status": data["status"], + "name": data["roleName"], + "list_order": data["roleSort"], + "remark": data["remark"], + } + _, err := tx.Model(model.SysRole{}).Data(roleMap).Save() + if err != nil { + return err + } + return nil +} + +//修改角色的授权规则 +func (s *sysRole) EditRoleRule(iRule interface{}, roleId int64) (err error) { + enforcer, e := service.Casbin.GetEnforcer() + if e != nil { + return e + } + + //删除旧权限 + _, err = enforcer.RemoveFilteredPolicy(0, fmt.Sprintf("%d", roleId)) + if err != nil { + return + } + // 添加新权限 + rule := gconv.Strings(iRule) + for _, v := range rule { + _, err = enforcer.AddPolicy(fmt.Sprintf("%d", roleId), fmt.Sprintf("%s", v), "All") + if err != nil { + break + } + } + + return + +} + +func (s *sysRole) EditRolePost(m map[string]interface{}, id int) error { + tx, err := g.DB("default").Begin() //开启事务 + if err != nil { + return err + } + err = s.EditRole(tx, m) + if err != nil { + tx.Rollback() + return err + } + err = s.EditRoleRule(m["menuIds"], int64(id)) + if err != nil { + tx.Rollback() //回滚 + return err + } + tx.Commit() + //清除TAG缓存 + service.Cache.New().RemoveByTag(global.SysAuthTag) + return nil +} + +func (s *sysRole) StatusSetRole(req *model.StatusSetReq) error { + _, err := dao.SysRole.Where(dao.SysRole.Columns.Id, req.RoleId).Data(dao.SysRole.Columns.Status, req.Status). + Update() + if err == nil { + //清除TAG缓存 + service.Cache.New().RemoveByTag(global.SysAuthTag) + } + return err +} + +//设置角色数据权限 +func (s *sysRole) RoleDataScope(req *model.DataScopeReq) error { + tx, err := g.DB().Begin() + if err != nil { + g.Log().Error(err) + return gerror.New("设置失败") + } + _, err = tx.Model(model.SysRole{}).Where("id", req.RoleId).Data(g.Map{"data_scope": req.DataScope}).Update() + if err != nil { + g.Log().Error(err) + tx.Rollback() + return gerror.New("设置失败") + } + if req.DataScope == 2 { + _, err := tx.Model(model.SysRoleDept{}).Where("role_id", req.RoleId).Delete() + if err != nil { + g.Log().Error(err) + tx.Rollback() + return gerror.New("设置失败") + } + data := g.List{} + for _, deptId := range req.DeptIds { + data = append(data, g.Map{"role_id": req.RoleId, "dept_id": deptId}) + } + _, err = tx.Model(model.SysRoleDept{}).Data(data).Insert() + if err != nil { + g.Log().Error(err) + tx.Rollback() + return gerror.New("设置失败") + } + } + tx.Commit() + return nil +} diff --git a/app/system/service/sys_user.go b/app/system/service/sys_user.go new file mode 100644 index 0000000..c2a6d1f --- /dev/null +++ b/app/system/service/sys_user.go @@ -0,0 +1,776 @@ +package service + +import ( + "context" + "errors" + "fmt" + comModel "gfast/app/common/model" + "gfast/app/common/service" + "gfast/app/system/dao" + "gfast/app/system/model" + "gfast/library" + "github.com/gogf/gf/container/gset" + "github.com/gogf/gf/database/gdb" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/gtime" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gconv" + "github.com/gogf/gf/util/grand" + "github.com/mssola/user_agent" +) + +type sysUser struct { + NotCheckAuthAdminIds *gset.Set //无需验证权限的用户id +} + +type UserMenu struct { + *model.SysAuthRuleInfoRes + Index string `json:"index"` + Name string `json:"name"` + MenuName string `json:"menuName"` + Component string `json:"component"` + Path string `json:"path"` + Meta struct { + Icon string `json:"icon"` + Title string `json:"title"` + } `json:"meta"` + Hidden bool `json:"hidden"` + AlwaysShow bool `json:"alwaysShow"` +} + +type UserMenus struct { + UserMenu + Children []UserMenus `json:"children"` +} + +var ( + notCheckAuthAdminIds = g.Cfg().GetInterfaces("system.notCheckAuthAdminIds") + SysUser = &sysUser{ + NotCheckAuthAdminIds: gset.NewFrom(notCheckAuthAdminIds), + } +) + +// GetAdminUserByUsernamePassword 后台登陆验证 +func (s *sysUser) GetAdminUserByUsernamePassword(ctx context.Context, req *model.LoginParamsReq) (user *model.LoginUserRes, err error) { + user, err = s.GetUserByUsernamePassword(ctx, req) + if err != nil { + return + } + //判断是否后台用户 + if user.IsAdmin != 1 { + return nil, gerror.New("抱歉!您不属于后台管理员!") + } + return +} + +// GetUserByUsernamePassword 登陆验证 +func (s *sysUser) GetUserByUsernamePassword(ctx context.Context, req *model.LoginParamsReq) (user *model.LoginUserRes, err error) { + user, err = s.GetUserByUsername(ctx, req.Username) + if err != nil { + return + } + if user == nil { + return nil, gerror.New("账号密码错误") + } + //验证密码 + if library.EncryptPassword(req.Password, user.UserSalt) != user.UserPassword { + return nil, gerror.New("账号密码错误") + } + //账号状态 + if user.UserStatus == 0 { + return nil, gerror.New("账号已被冻结") + } + return +} + +// GetUserByUsername 通过用户名获取用户信息 +func (s *sysUser) GetUserByUsername(ctx context.Context, userName string) (user *model.LoginUserRes, err error) { + return dao.SysUser.FindByUsername(ctx, userName) +} + +// UpdateLoginInfo 更新用户登录信息 保存登录日志 +func (s *sysUser) UpdateLoginInfo(id uint64, username, ip, userAgent, msg, module string) { + status := 0 //登录状态 0失败 1成功 + if id != 0 { + //说明登录成功更新登录信息 + status = 1 + dao.SysUser.UpLoginInfo(id, ip) + } + //保存登录日志(异步) + SysLoginLog.Invoke(&model.LoginLogParams{ + Status: status, + Username: username, + Ip: ip, + UserAgent: userAgent, + Msg: msg, + Module: module, + }) +} + +// LoginLog 记录登录日志 +func (s *sysUser) LoginLog(params *model.LoginLogParams) { + ua := user_agent.New(params.UserAgent) + browser, _ := ua.Browser() + loginData := &model.SysLoginLog{ + LoginName: params.Username, + Ipaddr: params.Ip, + LoginLocation: library.GetCityByIp(params.Ip), + Browser: browser, + Os: ua.OS(), + Status: params.Status, + Msg: params.Msg, + LoginTime: gtime.Now(), + Module: params.Module, + } + dao.SysLoginLog.SaveLog(loginData) +} + +// SaveOnline 保存用户登录在线状态信息 +func (s *sysUser) SaveOnline(params *model.SysUserOnline) { + dao.SysUserOnline.SaveOnline(params) +} + +// GetAdminRole 获取用户角色 +func (s *sysUser) GetAdminRole(userId uint64, allRoleList []*model.SysRole) (roles []*model.SysRole, err error) { + var roleIds []uint + roleIds, err = s.GetAdminRoleIds(userId) + if err != nil { + return + } + roles = make([]*model.SysRole, 0, len(allRoleList)) + for _, v := range allRoleList { + for _, id := range roleIds { + if id == v.Id { + roles = append(roles, v) + } + } + if len(roles) == len(roleIds) { + break + } + } + return +} + +// GetAdminRoleIds 获取用户角色ids +func (s *sysUser) GetAdminRoleIds(userId uint64) (roleIds []uint, err error) { + enforcer, e := service.Casbin.GetEnforcer() + if e != nil { + err = e + return + } + //查询关联角色规则 + groupPolicy := enforcer.GetFilteredGroupingPolicy(0, gconv.String(userId)) + if len(groupPolicy) > 0 { + roleIds = make([]uint, len(groupPolicy)) + //得到角色id的切片 + for k, v := range groupPolicy { + roleIds[k] = gconv.Uint(v[1]) + } + } + return +} + +func (s *sysUser) GetPermissions(roleIds []uint) ([]string, error) { + //获取角色对应的菜单id + enforcer, err := service.Casbin.GetEnforcer() + if err != nil { + return nil, err + } + menuIds := map[int64]int64{} + for _, roleId := range roleIds { + //查询当前权限 + gp := enforcer.GetFilteredPolicy(0, gconv.String(roleId)) + for _, p := range gp { + mid := gconv.Int64(p[1]) + menuIds[mid] = mid + } + } + //获取所有开启的按钮 + allButtons, err := Rule.GetIsButtonStatusList() + userButtons := make([]string, 0, len(allButtons)) + for _, button := range allButtons { + if _, ok := menuIds[gconv.Int64(button.Id)]; gstr.Equal(button.Condition, "nocheck") || ok { + userButtons = append(userButtons, button.Name) + } + } + return userButtons, nil +} + +func (s *sysUser) GetAllMenus() (menus []UserMenus, err error) { + //获取所有开启的菜单 + var allMenus []*model.SysAuthRuleInfoRes + allMenus, err = Rule.GetMenuIsStatusList() + if err != nil { + return + } + menus = make([]UserMenus, len(allMenus)) + for k, v := range allMenus { + var menu UserMenu + menu = s.setMenuData(menu, v) + menus[k] = UserMenus{UserMenu: menu} + } + menus = s.GetMenusTree(menus, 0) + return +} + +func (s *sysUser) GetAdminMenusByRoleIds(roleIds []uint) (menus []UserMenus, err error) { + //获取角色对应的菜单id + enforcer, e := service.Casbin.GetEnforcer() + if e != nil { + err = e + return + } + menuIds := map[int64]int64{} + for _, roleId := range roleIds { + //查询当前权限 + gp := enforcer.GetFilteredPolicy(0, fmt.Sprintf("%d", roleId)) + for _, p := range gp { + mid := gconv.Int64(p[1]) + menuIds[mid] = mid + } + } + //获取所有开启的菜单 + allMenus, err := Rule.GetMenuIsStatusList() + if err != nil { + return + } + menus = make([]UserMenus, 0, len(allMenus)) + for _, v := range allMenus { + if _, ok := menuIds[gconv.Int64(v.Id)]; gstr.Equal(v.Condition, "nocheck") || ok { + var roleMenu UserMenu + roleMenu = s.setMenuData(roleMenu, v) + menus = append(menus, UserMenus{UserMenu: roleMenu}) + } + } + menus = s.GetMenusTree(menus, 0) + return +} + +func (s *sysUser) GetMenusTree(menus []UserMenus, pid uint) []UserMenus { + returnList := make([]UserMenus, 0, len(menus)) + for _, menu := range menus { + if menu.Pid == pid { + menu.Children = s.GetMenusTree(menus, menu.Id) + returnList = append(returnList, menu) + } + } + return returnList +} + +func (s *sysUser) setMenuData(menu UserMenu, entity *model.SysAuthRuleInfoRes) UserMenu { + menu = UserMenu{ + SysAuthRuleInfoRes: entity, + Index: entity.Name, + Name: gstr.UcFirst(entity.Path), + MenuName: entity.Title, + Meta: struct { + Icon string `json:"icon"` + Title string `json:"title"` + }(struct { + Icon string + Title string + }{Icon: entity.Icon, Title: entity.Title}), + } + if entity.MenuType != 0 { + menu.Component = entity.Component + menu.Path = entity.Path + } else { + menu.Component = "Layout" + menu.Path = "/" + entity.Path + } + if entity.AlwaysShow == 1 { + menu.Hidden = false + } else { + menu.Hidden = true + } + if entity.AlwaysShow == 1 && entity.MenuType == 0 { + menu.AlwaysShow = true + } else { + menu.AlwaysShow = false + } + return menu +} + +func (s *sysUser) WriteDeptIdsOfSearchReq(req *model.SysUserSearchReq) error { + if req.DeptId == "" { + return nil + } + depts, e := Dept.GetList(&dao.SysDeptSearchParams{ + Status: "1", + }) + if e != nil { + return e + } + deptId := gconv.Int64(req.DeptId) + req.DeptIds = append(req.DeptIds, deptId) + children := Dept.FindSonByParentId(depts, deptId) + for _, d := range children { + req.DeptIds = append(req.DeptIds, d.DeptId) + } + return nil +} + +// GetUsersRoleDept 获取多个用户角色 部门信息 +func (s *sysUser) GetUsersRoleDept(userList []*model.SysUser) ([]*model.SysUserRoleDeptRes, error) { + allRoles, err := SysRole.GetRoleList() + if err != nil { + g.Log().Error(err) + return nil, err + } + depts, err := Dept.GetList(&dao.SysDeptSearchParams{}) + if err != nil { + g.Log().Error(err) + return nil, err + } + users := make([]*model.SysUserRoleDeptRes, len(userList)) + for k, u := range userList { + var dept *model.SysDept + users[k] = &model.SysUserRoleDeptRes{ + SysUser: u, + } + for _, d := range depts { + if u.DeptId == uint64(d.DeptId) { + dept = d + } + } + users[k].Dept = dept + roles, err := s.GetAdminRole(u.Id, allRoles) + if err != nil { + g.Log().Error(err) + return nil, err + } + for _, r := range roles { + users[k].RoleInfo = append(users[k].RoleInfo, &struct { + RoleId uint `json:"roleId"` + Name string `json:"name"` + }{RoleId: r.Id, Name: r.Name}) + } + } + return users, nil +} + +// GetUserRoleDeptPost 获取某个用户对应的部门、岗位、角色信息 +func (s *sysUser) GetUserRoleDeptPost(user *model.SysUser) (*model.SysUserRoleDeptRes, error) { + allRoles, err := SysRole.GetRoleList() + if err != nil { + g.Log().Error(err) + return nil, err + } + //部门 + depts, err := Dept.GetList(&dao.SysDeptSearchParams{}) + if err != nil { + g.Log().Error(err) + return nil, err + } + userData := &model.SysUserRoleDeptRes{ + SysUser: user, + } + for _, d := range depts { + if user.DeptId == uint64(d.DeptId) { + userData.Dept = d + } + } + //角色 + roles, err := s.GetAdminRole(user.Id, allRoles) + if err != nil { + g.Log().Error(err) + return nil, err + } + for _, r := range roles { + userData.RoleInfo = append(userData.RoleInfo, &struct { + RoleId uint `json:"roleId"` + Name string `json:"name"` + }{RoleId: r.Id, Name: r.Name}) + } + //岗位 + posts, err := s.GetPostsByUserId(user.Id) + if err != nil { + return nil, err + } + + for _, v := range posts { + userData.Post = append(userData.Post, &struct { + PostId int64 `json:"postId"` + PostName string `json:"postName"` + }{PostId: v.PostId, PostName: v.PostName}) + } + return userData, nil +} + +func (s *sysUser) GetUserList(req *model.SysUserSearchReq) (total, page int, userList []*model.SysUser, err error) { + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + userModel := dao.SysUser.M + if req.KeyWords != "" { + keyWords := "%" + req.KeyWords + "%" + userModel = userModel.Where("user_name like ? or user_nickname like ?", keyWords, keyWords) + } + if len(req.DeptIds) != 0 { + userModel = userModel.Where("dept_id in (?)", req.DeptIds) + } + if req.Status != "" { + userModel = userModel.Where("user_status", gconv.Int(req.Status)) + } + if req.Phonenumber != "" { + userModel = userModel.Where("mobile like ?", "%"+req.Phonenumber+"%") + } + if req.BeginTime != "" { + userModel = userModel.Where("created_at >=?", req.BeginTime) + } + if req.EndTime != "" { + userModel = userModel.Where("create_time <=?", req.EndTime) + } + total, err = userModel.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + if req.PageNum == 0 { + req.PageNum = 1 + } + page = req.PageNum + err = userModel.FieldsEx(dao.SysUser.Columns.UserPassword, dao.SysUser.Columns.UserSalt). + Page(page, req.PageSize).Order("id asc").Scan(&userList) + return +} + +func (s *sysUser) AddUser(req *model.AddUserReq) (err error) { + req.UserSalt = grand.S(10) + req.Password = library.EncryptPassword(req.Password, req.UserSalt) + var tx *gdb.TX + tx, err = g.DB().Begin() + if err != nil { + err = gerror.New("事务开启失败") + return + } + Model := dao.SysUser.TX(tx) + if i, _ := Model.Where("user_name=?", req.UserName).Count(); i != 0 { + err = gerror.New("用户名已经存在") + tx.Rollback() + return + } + if i, _ := Model.Where("mobile=?", req.Phonenumber).Count(); i != 0 { + err = gerror.New("手机号已经存在") + tx.Rollback() + return + } + userData := new(model.SysUser) + userData.UserName = req.UserName + userData.DeptId = req.DeptId + userData.UserStatus = req.Status + userData.Mobile = req.Phonenumber + userData.Sex = req.Sex + userData.UserEmail = req.Email + userData.UserNickname = req.NickName + userData.UserSalt = req.UserSalt + userData.UserPassword = req.Password + userData.Remark = req.Remark + userData.IsAdmin = req.IsAdmin + res, err := Model.Insert(userData) + if err != nil { + tx.Rollback() + return + } + InsertId, _ := res.LastInsertId() + err = s.AddUserRole(req.RoleIds, InsertId) + if err != nil { + g.Log().Error(err) + err = gerror.New("设置用户权限失败") + tx.Rollback() + return + } + err = s.AddUserPost(req.PostIds, InsertId, tx) + if err != nil { + g.Log().Error(err) + err = gerror.New("设置用户岗位信息失败") + tx.Rollback() + return + } + tx.Commit() + return +} + +// AddUserRole 添加用户角色信息 +func (s *sysUser) AddUserRole(roleIds interface{}, userId int64) (err error) { + enforcer, e := service.Casbin.GetEnforcer() + if e != nil { + err = e + return + } + rule := gconv.Ints(roleIds) + for _, v := range rule { + _, err = enforcer.AddGroupingPolicy(fmt.Sprintf("%d", userId), fmt.Sprintf("%d", v)) + if err != nil { + return + } + } + return +} + +// AddUserPost 添加用户岗位信息 +func (s *sysUser) AddUserPost(postIds []int64, userId int64, tx *gdb.TX) (err error) { + if err != nil { + g.Log().Error(err) + return gerror.New("用户岗位设置失败") + } + //删除旧岗位信息 + _, err = dao.SysUserPost.TX(tx).Where(dao.SysUserPost.Columns.UserId, userId).Delete() + if err != nil { + g.Log().Error(err) + return + } + //添加用户岗位信息 + data := g.List{} + for _, v := range postIds { + data = append(data, g.Map{ + dao.SysUserPost.Columns.UserId: userId, + dao.SysUserPost.Columns.PostId: v, + }) + } + _, err = dao.SysUserPost.TX(tx).Data(data).Insert() + if err != nil { + g.Log().Error(err) + return + } + return +} + +// GetUserInfoById 通过Id获取用户信息 +func (s *sysUser) GetUserInfoById(id uint64, withPwd ...bool) (user *model.SysUser, err error) { + if len(withPwd) > 0 && withPwd[0] { + //用户用户信息 + err = dao.SysUser.Where(dao.SysUser.Columns.Id, id).Scan(&user) + } else { + //用户用户信息 + err = dao.SysUser.Where(dao.SysUser.Columns.Id, id). + FieldsEx(dao.SysUser.Columns.UserPassword, dao.SysUser.Columns.UserSalt).Scan(&user) + } + if err != nil { + g.Log().Error(err) + return nil, errors.New("获取用户数据失败") + } + return +} + +// GetEditUser 获取要修改的用户信息 +func (s *sysUser) GetEditUser(id uint64) (g.Map, error) { + userData, err := s.GetUserInfoById(id) + //获取角色信息 + roleList, err := SysRole.GetRoleList() + if err != nil { + g.Log().Error(err) + return nil, errors.New("获取角色数据失败") + } + //获取已选择的角色信息 + checkedRoleIds, err := SysUser.GetAdminRoleIds(id) + if err != nil { + g.Log().Error(err) + return nil, errors.New("获取用户角色数据失败") + } + if checkedRoleIds == nil { + checkedRoleIds = []uint{} + } + //获取岗位信息 + posts, err := s.GetUsedPost() + if err != nil { + return nil, err + } + checkedPosts, err := s.GetUserPostIds(id) + if err != nil { + return nil, err + } + + if checkedPosts == nil { + checkedPosts = []int64{} + } + + res := g.Map{ + "roleList": roleList, + "userInfo": userData, + "checkedRoleIds": checkedRoleIds, + "posts": posts, + "checkedPosts": checkedPosts, + } + + return res, nil +} + +// GetUsedPost 获取正常状态的岗位 +func (s *sysUser) GetUsedPost() (list []*model.SysPost, err error) { + err = dao.SysPost.Where(dao.SysPost.C.Status, 1). + Order(dao.SysPost.C.PostSort + " ASC, " + dao.SysPost.C.PostId + " ASC ").Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取岗位数据失败") + } + return +} + +// GetUserPostIds 获取用户岗位 +func (s *sysUser) GetUserPostIds(userId uint64) (postIds []int64, err error) { + var list []*model.SysUserPost + err = dao.SysUserPost.Where(dao.SysUserPost.Columns.UserId, userId).Scan(&list) + if err != nil { + g.Log().Error(err) + return nil, gerror.New("获取用户岗位信息失败") + } + postIds = make([]int64, 0) + for _, entity := range list { + postIds = append(postIds, entity.PostId) + } + return +} + +// GetPostsByUserId 根据用户id获取岗位信息详情 +func (s *sysUser) GetPostsByUserId(userId uint64) ([]*model.SysPost, error) { + postIds, err := s.GetUserPostIds(userId) + if err != nil { + return nil, err + } + var posts []*model.SysPost + err = dao.SysPost.Where(dao.SysPost.C.PostId+" in (?)", postIds).Scan(&posts) + return posts, err +} + +// EditUser 修改用户 +func (s *sysUser) EditUser(req *model.EditUserReq) (err error) { + if i, _ := dao.SysUser.Where("id!=? and mobile=?", req.UserId, req.Phonenumber).Count(); i != 0 { + err = gerror.New("手机号已经存在") + return + } + var tx *gdb.TX + tx, err = g.DB().Begin() + //保存管理员信息 + var userData *model.SysUser + err = dao.SysUser.Where("id", req.UserId).Scan(&userData) + if err != nil || userData == nil { + g.Log().Error(err) + err = gerror.New("获取用户信息失败") + return + } + userData.DeptId = req.DeptId + userData.UserStatus = req.Status + userData.Mobile = req.Phonenumber + userData.Sex = req.Sex + userData.UserEmail = req.Email + userData.UserNickname = req.NickName + userData.Remark = req.Remark + userData.IsAdmin = req.IsAdmin + _, err = dao.SysUser.TX(tx).FieldsEx(dao.SysUser.Columns.Id, dao.SysUser.Columns.CreatedAt, + dao.SysUser.Columns.DeletedAt, dao.SysUser.Columns.LastLoginTime). + WherePri(userData.Id).Update(userData) + if err != nil { + g.Log().Error(err) + err = gerror.New("修改用户信息失败") + tx.Rollback() + return + } + //设置用户所属角色信息 + err = s.EditUserRole(req.RoleIds, req.UserId) + if err != nil { + g.Log().Error(err) + err = gerror.New("设置用户权限失败") + tx.Rollback() + return + } + //设置用户岗位数据 + err = s.AddUserPost(req.PostIds, gconv.Int64(req.UserId), tx) + if err != nil { + g.Log().Error(err) + err = gerror.New("设置用户岗位信息失败") + tx.Rollback() + return + } + tx.Commit() + return +} + +// EditUserRole 修改用户角色信息 +func (s *sysUser) EditUserRole(roleIds interface{}, userId int) (err error) { + enforcer, e := service.Casbin.GetEnforcer() + if e != nil { + err = e + return + } + rule := gconv.Ints(roleIds) + //删除用户旧角色信息 + enforcer.RemoveFilteredGroupingPolicy(0, fmt.Sprintf("%d", userId)) + for _, v := range rule { + _, err = enforcer.AddGroupingPolicy(fmt.Sprintf("%d", userId), fmt.Sprintf("%d", v)) + if err != nil { + return + } + } + return +} + +// ResetUserPwd 重置用户密码 +func (s *sysUser) ResetUserPwd(req *model.SysUserResetPwdReq) error { + salt := grand.S(10) + password := library.EncryptPassword(req.Password, salt) + _, err := dao.SysUser.WherePri(req.Id).Update(g.Map{ + dao.SysUser.Columns.UserSalt: salt, + dao.SysUser.Columns.UserPassword: password, + }) + return err +} + +func (s *sysUser) ChangeUserStatus(req *model.SysUserStatusReq) error { + _, err := dao.SysUser.WherePri(req.Id).Update(g.Map{ + dao.SysUser.Columns.UserStatus: req.UserStatus, + }) + return err +} + +// DeleteUser 删除用户信息 +func (s *sysUser) DeleteUser(ctx context.Context, ids []int) error { + return g.DB().Transaction(ctx, func(ctx context.Context, tx *gdb.TX) error { + _, err := dao.SysUser.Ctx(ctx).TX(tx).Where(dao.SysUser.Columns.Id+" in(?)", ids).Delete() + //删除对应权限 + enforcer, err := service.Casbin.GetEnforcer() + if err == nil { + for _, v := range ids { + enforcer.RemoveFilteredGroupingPolicy(0, fmt.Sprintf("%d", v)) + } + } + //删除用户对应的岗位 + _, err = dao.SysUserPost.Ctx(ctx).TX(tx).Delete(dao.SysUserPost.Columns.UserId+" in (?)", ids) + return err + }) +} + +// SetAvatar 修改用户头像 +func (s *sysUser) SetAvatar(userId uint64, avatarUrl string) error { + _, err := dao.SysUser.WherePri(userId).Unscoped().Update(g.Map{ + dao.SysUser.Columns.Avatar: avatarUrl, + }) + return err +} + +// ProfileEdit 修改个人资料 +func (s *sysUser) ProfileEdit(req *model.ProfileUpReq) error { + _, err := dao.SysUser.WherePri(req.UserId).Unscoped().Update(req) + return err +} + +// ProfileUpdatePwd 修改个人密码 +func (s *sysUser) ProfileUpdatePwd(req *model.ProfileUpdatePwdReq) error { + userInfo, err := s.GetUserInfoById(req.UserId, true) + if err != nil { + return err + } + oldPassword := library.EncryptPassword(req.OldPassword, userInfo.UserSalt) + if oldPassword != userInfo.UserPassword { + return errors.New("原始密码错误!") + } + salt := grand.S(10) + newPassword := library.EncryptPassword(req.NewPassword, salt) + _, err = dao.SysUser.WherePri(req.UserId).Unscoped().Update(g.Map{ + dao.SysUser.Columns.UserSalt: salt, + dao.SysUser.Columns.UserPassword: newPassword, + }) + return err +} diff --git a/app/system/service/sys_user_online.go b/app/system/service/sys_user_online.go new file mode 100644 index 0000000..9d589f1 --- /dev/null +++ b/app/system/service/sys_user_online.go @@ -0,0 +1,92 @@ +/* +* @desc:在线用户管理 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/3/18 14:45 + */ + +package service + +import ( + comModel "gfast/app/common/model" + "gfast/app/system/dao" + "gfast/app/system/model" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/grpool" +) + +type online struct { + Pool *grpool.Pool +} + +var ( + Online = &online{ + Pool: grpool.New(100), + } +) + +func (s *online) Invoke(data *model.SysUserOnline) { + s.Pool.Add(func() { + //写入数据 + SysUser.SaveOnline(data) + }) +} + +// DeleteOnlineByToken 删除用户在线状态操作 +func (s *online) DeleteOnlineByToken(token string) { + _, err := dao.SysUserOnline.Delete(dao.SysUserOnline.Columns.Token, token) + if err != nil { + g.Log().Error(err) + } +} + +// GetOnlineListPage 搜素在线用户列表 +func (s *online) GetOnlineListPage(req *model.SysUserOnlineSearchReq, hasToken ...bool) (total, page int, list []*model.SysUserOnline, err error) { + if req.PageNum == 0 { + req.PageNum = 1 + } + if req.PageSize == 0 { + req.PageSize = comModel.PageSize + } + model := dao.SysUserOnline.M + if req.Ip != "" { + model = model.Where("ip like ?", "%"+req.Ip+"%") + } + if req.Username != "" { + model = model.Where("user_name like ?", "%"+req.Username+"%") + } + total, err = model.Count() + if err != nil { + g.Log().Error(err) + err = gerror.New("获取总行数失败") + return + } + if len(hasToken) == 0 || !hasToken[0] { + model = model.FieldsEx("token") + } + err = model.Page(page, req.PageSize).Order("create_time DESC").Scan(&list) + if err != nil { + g.Log().Error(err) + err = gerror.New("获取数据失败") + } + return +} + +func (s *online) ForceLogout(ids []int) (tokens []string, err error) { + var onlineList []*model.SysUserOnline + onlineList, err = s.GetInfosByIds(ids) + if err != nil { + return + } + for _, v := range onlineList { + tokens = append(tokens, v.Token) + } + _, err = dao.SysUserOnline.Where(dao.SysUserOnline.Columns.Id+" in(?)", ids).Delete() + return +} + +func (s *online) GetInfosByIds(ids []int) (onlineList []*model.SysUserOnline, err error) { + err = dao.SysUserOnline.Where(dao.SysUserOnline.Columns.Id+" in(?)", ids).Scan(&onlineList) + return +} diff --git a/app/system/service/sys_web_set.go b/app/system/service/sys_web_set.go new file mode 100644 index 0000000..a4ff058 --- /dev/null +++ b/app/system/service/sys_web_set.go @@ -0,0 +1,45 @@ +/* +* @desc:站点配置 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/6 15:48 + */ + +package service + +import ( + "gfast/app/common/global" + commonService "gfast/app/common/service" + "gfast/app/system/dao" + "gfast/app/system/model" + "github.com/gogf/gf/util/gconv" +) + +type sysWebSet struct { +} + +var SysWebSet = new(sysWebSet) + +func (s *sysWebSet) Get() (data *model.SysWebSet, err error) { + cache := commonService.Cache.New() + d := cache.Get(global.SysWebSet) + if d != nil { + err = gconv.Struct(d, &data) + return + } + err = dao.SysWebSet.Page(1, 1).Scan(&data) + if err != nil { + return + } + cache.Set(global.SysWebSet, data, 0) + return +} + +func (s *sysWebSet) UpdateSave(req *model.SysWebSetUpdateReq) (err error) { + if req.WebId != 0 { + _, err = dao.SysWebSet.FieldsEx(dao.SysWebSet.C.WebId).WherePri(req.WebId).Update(req) + } else { + _, err = dao.SysWebSet.FieldsEx(dao.SysWebSet.C.WebId).Insert(req) + } + return +} diff --git a/app/system/service/time_task.go b/app/system/service/time_task.go new file mode 100644 index 0000000..74f899d --- /dev/null +++ b/app/system/service/time_task.go @@ -0,0 +1,58 @@ +/* +* @desc:定时任务栈 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/16 17:10 + */ + +package service + +import "github.com/gogf/gf/os/gmutex" + +var TimeTaskList = &taskList{ + mu: gmutex.New(), +} + +type TimeTask struct { + FuncName string + Param []string + Run func() +} + +type taskList struct { + taskList []*TimeTask + mu *gmutex.Mutex +} + +// AddTask 添加任务 +func (s *taskList) AddTask(task *TimeTask) *taskList { + if task.FuncName == "" || task.Run == nil { + return s + } + s.taskList = append(s.taskList, task) + return s +} + +// GetByName 通过方法名获取对应task信息 +func (s *taskList) GetByName(funcName string) *TimeTask { + var result *TimeTask + for _, item := range s.taskList { + if item.FuncName == funcName { + result = item + break + } + } + return result +} + +// EditParams 修改参数 +func (s *taskList) EditParams(funcName string, params []string) { + s.mu.Lock() + defer s.mu.Unlock() + for _, item := range s.taskList { + if item.FuncName == funcName { + item.Param = params + break + } + } +} diff --git a/boot/.gitkeep b/boot/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/boot/boot.go b/boot/boot.go new file mode 100644 index 0000000..1665bab --- /dev/null +++ b/boot/boot.go @@ -0,0 +1,24 @@ +package boot + +import ( + "fmt" + _ "gfast/packed" + _ "gfast/task" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/os/glog" + "github.com/gogf/gf/os/gtime" +) + +//版本号 +const Version = "2.0.0" + +func init() { + gtime.SetTimeZone("Asia/Shanghai") //设置系统时区 + showLogo() + g.Log().SetFlags(glog.F_ASYNC | glog.F_TIME_DATE | glog.F_TIME_TIME | glog.F_FILE_LONG) +} + +func showLogo() { + fmt.Println(" .----------------. .----------------. .----------------. .----------------. .----------------. \n| .--------------. || .--------------. || .--------------. || .--------------. || .--------------. |\n| | ______ | || | _________ | || | __ | || | _______ | || | _________ | |\n| | .' ___ | | || | |_ ___ | | || | / \\ | || | / ___ | | || | | _ _ | | |\n| | / .' \\_| | || | | |_ \\_| | || | / /\\ \\ | || | | (__ \\_| | || | |_/ | | \\_| | |\n| | | | ____ | || | | _| | || | / ____ \\ | || | '.___`-. | || | | | | |\n| | \\ `.___] _| | || | _| |_ | || | _/ / \\ \\_ | || | |`\\____) | | || | _| |_ | |\n| | `._____.' | || | |_____| | || ||____| |____|| || | |_______.' | || | |_____| | |\n| | | || | | || | | || | | || | | |\n| '--------------' || '--------------' || '--------------' || '--------------' || '--------------' |\n '----------------' '----------------' '----------------' '----------------' '----------------' ") + fmt.Println("当前版本:", Version) +} diff --git a/config/.gitkeep b/config/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/config/casbin_conf/rbac_model.conf b/config/casbin_conf/rbac_model.conf new file mode 100644 index 0000000..71159e3 --- /dev/null +++ b/config/casbin_conf/rbac_model.conf @@ -0,0 +1,14 @@ +[request_definition] +r = sub, obj, act + +[policy_definition] +p = sub, obj, act + +[role_definition] +g = _, _ + +[policy_effect] +e = some(where (p.eft == allow)) + +[matchers] +m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act \ No newline at end of file diff --git a/config/casbin_conf/rbac_policy.csv b/config/casbin_conf/rbac_policy.csv new file mode 100644 index 0000000..f93d6df --- /dev/null +++ b/config/casbin_conf/rbac_policy.csv @@ -0,0 +1,5 @@ +p, alice, data1, read +p, bob, data2, write +p, data2_admin, data2, read +p, data2_admin, data2, write +g, alice, data2_admin \ No newline at end of file diff --git a/config/config.toml b/config/config.toml new file mode 100644 index 0000000..a9acb44 --- /dev/null +++ b/config/config.toml @@ -0,0 +1,68 @@ +# HTTP Server +[server] + Address = ":8199" + ServerRoot = "./public/resource" + ServerAgent = "gfast-app" + LogPath = "./data/log/gf-app/server" + logStdout = true # 日志是否输出到终端。默认为true + errorStack = true # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true + errorLogPattern = "error-{Ymd}.log" # 异常错误日志文件格式。默认为"error-{Ymd}.log" + accessLogPattern = "access-{Ymd}.log" # 访问日志文件格式。默认为"access-{Ymd}.log" + DumpRouterMap = true + NameToUriType = 3 + maxHeaderBytes = "20KB" + clientMaxBodySize = "200MB" + accessLogEnabled = true # 是否记录访问日志。默认为false + errorLogEnabled = true # 是否记录异常日志信息到日志中。默认为true + PProfEnabled = true # 是否开启PProf性能调试特性。默认为false + +# Logger. +[logger] + Path = "./data/log/gf-app" + Level = "all" + Stdout = true + +# Template. +[viewer] + Path = "template" + DefaultFile = "index.html" + Delimiters = ["${", "}"] + +# Database. +[database] + link = "mysql:root:123456@tcp(localhost:3306)/gfast-v2-open" + charset = "utf8mb4" #数据库编码 + debug = true + dryRun = false #空跑 + maxIdle = "10" #连接池最大闲置的连接数 + maxOpen = "10" #连接池最大打开的连接数 + maxLifetime = "30" #(单位秒)连接对象可重复使用的时间长度 + # Database logger. + [database.logger] + Path = "./data/log/gf-app/sql" + Level = "all" + Stdout = true + +# Redis数据库配置 +[redis] + open = true #是否开启 redis 缓存 若不开启使用gchache缓存方式 + default = "127.0.0.1:6379,0?idleTimeout=600" + +#jwt配置 +[gToken] + [gToken.system] + CacheMode = 2 + CacheKey = "GToken:" + Timeout = 3600000 #1个小时 + MaxRefresh = 0 + TokenDelimiter="_" + EncryptKey = "koi29a83idakguqjq29asd9asd8a7jhq" + AuthFailMsg = "登录超时,请重新登录" + MultiLogin = true #后台是否允许多端同时在线 +[system] + notCheckAuthAdminIds = [1,2,31] #无需验证后台权限的用户id + +#casbin配置 +[casbin] + modelFile="./config/casbin_conf/rbac_model.conf" + policyFile="./config/casbin_conf/rbac_policy.csv" \ No newline at end of file diff --git a/docker/.gitkeep b/docker/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/document/.gitkeep b/document/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..76ae1c7 --- /dev/null +++ b/go.mod @@ -0,0 +1,26 @@ +module gfast + +require ( + github.com/StackExchange/wmi v1.2.0 // indirect + github.com/casbin/casbin/v2 v2.31.9 + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-ole/go-ole v1.2.5 // indirect + github.com/goflyfox/gtoken v1.4.2 + github.com/gogf/gcache-adapter v0.1.2 + github.com/gogf/gf v1.16.4 + github.com/google/go-querystring v1.1.0 // indirect + github.com/gorilla/websocket v1.4.2 // indirect + github.com/kr/text v0.2.0 // indirect + github.com/mojocn/base64Captcha v1.3.1 + github.com/mozillazg/go-httpheader v0.3.0 // indirect + github.com/mssola/user_agent v0.5.1 + github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect + github.com/shirou/gopsutil v3.21.6+incompatible + github.com/tencentyun/cos-go-sdk-v5 v0.7.27 + github.com/tklauser/go-sysconf v0.3.7 // indirect + golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb // indirect + golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d // indirect + gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect +) + +go 1.16 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..5615590 --- /dev/null +++ b/go.sum @@ -0,0 +1,130 @@ +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible h1:1G1pk05UrOh0NlF1oeaaix1x8XzrfjIDK47TY0Zehcw= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/QcloudApi/qcloud_sign_golang v0.0.0-20141224014652-e4130a326409/go.mod h1:1pk82RBxDY/JZnPQrtqHlUFfCctgdorsd9M06fMynOM= +github.com/StackExchange/wmi v1.2.0 h1:noJEYkMQVlFCEAc+2ma5YyRhlfjcWfZqk5sBRYozdyM= +github.com/StackExchange/wmi v1.2.0/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= +github.com/casbin/casbin/v2 v2.31.9 h1:UocnnFb2KEmYmtgQw8anFN5y9VIU3GvR5xiXzni7sFk= +github.com/casbin/casbin/v2 v2.31.9/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg= +github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28 h1:LdXxtjzvZYhhUaonAaAKArG3pyC67kGL3YY+6hGG8G4= +github.com/clbanning/mxj v1.8.5-0.20200714211355-ff02cfb8ea28/go.mod h1:BVjHeAH+rl9rs6f+QIpeRl0tfu10SXn1pUSa5PVGJng= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= +github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= +github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/goflyfox/gtoken v1.4.2 h1:hC4JGYCTIE1KTm3H7m52ZkYgNK+uN94rU7D2c3R6t0E= +github.com/goflyfox/gtoken v1.4.2/go.mod h1:RpR8B4zXse/yzMpUn5Ck+Qi2FHICTS5SbEqZveiKJMc= +github.com/gogf/gcache-adapter v0.1.2 h1:m/be20UC3tbQqIKu9VOWmE21z1CztvjLYbcqxnPrsVU= +github.com/gogf/gcache-adapter v0.1.2/go.mod h1:LGkbo4Jp+23kEuPWiagDs+bpg93n1EZls82LCzKohaI= +github.com/gogf/gf v1.15.3/go.mod h1:K3FG9L4JBUeNLxQR/jCzDgB9+G9sayn49uQwx2zAn4A= +github.com/gogf/gf v1.16.4 h1:1Y8/P1UMp9BmrtUn0wAg3g6ElRAO0R9QHCdUNt9Z5L4= +github.com/gogf/gf v1.16.4/go.mod h1:EjnxZXddTwfFoLPofDE3NokFWx+immofINtSyFCj280= +github.com/gogf/mysql v1.6.1-0.20210603073548-16164ae25579 h1:pP/uEy52biKDytlgK/ug8kiYPAiYu6KajKVUHfGrtyw= +github.com/gogf/mysql v1.6.1-0.20210603073548-16164ae25579/go.mod h1:52e6mXyNnHAsFrXrSnj5JPRSKsZKpHylVtA3j4AtMz8= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g= +github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= +github.com/golang/mock v1.4.4 h1:l75CXGRSwbaYNpl/Z2X1XIIAMSCquvXgpVZDhwEIJsc= +github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= +github.com/gomodule/redigo v2.0.0+incompatible h1:K/R+8tc58AaqLkqG2Ol3Qk+DR/TlNuhuh457pBFPtt0= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf h1:wIOAyJMMen0ELGiFzlmqxdcV1yGbkyHBAB6PolcNbLA= +github.com/grokify/html-strip-tags-go v0.0.0-20190921062105-daaa06bf1aaf/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-runewidth v0.0.10 h1:CoZ3S2P7pvtP45xOtBw+/mDL2z0RKI576gSkzRRpdGg= +github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= +github.com/mojocn/base64Captcha v1.3.1 h1:2Wbkt8Oc8qjmNJ5GyOfSo4tgVQPsbKMftqASnq8GlT0= +github.com/mojocn/base64Captcha v1.3.1/go.mod h1:wAQCKEc5bDujxKRmbT6/vTnTt5CjStQ8bRfPWUuz/iY= +github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60= +github.com/mozillazg/go-httpheader v0.3.0 h1:3brX5z8HTH+0RrNA1362Rc3HsaxyWEKtGY45YrhuINM= +github.com/mozillazg/go-httpheader v0.3.0/go.mod h1:PuT8h0pw6efvp8ZeUec1Rs7dwjK08bt6gKSReGMqtdA= +github.com/mssola/user_agent v0.5.1 h1:sJUCUozh+j7c0dR2zMIUX5aJjoY/TNo/gXiNujoH5oY= +github.com/mssola/user_agent v0.5.1/go.mod h1:TTPno8LPY3wAIEKRpAtkdMT0f8SE24pLRGPahjCH4uw= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/olekukonko/tablewriter v0.0.1/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= +github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.1.0 h1:+2KBaVoUmb9XzDsrx/Ct0W/EYOSFf/nWTauy++DprtY= +github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/shirou/gopsutil v3.21.6+incompatible h1:mmZtAlWSd8U2HeRTjswbnDLPxqsEoK01NK+GZ1P+nEM= +github.com/shirou/gopsutil v3.21.6+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y= +github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4= +github.com/tencentyun/cos-go-sdk-v5 v0.7.27 h1:rLlBZyC13xvDcaW/uNK68aSqtMktlFlXqAq2qNULg7E= +github.com/tencentyun/cos-go-sdk-v5 v0.7.27/go.mod h1:4E4+bQ2gBVJcgEC9Cufwylio4mXOct2iu05WjgEBx1o= +github.com/tklauser/go-sysconf v0.3.7 h1:HT7h4+536gjqeq1ZIJPgOl1rg1XFatQGVZWp7Py53eg= +github.com/tklauser/go-sysconf v0.3.7/go.mod h1:JZIdXh4RmBvZDBZ41ld2bGxRV3n4daiiqA3skYhAoQ4= +github.com/tklauser/numcpus v0.2.3 h1:nQ0QYpiritP6ViFhrKYsiv6VVxOpum2Gks5GhnJbS/8= +github.com/tklauser/numcpus v0.2.3/go.mod h1:vpEPS/JC+oZGGQ/My/vJnNsvMDQL6PwOqt8dsCw5j+E= +go.opentelemetry.io/otel v0.16.0/go.mod h1:e4GKElweB8W2gWUqbghw0B8t5MCTccc9212eNHnOHwA= +go.opentelemetry.io/otel v0.19.0 h1:Lenfy7QHRXPZVsw/12CWpxX6d/JkrX8wrx2vO8G80Ng= +go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg= +go.opentelemetry.io/otel/metric v0.19.0 h1:dtZ1Ju44gkJkYvo+3qGqVXmf88tc+a42edOywypengg= +go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc= +go.opentelemetry.io/otel/oteltest v0.19.0 h1:YVfA0ByROYqTwOxqHVZYZExzEpfZor+MU1rU+ip2v9Q= +go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA= +go.opentelemetry.io/otel/trace v0.19.0 h1:1ucYlenXIDA1OlHVLDZKX0ObXV5RLaq06DtUKz5e5zc= +go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb h1:fqpd0EBDzlHRCjiphRR5Zo/RSWWQlWv34418dnEixWk= +golang.org/x/image v0.0.0-20210220032944-ac19c3e999fb/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d h1:BgJvlyh+UqCUaPlscHJ+PN8GcpfrFdr7NHjd1JL0+Gs= +golang.org/x/net v0.0.0-20210415231046-e915ea6b2b7d/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c h1:F1jZWGFhYfh0Ci55sIpILtKKK8p3i2/krTr0H1rg74I= +golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/i18n/.gitkeep b/i18n/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/library/response.go b/library/response.go new file mode 100644 index 0000000..160a8af --- /dev/null +++ b/library/response.go @@ -0,0 +1,123 @@ +package library + +import ( + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/gview" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gconv" +) + +const ( + SuccessCode int = 0 + ErrorCode int = -1 +) + +type Response struct { + // 代码 + Code int `json:"code" example:"200"` + // 数据集 + Data interface{} `json:"data"` + // 消息 + Msg string `json:"msg"` +} + +var response = new(Response) + +func JsonExit(r *ghttp.Request, code int, msg string, data ...interface{}) { + response.JsonExit(r, code, msg, data...) +} + +func RJson(r *ghttp.Request, code int, msg string, data ...interface{}) { + response.RJson(r, code, msg, data...) +} + +func SusJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) { + response.SusJson(isExit, r, msg, data...) +} + +func FailJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) { + response.FailJson(isExit, r, msg, data...) +} + +func WriteTpl(r *ghttp.Request, tpl string, view *gview.View, params ...gview.Params) error { + return response.WriteTpl(r, tpl, view, params...) +} + +// 返回JSON数据并退出当前HTTP执行函数。 +func (res *Response) JsonExit(r *ghttp.Request, code int, msg string, data ...interface{}) { + res.RJson(r, code, msg, data...) + r.Exit() +} + +// 标准返回结果数据结构封装。 +// 返回固定数据结构的JSON: +// code: 状态码(200:成功,302跳转,和http请求状态码一至); +// msg: 请求结果信息; +// data: 请求结果,根据不同接口返回结果的数据结构不同; +func (res *Response) RJson(r *ghttp.Request, code int, msg string, data ...interface{}) { + responseData := interface{}(nil) + if len(data) > 0 { + responseData = data[0] + } + response = &Response{ + Code: code, + Msg: msg, + Data: responseData, + } + r.SetParam("apiReturnRes", response) + r.Response.WriteJson(response) +} + +//成功返回JSON +func (res *Response) SusJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) { + if isExit { + res.JsonExit(r, SuccessCode, msg, data...) + } + res.RJson(r, SuccessCode, msg, data...) +} + +//失败返回JSON +func (res *Response) FailJson(isExit bool, r *ghttp.Request, msg string, data ...interface{}) { + if isExit { + res.JsonExit(r, ErrorCode, msg, data...) + } + res.RJson(r, ErrorCode, msg, data...) +} + +//模板输出 +func (res *Response) WriteTpl(r *ghttp.Request, tpl string, view *gview.View, params ...gview.Params) error { + //绑定模板中需要用到的方法 + view.BindFuncMap(g.Map{ + // 根据长度i来切割字符串 + "subStr": func(str interface{}, i int) (s string) { + s1 := gconv.String(str) + if gstr.LenRune(s1) > i { + s = gstr.SubStrRune(s1, 0, i) + "..." + return s + } + return s1 + }, + // 格式化时间戳 年月日 + "timeFormatYear": func(time interface{}) string { + return TimeStampToDate(gconv.Int64(time)) + }, + // 格式化时间戳 年月日时分秒 + "timeFormatDateTime": func(time interface{}) string { + return TimeStampToDateTime(gconv.Int64(time)) + }, + "add": func(a, b interface{}) int { + return gconv.Int(a) + gconv.Int(b) + }, + }) + //设置全局变量 + domain, _ := GetDomain(r) + view.Assigns(g.Map{ + "domain": domain, + }) + return r.Response.WriteTpl(tpl, params...) +} + +func (res *Response) Redirect(r *ghttp.Request, location string, code ...int) { + r.Response.RedirectTo(location, code...) +} diff --git a/library/utils.go b/library/utils.go new file mode 100644 index 0000000..f477bce --- /dev/null +++ b/library/utils.go @@ -0,0 +1,108 @@ +package library + +import ( + "fmt" + "github.com/gogf/gf/crypto/gmd5" + "github.com/gogf/gf/encoding/gcharset" + "github.com/gogf/gf/encoding/gjson" + "github.com/gogf/gf/encoding/gurl" + "github.com/gogf/gf/errors/gerror" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/os/gtime" + "net" +) + +//密码加密 +func EncryptPassword(password, salt string) string { + return gmd5.MustEncryptString(gmd5.MustEncryptString(password) + gmd5.MustEncryptString(salt)) +} + +//时间戳转 yyyy-MM-dd HH:mm:ss +func TimeStampToDateTime(timeStamp int64) string { + tm := gtime.NewFromTimeStamp(timeStamp) + return tm.Format("Y-m-d H:i:s") +} + +//时间戳转 yyyy-MM-dd +func TimeStampToDate(timeStamp int64) string { + tm := gtime.NewFromTimeStamp(timeStamp) + return tm.Format("Y-m-d") +} + +//获取当前请求接口域名 +func GetDomain(r *ghttp.Request) (string, error) { + pathInfo, err := gurl.ParseURL(r.GetUrl(), -1) + if err != nil { + g.Log().Error(err) + err = gerror.New("解析附件路径失败") + return "", err + } + return fmt.Sprintf("%s://%s:%s/", pathInfo["scheme"], pathInfo["host"], pathInfo["port"]), nil +} + +//获取客户端IP +func GetClientIp(r *ghttp.Request) string { + ip := r.Header.Get("X-Forwarded-For") + if ip == "" { + ip = r.GetClientIp() + } + return ip +} + +//服务端ip +func GetLocalIP() (ip string, err error) { + addrs, err := net.InterfaceAddrs() + if err != nil { + return + } + for _, addr := range addrs { + ipAddr, ok := addr.(*net.IPNet) + if !ok { + continue + } + if ipAddr.IP.IsLoopback() { + continue + } + if !ipAddr.IP.IsGlobalUnicast() { + continue + } + return ipAddr.IP.String(), nil + } + return +} + +//获取ip所属城市 +func GetCityByIp(ip string) string { + if ip == "" { + return "" + } + if ip == "[::1]" || ip == "127.0.0.1" { + return "内网IP" + } + url := "http://whois.pconline.com.cn/ipJson.jsp?json=true&ip=" + ip + bytes := g.Client().GetBytes(url) + src := string(bytes) + srcCharset := "GBK" + tmp, _ := gcharset.ToUTF8(srcCharset, src) + json, err := gjson.DecodeToJson(tmp) + if err != nil { + return "" + } + if json.GetInt("code") == 0 { + city := fmt.Sprintf("%s %s", json.GetString("pro"), json.GetString("city")) + return city + } else { + return "" + } +} + +//日期字符串转时间戳(秒) +func StrToTimestamp(dateStr string) int64 { + tm, err := gtime.StrToTime(dateStr) + if err != nil { + g.Log().Error(err) + return 0 + } + return tm.Timestamp() +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..f8045cb --- /dev/null +++ b/main.go @@ -0,0 +1,11 @@ +package main + +import ( + _ "gfast/boot" + _ "gfast/router" + "github.com/gogf/gf/frame/g" +) + +func main() { + g.Server().Run() +} diff --git a/middleware/auth.go b/middleware/auth.go new file mode 100644 index 0000000..f4a3cfa --- /dev/null +++ b/middleware/auth.go @@ -0,0 +1,127 @@ +package middleware + +import ( + comService "gfast/app/common/service" + "gfast/app/system/api" + "gfast/app/system/dao" + "gfast/app/system/model" + "gfast/app/system/service" + "gfast/library" + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" + "github.com/gogf/gf/text/gstr" + "github.com/gogf/gf/util/gconv" +) + +// Ctx 自定义上下文对象 +func Ctx(r *ghttp.Request) { + // 初始化,务必最开始执行 + customCtx := &dao.Context{ + Session: r.Session, + Data: make(g.Map), + } + service.Context.Init(r, customCtx) + user := new(model.LoginUserRes) + resp := api.GfToken.GetTokenData(r) + err := gconv.Struct(resp.Get("data"), &user) + if err != nil { + g.Log().Error(err.Error()) + } + if user != nil { + customCtx.User = &dao.CtxUser{ + Id: user.Id, + UserName: user.UserName, + UserNickname: user.UserNickname, + DeptId: user.DeptId, + UserStatus: user.UserStatus, + IsAdmin: user.IsAdmin, + Avatar: user.Avatar, + } + } + // 将自定义的上下文对象传递到模板变量中使用 + r.Assigns(g.Map{ + "Context": customCtx, + }) + // 执行下一步请求逻辑 + r.Middleware.Next() +} + +// Auth 权限判断处理中间件 +func Auth(r *ghttp.Request) { + userInfo := service.Context.Get(r.GetCtx()).User + //获取登陆用户id + adminId := userInfo.Id + /*if r.Method != "GET" && adminId!=1{ + response.FailJson(true, r, "演示系统禁止操作") + }*/ + accessParams := r.GetStrings("accessParams") + accessParamsStr := "" + if len(accessParams) > 0 && accessParams[0] != "undefined" { + accessParamsStr = "?" + gstr.Join(accessParams, "&") + } + //获取无需验证权限的用户id + tagSuperAdmin := false + service.SysUser.NotCheckAuthAdminIds.Iterator(func(v interface{}) bool { + if gconv.Uint64(v) == adminId { + tagSuperAdmin = true + return false + } + return true + }) + if tagSuperAdmin { + r.Middleware.Next() + //不要再往后面执行 + return + } + url := gstr.TrimLeft(r.Request.URL.Path, "/") + accessParamsStr + //获取地址对应的菜单id + menuList, err := service.Rule.GetMenuIsStatusList() + if err != nil { + g.Log().Error(err) + library.FailJson(true, r, "请求数据失败") + } + var menu *model.SysAuthRuleInfoRes + for _, m := range menuList { + ms := gstr.SubStr(m.Name, 0, gstr.Pos(m.Name, "?")) + if m.Name == url || ms == url { + menu = m + break + } + } + //只验证存在数据库中的规则 + if menu != nil { + //若存在不需要验证的条件则跳过 + if gstr.Equal(menu.Condition, "nocheck") { + r.Middleware.Next() + return + } + menuId := menu.Id + //菜单没存数据库不验证权限 + if menuId != 0 { + //判断权限操作 + enforcer, err := comService.Casbin.GetEnforcer() + if err != nil { + g.Log().Error(err) + library.FailJson(true, r, "获取权限失败") + } + groupPolicy := enforcer.GetFilteredGroupingPolicy(0, + gconv.String(adminId)) + if len(groupPolicy) == 0 { + library.FailJson(true, r, "没有访问权限") + } + hasAccess := false + for _, v := range groupPolicy { + if enforcer.HasPolicy(v[1], gconv.String(menuId), "All") { + hasAccess = true + break + } + } + if !hasAccess { + library.FailJson(true, r, "没有访问权限") + } + } + } else if menu == nil && accessParamsStr != "" { + library.FailJson(true, r, "没有访问权限") + } + r.Middleware.Next() +} diff --git a/middleware/cors.go b/middleware/cors.go new file mode 100644 index 0000000..696aad8 --- /dev/null +++ b/middleware/cors.go @@ -0,0 +1,16 @@ +/* +* @desc:xxxx功能描述 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/3/18 16:42 + */ + +package middleware + +import "github.com/gogf/gf/net/ghttp" + +// CORS 跨域处理中间件 +func CORS(r *ghttp.Request) { + r.Response.CORSDefault() + r.Middleware.Next() +} diff --git a/packed/packed.go b/packed/packed.go new file mode 100644 index 0000000..e20ab1e --- /dev/null +++ b/packed/packed.go @@ -0,0 +1 @@ +package packed diff --git a/public/html/.gitkeep b/public/html/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/plugin/.gitkeep b/public/plugin/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/resource/css/.gitkeep b/public/resource/css/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/resource/image/.gitkeep b/public/resource/image/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/public/resource/js/.gitkeep b/public/resource/js/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/router/.gitkeep b/router/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/router/router.go b/router/router.go new file mode 100644 index 0000000..e504ae6 --- /dev/null +++ b/router/router.go @@ -0,0 +1,29 @@ +package router + +import ( + "gfast/app/common/api" + _ "gfast/app/system/router" + "gfast/middleware" + + "github.com/gogf/gf/frame/g" + "github.com/gogf/gf/net/ghttp" +) + +func init() { + s := g.Server() + + //跨域处理 + s.Use(middleware.CORS) + // 添加URI与静态目录的映射 + s.AddStaticPath("/static", g.Cfg().GetString("server.ServerRoot")) + s.Group("/", func(group *ghttp.RouterGroup) { + + //上传的文件允许跨域请求 + group.Hook("/pub_upload/*", ghttp.HookBeforeServe, func(r *ghttp.Request) { + r.Response.CORSDefault() + }) + group.Group("/captcha", func(group *ghttp.RouterGroup) { + group.GET("/get", api.Captcha.Img) + }) + }) +} diff --git a/task/bind_function.go b/task/bind_function.go new file mode 100644 index 0000000..ab9ec8d --- /dev/null +++ b/task/bind_function.go @@ -0,0 +1,38 @@ +/* +* @desc:定时任务配置 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/16 15:45 + */ + +package task + +import ( + "gfast/app/system/api" + "gfast/app/system/service" + "github.com/gogf/gf/frame/g" +) + +func init() { + task1 := &service.TimeTask{ + FuncName: "test1", + Run: Test1, + } + task2 := &service.TimeTask{ + FuncName: "test2", + Run: Test2, + } + checkUserOnlineTask := &service.TimeTask{ + FuncName: "checkUserOnline", + Run: api.Auth.CheckUserOnline, + } + service.TimeTaskList.AddTask(task1).AddTask(task2).AddTask(checkUserOnlineTask) + //自动执行已开启的任务 + jobs, err := service.SysJob.GetJobs() + if err != nil { + g.Log().Error(err) + } + for _, job := range jobs { + service.SysJob.JobStart(job) + } +} diff --git a/task/demo.go b/task/demo.go new file mode 100644 index 0000000..76197e9 --- /dev/null +++ b/task/demo.go @@ -0,0 +1,29 @@ +/* +* @desc:测试定时任务 +* @company:云南省奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2021/7/16 15:52 + */ + +package task + +import ( + "fmt" + "gfast/app/system/service" +) + +func Test1() { + fmt.Println("无参测试") +} + +func Test2() { + //获取参数 + t := service.TimeTaskList.GetByName("test2") + if t == nil { + return + } + for _, v := range t.Param { + fmt.Printf("参数:%s; ", v) + } + fmt.Println() +} diff --git a/template/.gitkeep b/template/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/test/demo_test.go b/test/demo_test.go new file mode 100644 index 0000000..d479e7a --- /dev/null +++ b/test/demo_test.go @@ -0,0 +1,38 @@ +package test + +import ( + "fmt" + "gfast/app/system/dao" + _ "gfast/boot" + "gfast/library" + "github.com/gogf/gf/os/glog" + "testing" +) + +func TestDemo(t *testing.T) { + //t.Run("testEncryptPassword", testEncryptPassword) + //t.Run("testIpToAddr", testIpToAddr) + //t.Run("testDb", testDb) + t.Run("test2", test2) +} + +//测试加密函数 +func testEncryptPassword(t *testing.T) { + fmt.Println(library.EncryptPassword("yxh402063397", "OoFtPv")) +} + +func testIpToAddr(t *testing.T) { + fmt.Println(library.GetCityByIp("223.210.17.184")) +} + +func testDb(t *testing.T) { + d := dao.SysUser.Fields("id,user_name,user_nickname") + d = d.Where("user_name", "admin") + d = d.Or("user_name", "zs") + data, _ := d.All() + glog.Debug(data) +} + +func test2(t *testing.T) { + +}