├── utility ├── .gitkeep ├── xpwd │ ├── xpwd_test.go │ └── xpwd.go ├── xotp │ └── xotp.go ├── xcasbin │ └── casbin.go ├── xcache │ └── cache.go └── xgtoken │ └── gtoken.go ├── internal ├── dao │ ├── .gitkeep │ ├── api.go │ ├── dict.go │ ├── file.go │ ├── menu.go │ ├── role.go │ ├── user.go │ ├── button.go │ ├── notice.go │ ├── otp_auth.go │ ├── login_log.go │ ├── blacklist.go │ ├── provinces.go │ ├── casbin_policy.go │ ├── user_relation.go │ ├── notice_user_relation.go │ └── internal │ │ ├── otp_auth.go │ │ ├── api.go │ │ ├── button.go │ │ ├── user_relation.go │ │ ├── blacklist.go │ │ ├── casbin_policy.go │ │ ├── role.go │ │ ├── file.go │ │ ├── notice.go │ │ ├── dict.go │ │ ├── notice_user_relation.go │ │ ├── provinces.go │ │ ├── login_log.go │ │ ├── user.go │ │ └── menu.go ├── logic │ └── .gitkeep ├── model │ ├── .gitkeep │ ├── do │ │ ├── .gitkeep │ │ ├── user_relation.go │ │ ├── otp_auth.go │ │ ├── button.go │ │ ├── casbin_policy.go │ │ ├── api.go │ │ ├── blacklist.go │ │ ├── notice_user_relation.go │ │ ├── role.go │ │ ├── notice.go │ │ ├── file.go │ │ ├── dict.go │ │ ├── login_log.go │ │ ├── provinces.go │ │ ├── user.go │ │ └── menu.go │ └── entity │ │ ├── .gitkeep │ │ ├── user_relation.go │ │ ├── otp_auth.go │ │ ├── button.go │ │ ├── casbin_policy.go │ │ ├── blacklist.go │ │ ├── api.go │ │ ├── notice_user_relation.go │ │ ├── role.go │ │ ├── notice.go │ │ ├── file.go │ │ ├── dict.go │ │ ├── provinces.go │ │ ├── login_log.go │ │ ├── user.go │ │ └── menu.go ├── service │ ├── .gitkeep │ ├── userService │ │ └── user_test.go │ ├── regionService │ │ └── region.go │ ├── buttonService │ │ ├── button_test.go │ │ └── button.go │ ├── dictService │ │ └── dict.go │ ├── apiService │ │ └── api.go │ ├── roleService │ │ └── role.go │ ├── gtokenService │ │ └── gtoken.go │ ├── fileService │ │ └── file.go │ ├── menuService │ │ └── menu.go │ └── noticeService │ │ └── notice.go ├── packed │ └── packed.go ├── controller │ ├── region │ │ └── region.go │ ├── file │ │ └── file.go │ ├── dict │ │ └── dict.go │ ├── role │ │ └── role.go │ ├── api │ │ └── api.go │ ├── menu │ │ └── menu.go │ ├── user │ │ └── user.go │ ├── button │ │ └── button.go │ ├── log │ │ └── log.go │ ├── notice │ │ └── notice.go │ └── otp │ │ └── otp.go ├── middleware │ └── middleware.go ├── cmd │ └── cmd.go └── consts │ └── consts.go ├── resource ├── i18n │ └── .gitkeep ├── template │ └── .gitkeep ├── public │ ├── html │ │ └── .gitkeep │ ├── plugin │ │ └── .gitkeep │ └── resource │ │ ├── css │ │ └── .gitkeep │ │ ├── js │ │ └── .gitkeep │ │ └── image │ │ └── .gitkeep └── casbin │ ├── policy.csv │ └── model.conf ├── .gitattributes ├── manifest ├── protobuf │ └── .keep-if-necessary ├── docker │ ├── docker.sh │ └── Dockerfile ├── deploy │ └── kustomize │ │ ├── base │ │ ├── kustomization.yaml │ │ ├── service.yaml │ │ └── deployment.yaml │ │ └── overlays │ │ └── develop │ │ ├── deployment.yaml │ │ ├── kustomization.yaml │ │ └── configmap.yaml └── config │ ├── config.yaml │ ├── config.dev.yaml │ └── config.prod.yaml ├── start-dev.bat ├── start-dev.sh ├── logo.jpg ├── docs ├── 1.png ├── 2.png ├── 3.png ├── 4.png ├── 5.png ├── 6.png ├── 7.png ├── 8.png └── 1.md ├── stop-prod.sh ├── Makefile ├── main.go ├── .gitignore ├── api ├── vcommon │ └── common.go ├── vregion │ └── region.go ├── vlog │ └── loginLog.go ├── vdict │ └── dict.go ├── vrole │ └── role.go ├── vapi │ └── api.go ├── votp │ └── otp.go ├── vbutton │ └── button.go ├── vfile │ └── file.go ├── vnotice │ └── notice.go ├── vmenu │ └── menu.go └── vuser │ └── user.go ├── dev.sh ├── run-prod.sh ├── hack ├── hack-cli.mk ├── config.yaml └── hack.mk ├── go.mod └── README.MD /utility/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/dao/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/logic/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/model/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resource/i18n/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/model/do/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/service/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resource/template/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/model/entity/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resource/public/html/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resource/public/plugin/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * linguist-language=GO -------------------------------------------------------------------------------- /manifest/protobuf/.keep-if-necessary: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resource/public/resource/css/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resource/public/resource/js/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /resource/public/resource/image/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /internal/packed/packed.go: -------------------------------------------------------------------------------- 1 | package packed 2 | -------------------------------------------------------------------------------- /start-dev.bat: -------------------------------------------------------------------------------- 1 | go run main.go --gf.gcfg.file=config.dev.yaml -------------------------------------------------------------------------------- /start-dev.sh: -------------------------------------------------------------------------------- 1 | go run main.go --gf.gcfg.file=config.dev.yaml -------------------------------------------------------------------------------- /logo.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/logo.jpg -------------------------------------------------------------------------------- /docs/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/docs/1.png -------------------------------------------------------------------------------- /docs/2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/docs/2.png -------------------------------------------------------------------------------- /docs/3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/docs/3.png -------------------------------------------------------------------------------- /docs/4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/docs/4.png -------------------------------------------------------------------------------- /docs/5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/docs/5.png -------------------------------------------------------------------------------- /docs/6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/docs/6.png -------------------------------------------------------------------------------- /docs/7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/docs/7.png -------------------------------------------------------------------------------- /docs/8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/apple1563/goframe-admin/HEAD/docs/8.png -------------------------------------------------------------------------------- /manifest/docker/docker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # This shell is executed before docker build. 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /stop-prod.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | name="goframe-admin" 3 | # 停止正在运行的程序 4 | echo "停止正在运行的程序..." 5 | pkill -f $name 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /utility/xpwd/xpwd_test.go: -------------------------------------------------------------------------------- 1 | package xpwd 2 | 3 | import "testing" 4 | 5 | func TestGenPwd(t *testing.T) { 6 | pwd := GenPwd("2") 7 | println(pwd) 8 | } 9 | -------------------------------------------------------------------------------- /resource/casbin/policy.csv: -------------------------------------------------------------------------------- 1 | p, alice, data1, read 2 | p, bob, data2, write 3 | p, data2_admin, data2, read 4 | p, data2_admin, data2, write 5 | g, alice, data2_admin -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | ROOT_DIR = $(shell pwd) 2 | NAMESPACE = "default" 3 | DEPLOY_NAME = "template-single" 4 | DOCKER_NAME = "template-single" 5 | 6 | include ./hack/hack.mk -------------------------------------------------------------------------------- /manifest/deploy/kustomize/base/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | resources: 4 | - deployment.yaml 5 | - service.yaml 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "goframe-starter/internal/packed" 5 | 6 | "github.com/gogf/gf/v2/os/gctx" 7 | 8 | "goframe-starter/internal/cmd" 9 | ) 10 | 11 | func main() { 12 | cmd.Main.Run(gctx.GetInitCtx()) 13 | } 14 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/base/service.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: Service 3 | metadata: 4 | name: template-single 5 | spec: 6 | ports: 7 | - port: 80 8 | protocol: TCP 9 | targetPort: 8000 10 | selector: 11 | app: template-single 12 | 13 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/overlays/develop/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: template-single 5 | spec: 6 | template: 7 | spec: 8 | containers: 9 | - name : main 10 | image: template-single:develop -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .buildpath 2 | .hgignore.swp 3 | .project 4 | .orig 5 | .swp 6 | .idea/ 7 | .settings/ 8 | .vscode/ 9 | bin/ 10 | **/.DS_Store 11 | gf 12 | main 13 | main.exe 14 | output/ 15 | manifest/output/ 16 | temp/ 17 | temp.yaml 18 | bin 19 | logs 20 | **/logs 21 | resource/public/upload/** -------------------------------------------------------------------------------- /manifest/deploy/kustomize/overlays/develop/kustomization.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: kustomize.config.k8s.io/v1beta1 2 | kind: Kustomization 3 | 4 | resources: 5 | - ../../base 6 | - configmap.yaml 7 | 8 | patchesStrategicMerge: 9 | - deployment.yaml 10 | 11 | namespace: default 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/overlays/develop/configmap.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: v1 2 | kind: ConfigMap 3 | metadata: 4 | name: template-single-configmap 5 | data: 6 | config.yaml: | 7 | server: 8 | address: ":8000" 9 | openapiPath: "/api.json" 10 | swaggerPath: "/swagger" 11 | 12 | logger: 13 | level : "all" 14 | stdout: true 15 | -------------------------------------------------------------------------------- /internal/service/userService/user_test.go: -------------------------------------------------------------------------------- 1 | package userService 2 | 3 | import ( 4 | _ "github.com/gogf/gf/contrib/drivers/mysql/v2" 5 | "github.com/gogf/gf/v2/os/gctx" 6 | "goframe-starter/api/vuser" 7 | "testing" 8 | ) 9 | 10 | func TestAdd(t *testing.T) { 11 | var req = &vuser.AddUserReq{ 12 | Username: "admin", 13 | Password: "1", 14 | } 15 | AddUser(gctx.New(), req) 16 | } 17 | -------------------------------------------------------------------------------- /api/vcommon/common.go: -------------------------------------------------------------------------------- 1 | package vcommon 2 | 3 | type CommonPageReq struct { 4 | PageIndex int `json:"page"` 5 | PageSize int `json:"size"` 6 | } 7 | 8 | type CommonPageRes struct { 9 | PageIndex int `json:"page" d:"1" dc:"当前页数"` 10 | //TotalPage int `json:"total_page,omitempty" dc:"总页数"` 11 | PageSize int `json:"size,omitempty" dc:"页面大小"` 12 | Total int `json:"total" dc:"总条数"` 13 | } 14 | -------------------------------------------------------------------------------- /resource/casbin/model.conf: -------------------------------------------------------------------------------- 1 | [request_definition] 2 | r = sub, obj, act 3 | 4 | [policy_definition] 5 | p = sub, obj, act 6 | 7 | [role_definition] 8 | g = _, _ 9 | 10 | [policy_effect] 11 | e = some(where (p.eft == allow)) 12 | 13 | [matchers] 14 | m = g(r.sub, p.sub) && r.obj == p.obj && r.act == p.act || r.sub == "role-api 1024" || r.sub == "role-menu 1024" || r.sub == "role-button 1024" 15 | 16 | 17 | -------------------------------------------------------------------------------- /internal/controller/region/region.go: -------------------------------------------------------------------------------- 1 | package region 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vregion" 6 | "goframe-starter/internal/service/regionService" 7 | ) 8 | 9 | type Region struct{} 10 | 11 | var Ctrl = new(Region) 12 | 13 | func (u *Region) AddRegion(ctx context.Context, req *vregion.ListTreeReq) (res *vregion.ListTreeRes, err error) { 14 | return regionService.GetTreeList(ctx, req) 15 | } 16 | -------------------------------------------------------------------------------- /api/vregion/region.go: -------------------------------------------------------------------------------- 1 | package vregion 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "goframe-starter/internal/model/entity" 6 | ) 7 | 8 | type ListTreeReq struct { 9 | g.Meta `tags:"省市列表" method:"get" path:"/region/tree" sm:"列表" dc:"树形列表" ` 10 | } 11 | type TreeItem struct { 12 | *entity.Provinces 13 | Children []*TreeItem `json:"children"` 14 | } 15 | type ListTreeRes struct { 16 | List []*TreeItem `json:"list"` 17 | } 18 | -------------------------------------------------------------------------------- /utility/xpwd/xpwd.go: -------------------------------------------------------------------------------- 1 | package xpwd 2 | 3 | import "golang.org/x/crypto/bcrypt" 4 | 5 | func GenPwd(pwd string) string { 6 | password, _ := bcrypt.GenerateFromPassword([]byte(pwd), bcrypt.DefaultCost) 7 | return string(password) 8 | } 9 | 10 | // ComparePassword pwd 数据库里面的密码 rePwd 用户输入的密码 11 | func ComparePassword(dbPwd, reqPwd string) bool { 12 | e := bcrypt.CompareHashAndPassword([]byte(dbPwd), []byte(reqPwd)) 13 | return e == nil 14 | } 15 | -------------------------------------------------------------------------------- /manifest/deploy/kustomize/base/deployment.yaml: -------------------------------------------------------------------------------- 1 | apiVersion: apps/v1 2 | kind: Deployment 3 | metadata: 4 | name: template-single 5 | labels: 6 | app: template-single 7 | spec: 8 | replicas: 1 9 | selector: 10 | matchLabels: 11 | app: template-single 12 | template: 13 | metadata: 14 | labels: 15 | app: template-single 16 | spec: 17 | containers: 18 | - name : main 19 | image: template-single 20 | imagePullPolicy: Always 21 | 22 | -------------------------------------------------------------------------------- /utility/xotp/xotp.go: -------------------------------------------------------------------------------- 1 | package xotp 2 | 3 | import ( 4 | "github.com/pquerna/otp" 5 | "github.com/pquerna/otp/totp" 6 | ) 7 | 8 | func GenerateOtp(uname string, issuer string) (*otp.Key, error) { 9 | key, err := totp.Generate(totp.GenerateOpts{ 10 | Issuer: issuer, // 发行者名称(用于显示在谷歌验证器中) 11 | AccountName: uname, 12 | }) 13 | return key, err 14 | } 15 | 16 | func ValidateOtp(totpCode string, keySecret string) bool { 17 | isValid := totp.Validate(totpCode, keySecret) 18 | return isValid 19 | } 20 | -------------------------------------------------------------------------------- /dev.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Go 可执行文件名 4 | name="goframe-admin" 5 | # 日志文件名 6 | logFile="output_$(date '+%Y%m%d_%H%M%S').log" 7 | configFile="config.dev.yaml" 8 | 9 | # 执行发布流程 10 | #echo "Fetching latest code..." 11 | #git fetch --all 12 | #git reset --hard origin/master 13 | 14 | # 停止正在运行的程序 15 | echo "停止正在运行的程序..." 16 | pkill -f $name 17 | sleep 2 # 等待程序停止 18 | 19 | # 启动 Go 程序并将输出重定向到日志文件 20 | echo "启动 Go 程序..." 21 | nohup ./$name --gf.gcfg.file=$configFile > $logFile 2>&1 & 22 | 23 | # 打印进程 ID 24 | echo "Go 程序已在后台运行,进程 ID:$!" 25 | -------------------------------------------------------------------------------- /run-prod.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Go 可执行文件名 4 | name="goframe-admin" 5 | # 日志文件名 6 | logFile="output_$(date '+%Y%m%d_%H%M%S').log" 7 | configFile="config.prod.yaml" 8 | 9 | # 执行发布流程 10 | #echo "Fetching latest code..." 11 | #git fetch --all 12 | #git reset --hard origin/master 13 | 14 | # 停止正在运行的程序 15 | echo "停止正在运行的程序..." 16 | pkill -f $name 17 | sleep 2 # 等待程序停止 18 | 19 | # 启动 Go 程序并将输出重定向到日志文件 20 | echo "启动 Go 程序..." 21 | nohup ./$name --gf.gcfg.file=$configFile > $logFile 2>&1 & 22 | 23 | # 打印进程 ID 24 | echo "Go 程序已在后台运行,进程 ID:$!" 25 | -------------------------------------------------------------------------------- /hack/hack-cli.mk: -------------------------------------------------------------------------------- 1 | 2 | # Install/Update to the latest CLI tool. 3 | .PHONY: cli 4 | cli: 5 | @set -e; \ 6 | wget -O gf https://github.com/gogf/gf/releases/latest/download/gf_$(shell go env GOOS)_$(shell go env GOARCH) && \ 7 | chmod +x gf && \ 8 | ./gf install -y && \ 9 | rm ./gf 10 | 11 | 12 | # Check and install CLI tool. 13 | .PHONY: cli.install 14 | cli.install: 15 | @set -e; \ 16 | gf -v > /dev/null 2>&1 || if [[ "$?" -ne "0" ]]; then \ 17 | echo "GoFame CLI is not installed, start proceeding auto installation..."; \ 18 | make cli; \ 19 | fi; -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module goframe-starter 2 | 3 | go 1.15 4 | 5 | require ( 6 | github.com/casbin/casbin/v2 v2.77.2 // indirect 7 | github.com/dobyte/gf-casbin v0.1.1 8 | github.com/goflyfox/gtoken v1.5.9 9 | github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.4 10 | github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.4 11 | github.com/gogf/gf/v2 v2.5.4 12 | github.com/pquerna/otp v1.4.0 13 | github.com/yudeguang/iox v0.0.0-20220912082704-297952f8e912 // indirect 14 | github.com/yudeguang/ratelimit v0.0.0-20230316132559-4d9cafca864e 15 | golang.org/x/crypto v0.11.0 16 | ) 17 | -------------------------------------------------------------------------------- /internal/model/entity/user_relation.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | // UserRelation is the golang structure for table user_relation. 8 | type UserRelation struct { 9 | Id int `json:"id" description:""` 10 | PUserId int `json:"pUserId" description:""` 11 | Level uint `json:"level" description:"代理层级"` 12 | UserId uint `json:"userId" description:""` 13 | } 14 | -------------------------------------------------------------------------------- /api/vlog/loginLog.go: -------------------------------------------------------------------------------- 1 | package vlog 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "goframe-starter/api/vcommon" 6 | "goframe-starter/internal/model/entity" 7 | ) 8 | 9 | type ListLoginLogReq struct { 10 | g.Meta `tags:"loginLog" method:"get" path:"/loginLog/list" sm:"列表" dc:"loginLog列表" ` 11 | Username string `json:"username" description:""` 12 | Ip string `json:"ip" description:""` 13 | TimeBetween []string `json:"timeBetween"` 14 | *vcommon.CommonPageReq 15 | } 16 | type ListLoginLogRes struct { 17 | List []*entity.LoginLog `json:"list"` 18 | *vcommon.CommonPageRes 19 | } 20 | -------------------------------------------------------------------------------- /utility/xcasbin/casbin.go: -------------------------------------------------------------------------------- 1 | package xcasbin 2 | 3 | import ( 4 | "github.com/dobyte/gf-casbin" 5 | "github.com/gogf/gf/v2/frame/g" 6 | "github.com/gogf/gf/v2/os/gctx" 7 | ) 8 | 9 | var Enforcer *casbin.Enforcer 10 | 11 | func Init() { 12 | ctx := gctx.New() 13 | Enf, err := casbin.NewEnforcer(&casbin.Options{ 14 | Model: g.Cfg().MustGet(ctx, "casbin.modelFile").String(), 15 | Debug: false, 16 | Enable: true, 17 | AutoLoad: true, 18 | Table: "casbin_policy", 19 | Link: g.Cfg().MustGet(ctx, "database.default.link").String(), 20 | }) 21 | 22 | if err != nil { 23 | panic(err) 24 | } 25 | Enforcer = Enf 26 | } 27 | -------------------------------------------------------------------------------- /utility/xcache/cache.go: -------------------------------------------------------------------------------- 1 | package xcache 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "github.com/gogf/gf/v2/os/gcache" 6 | "github.com/gogf/gf/v2/os/gctx" 7 | "goframe-starter/internal/consts" 8 | ) 9 | 10 | var Instance *gcache.Cache 11 | 12 | func Init() { 13 | var ( 14 | ctx = gctx.New() 15 | cache = gcache.New() 16 | ) 17 | //prefix := g.Cfg().MustGet(ctx, "cache.prefix").Int() 18 | model := g.Cfg().MustGet(ctx, "cache.model").Int() 19 | if model == consts.Cache_Mode_Redis { 20 | // Create redis cache adapter and set it to cache object. 21 | cache.SetAdapter(gcache.NewAdapterRedis(g.Redis())) 22 | } 23 | Instance = cache 24 | } 25 | -------------------------------------------------------------------------------- /internal/model/entity/otp_auth.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | // OtpAuth is the golang structure for table otp_auth. 8 | type OtpAuth struct { 9 | Id int `json:"id" description:""` 10 | Uid uint `json:"uid" description:""` 11 | Username string `json:"username" description:""` 12 | Secret string `json:"secret" description:""` 13 | Status uint `json:"status" description:"1开2关"` 14 | } 15 | -------------------------------------------------------------------------------- /internal/model/do/user_relation.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | ) 10 | 11 | // UserRelation is the golang structure of table user_relation for DAO operations like Where/Data. 12 | type UserRelation struct { 13 | g.Meta `orm:"table:user_relation, do:true"` 14 | Id interface{} // 15 | PUserId interface{} // 16 | Level interface{} // 代理层级 17 | UserId interface{} // 18 | } 19 | -------------------------------------------------------------------------------- /internal/model/do/otp_auth.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | ) 10 | 11 | // OtpAuth is the golang structure of table otp_auth for DAO operations like Where/Data. 12 | type OtpAuth struct { 13 | g.Meta `orm:"table:otp_auth, do:true"` 14 | Id interface{} // 15 | Uid interface{} // 16 | Username interface{} // 17 | Secret interface{} // 18 | Status interface{} // 1开2关 19 | } 20 | -------------------------------------------------------------------------------- /manifest/docker/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM loads/alpine:3.8 2 | 3 | ############################################################################### 4 | # INSTALLATION 5 | ############################################################################### 6 | 7 | ENV WORKDIR /app 8 | ADD resource $WORKDIR/ 9 | ADD ./temp/linux_amd64/main $WORKDIR/main 10 | RUN chmod +x $WORKDIR/main 11 | 12 | ############################################################################### 13 | # START 14 | ############################################################################### 15 | WORKDIR $WORKDIR 16 | CMD ./main 17 | -------------------------------------------------------------------------------- /docs/1.md: -------------------------------------------------------------------------------- 1 | # GoFrame Admin 2 | 3 | 权限说明: 4 | 菜单: 5 | 在角色管理页面,可以为不同角色设置菜单权限。通过casbin规则控制,设置时将角色与菜单id关联,该角色登录后获取的菜单也是与该角色casbin规则关联的菜单。 6 | 前端将从接口收到一个vue路由的配置json,动态生成路由和菜单。 7 | 按钮: 8 | 在角色管理页面,可以为不同角色设置按钮权限。通过casbin规则控制,设置时将角色与按钮id关联,该角色登录后获取有权限的按钮id列表。 9 | 前端使用指令`v-auth-buton`来判断是否展示菜单,具体原理是看`v-auth-buton`的值(按钮id)是否在返回的按钮id列表中,在就展示,不在就隐藏。 10 | API: 11 | 在角色管理页面,可以为不同角色设置API权限。通过casbin规则控制,设置时将角色与API的url&method关联。 12 | 前端在发起请求时,后端casbin会校验该用户所属角色是否拥有该API权限,无权限则返回403。 13 | 14 | 用户管理说明: 15 | 用户层级是一个树形结构,区分上下级。每个用户登录后台查看用户列表只能查看自己的下级。 16 | todo 参数控制 17 | 18 | 菜单管理说明: 19 | 添加菜单时填写vue路由的一些配置项,同时前端对应路径也要添加相应的目录和文件。 20 | 按钮管理说明: 21 | 按妞的增删改查,按钮列表方便用户在设置按钮权限时作为选择框的下拉列表。 22 | api管理说明: 23 | api的增删改查,api列表方便用户在设置api权限时作为选择框的下拉列表 -------------------------------------------------------------------------------- /internal/model/do/button.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | ) 10 | 11 | // Button is the golang structure of table button for DAO operations like Where/Data. 12 | type Button struct { 13 | g.Meta `orm:"table:button, do:true"` 14 | Id interface{} // 15 | MenuId interface{} // 按钮所在菜单id 16 | MenuTitle interface{} // 按钮所在菜单名称 17 | Name interface{} // 按钮标识符 18 | Title interface{} // 按钮名称 19 | Remark interface{} // 20 | } 21 | -------------------------------------------------------------------------------- /internal/model/do/casbin_policy.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | ) 10 | 11 | // CasbinPolicy is the golang structure of table casbin_policy for DAO operations like Where/Data. 12 | type CasbinPolicy struct { 13 | g.Meta `orm:"table:casbin_policy, do:true"` 14 | Ptype interface{} // 15 | V0 interface{} // 16 | V1 interface{} // 17 | V2 interface{} // 18 | V3 interface{} // 19 | V4 interface{} // 20 | V5 interface{} // 21 | } 22 | -------------------------------------------------------------------------------- /internal/model/entity/button.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | // Button is the golang structure for table button. 8 | type Button struct { 9 | Id uint `json:"id" description:""` 10 | MenuId int64 `json:"menuId" description:"按钮所在菜单id"` 11 | MenuTitle string `json:"menuTitle" description:"按钮所在菜单名称"` 12 | Name string `json:"name" description:"按钮标识符"` 13 | Title string `json:"title" description:"按钮名称"` 14 | Remark string `json:"remark" description:""` 15 | } 16 | -------------------------------------------------------------------------------- /internal/model/entity/casbin_policy.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | // CasbinPolicy is the golang structure for table casbin_policy. 8 | type CasbinPolicy struct { 9 | Ptype string `json:"ptype" description:""` 10 | V0 string `json:"v0" description:""` 11 | V1 string `json:"v1" description:""` 12 | V2 string `json:"v2" description:""` 13 | V3 string `json:"v3" description:""` 14 | V4 string `json:"v4" description:""` 15 | V5 string `json:"v5" description:""` 16 | } 17 | -------------------------------------------------------------------------------- /internal/model/do/api.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Api is the golang structure of table api for DAO operations like Where/Data. 13 | type Api struct { 14 | g.Meta `orm:"table:api, do:true"` 15 | Id interface{} // 16 | Url interface{} // 17 | Method interface{} // 18 | Group interface{} // 19 | Remark interface{} // 20 | CreatedAt *gtime.Time // 21 | UpdatedAt *gtime.Time // 22 | } 23 | -------------------------------------------------------------------------------- /internal/model/do/blacklist.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Blacklist is the golang structure of table blacklist for DAO operations like Where/Data. 13 | type Blacklist struct { 14 | g.Meta `orm:"table:blacklist, do:true"` 15 | Id interface{} // 黑名单ID 16 | Ip interface{} // IP地址 17 | Remark interface{} // 备注 18 | Status interface{} // 状态 19 | CreatedAt *gtime.Time // 创建时间 20 | UpdatedAt *gtime.Time // 更新时间 21 | } 22 | -------------------------------------------------------------------------------- /internal/model/entity/blacklist.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Blacklist is the golang structure for table blacklist. 12 | type Blacklist struct { 13 | Id int64 `json:"id" description:"黑名单ID"` 14 | Ip string `json:"ip" description:"IP地址"` 15 | Remark string `json:"remark" description:"备注"` 16 | Status int `json:"status" description:"状态"` 17 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 18 | UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` 19 | } 20 | -------------------------------------------------------------------------------- /internal/model/do/notice_user_relation.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // NoticeUserRelation is the golang structure of table notice_user_relation for DAO operations like Where/Data. 13 | type NoticeUserRelation struct { 14 | g.Meta `orm:"table:notice_user_relation, do:true"` 15 | Id interface{} // 16 | NoticeId interface{} // 17 | Uid interface{} // 18 | Status interface{} // 1未读2已读3隐藏,用户看过把status置为2,看完后选择删除就把status置为3 19 | CreatedAt *gtime.Time // 创建时间 20 | UpdatedAt *gtime.Time // 更新时间 21 | } 22 | -------------------------------------------------------------------------------- /internal/model/entity/api.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Api is the golang structure for table api. 12 | type Api struct { 13 | Id int `json:"id" description:""` 14 | Url string `json:"url" description:""` 15 | Method string `json:"method" description:""` 16 | Group string `json:"group" description:""` 17 | Remark string `json:"remark" description:""` 18 | CreatedAt *gtime.Time `json:"createdAt" description:""` 19 | UpdatedAt *gtime.Time `json:"updatedAt" description:""` 20 | } 21 | -------------------------------------------------------------------------------- /internal/model/do/role.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Role is the golang structure of table role for DAO operations like Where/Data. 13 | type Role struct { 14 | g.Meta `orm:"table:role, do:true"` 15 | Id interface{} // 16 | Status interface{} // 状态;1:正常2:禁用 17 | ListOrder interface{} // 排序 18 | Name interface{} // 角色名称 19 | Remark interface{} // 备注 20 | DataScope interface{} // 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) 21 | CreatedAt *gtime.Time // 创建时间 22 | UpdatedAt *gtime.Time // 更新时间 23 | } 24 | -------------------------------------------------------------------------------- /internal/dao/api.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalApiDao is internal type for wrapping internal DAO implements. 12 | type internalApiDao = *internal.ApiDao 13 | 14 | // apiDao is the data access object for table api. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type apiDao struct { 17 | internalApiDao 18 | } 19 | 20 | var ( 21 | // Api is globally public accessible object for table api operations. 22 | Api = apiDao{ 23 | internal.NewApiDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/model/do/notice.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Notice is the golang structure of table notice for DAO operations like Where/Data. 13 | type Notice struct { 14 | g.Meta `orm:"table:notice, do:true"` 15 | Id interface{} // 16 | Title interface{} // 17 | Content interface{} // 18 | Creater interface{} // 创建者username,发送者 19 | Receivers interface{} // 接收者用户id数组 20 | Sort interface{} // 21 | Tag interface{} // 22 | Remark interface{} // 23 | CreatedAt *gtime.Time // 24 | UpdatedAt *gtime.Time // 25 | } 26 | -------------------------------------------------------------------------------- /internal/dao/dict.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalDictDao is internal type for wrapping internal DAO implements. 12 | type internalDictDao = *internal.DictDao 13 | 14 | // dictDao is the data access object for table dict. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type dictDao struct { 17 | internalDictDao 18 | } 19 | 20 | var ( 21 | // Dict is globally public accessible object for table dict operations. 22 | Dict = dictDao{ 23 | internal.NewDictDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/file.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalFileDao is internal type for wrapping internal DAO implements. 12 | type internalFileDao = *internal.FileDao 13 | 14 | // fileDao is the data access object for table file. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type fileDao struct { 17 | internalFileDao 18 | } 19 | 20 | var ( 21 | // File is globally public accessible object for table file operations. 22 | File = fileDao{ 23 | internal.NewFileDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/menu.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalMenuDao is internal type for wrapping internal DAO implements. 12 | type internalMenuDao = *internal.MenuDao 13 | 14 | // menuDao is the data access object for table menu. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type menuDao struct { 17 | internalMenuDao 18 | } 19 | 20 | var ( 21 | // Menu is globally public accessible object for table menu operations. 22 | Menu = menuDao{ 23 | internal.NewMenuDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/role.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalRoleDao is internal type for wrapping internal DAO implements. 12 | type internalRoleDao = *internal.RoleDao 13 | 14 | // roleDao is the data access object for table role. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type roleDao struct { 17 | internalRoleDao 18 | } 19 | 20 | var ( 21 | // Role is globally public accessible object for table role operations. 22 | Role = roleDao{ 23 | internal.NewRoleDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/user.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalUserDao is internal type for wrapping internal DAO implements. 12 | type internalUserDao = *internal.UserDao 13 | 14 | // userDao is the data access object for table user. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type userDao struct { 17 | internalUserDao 18 | } 19 | 20 | var ( 21 | // User is globally public accessible object for table user operations. 22 | User = userDao{ 23 | internal.NewUserDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/model/do/file.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // File is the golang structure of table file for DAO operations like Where/Data. 13 | type File struct { 14 | g.Meta `orm:"table:file, do:true"` 15 | Id interface{} // 16 | Drive interface{} // 上传驱动:本地,ucloud 17 | OriginName interface{} // 文件原始名 18 | FileUrl interface{} // 19 | Size interface{} // 单位M 20 | Ext interface{} // 扩展名 21 | Uid interface{} // 上传者用户id 22 | CreatedAt *gtime.Time // 23 | UpdatedAt *gtime.Time // 24 | Remark interface{} // 25 | } 26 | -------------------------------------------------------------------------------- /internal/model/entity/notice_user_relation.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // NoticeUserRelation is the golang structure for table notice_user_relation. 12 | type NoticeUserRelation struct { 13 | Id int `json:"id" description:""` 14 | NoticeId int `json:"noticeId" description:""` 15 | Uid uint `json:"uid" description:""` 16 | Status int `json:"status" description:"1未读2已读3隐藏,用户看过把status置为2,看完后选择删除就把status置为3"` 17 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 18 | UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` 19 | } 20 | -------------------------------------------------------------------------------- /internal/dao/button.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalButtonDao is internal type for wrapping internal DAO implements. 12 | type internalButtonDao = *internal.ButtonDao 13 | 14 | // buttonDao is the data access object for table button. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type buttonDao struct { 17 | internalButtonDao 18 | } 19 | 20 | var ( 21 | // Button is globally public accessible object for table button operations. 22 | Button = buttonDao{ 23 | internal.NewButtonDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/notice.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalNoticeDao is internal type for wrapping internal DAO implements. 12 | type internalNoticeDao = *internal.NoticeDao 13 | 14 | // noticeDao is the data access object for table notice. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type noticeDao struct { 17 | internalNoticeDao 18 | } 19 | 20 | var ( 21 | // Notice is globally public accessible object for table notice operations. 22 | Notice = noticeDao{ 23 | internal.NewNoticeDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/model/do/dict.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Dict is the golang structure of table dict for DAO operations like Where/Data. 13 | type Dict struct { 14 | g.Meta `orm:"table:dict, do:true"` 15 | Id interface{} // 参数主键 16 | ConfigName interface{} // 参数名称 17 | ConfigKey interface{} // 参数键名 18 | ConfigValue interface{} // 参数键值 19 | ConfigType interface{} // 字典类型 20 | CreateBy interface{} // 创建者 21 | UpdateBy interface{} // 更新者 22 | Remark interface{} // 备注 23 | CreatedAt *gtime.Time // 创建时间 24 | UpdatedAt *gtime.Time // 修改时间 25 | } 26 | -------------------------------------------------------------------------------- /hack/config.yaml: -------------------------------------------------------------------------------- 1 | 2 | # CLI tool, only in development environment. 3 | # https://goframe.org/pages/viewpage.action?pageId=3673173 4 | gfcli: 5 | gen: 6 | dao: 7 | - link: "mysql:starter:HPxNd6sT48yehDCr@tcp(163.197.246.80:3306)/starter?loc=Local&parseTime=true" 8 | # - link: "mysql:root:123456@tcp(127.0.0.1:3306)/starter?loc=Local&parseTime=true" 9 | tables: "" 10 | removePrefix: "" 11 | descriptionTag: true 12 | noModelComment: true 13 | group: "default" 14 | overwriteDao: true 15 | docker: 16 | build: "-a amd64 -s linux -p temp -ew" 17 | tagPrefixes: 18 | - my.image.pub/my-app 19 | build: 20 | name: "goframe-admin" 21 | arch: "amd64" 22 | system: "linux,windows" 23 | #system: "linux,darwin,windows" 24 | mod: "none" 25 | packSrc: "" 26 | #packSrc: "resource,manifest" 27 | version: "v1.0.0" 28 | path: "./bin" 29 | extra: "" -------------------------------------------------------------------------------- /internal/dao/otp_auth.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalOtpAuthDao is internal type for wrapping internal DAO implements. 12 | type internalOtpAuthDao = *internal.OtpAuthDao 13 | 14 | // otpAuthDao is the data access object for table otp_auth. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type otpAuthDao struct { 17 | internalOtpAuthDao 18 | } 19 | 20 | var ( 21 | // OtpAuth is globally public accessible object for table otp_auth operations. 22 | OtpAuth = otpAuthDao{ 23 | internal.NewOtpAuthDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/login_log.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalLoginLogDao is internal type for wrapping internal DAO implements. 12 | type internalLoginLogDao = *internal.LoginLogDao 13 | 14 | // loginLogDao is the data access object for table login_log. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type loginLogDao struct { 17 | internalLoginLogDao 18 | } 19 | 20 | var ( 21 | // LoginLog is globally public accessible object for table login_log operations. 22 | LoginLog = loginLogDao{ 23 | internal.NewLoginLogDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/blacklist.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalBlacklistDao is internal type for wrapping internal DAO implements. 12 | type internalBlacklistDao = *internal.BlacklistDao 13 | 14 | // blacklistDao is the data access object for table blacklist. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type blacklistDao struct { 17 | internalBlacklistDao 18 | } 19 | 20 | var ( 21 | // Blacklist is globally public accessible object for table blacklist operations. 22 | Blacklist = blacklistDao{ 23 | internal.NewBlacklistDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/provinces.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalProvincesDao is internal type for wrapping internal DAO implements. 12 | type internalProvincesDao = *internal.ProvincesDao 13 | 14 | // provincesDao is the data access object for table provinces. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type provincesDao struct { 17 | internalProvincesDao 18 | } 19 | 20 | var ( 21 | // Provinces is globally public accessible object for table provinces operations. 22 | Provinces = provincesDao{ 23 | internal.NewProvincesDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/model/do/login_log.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // LoginLog is the golang structure of table login_log for DAO operations like Where/Data. 13 | type LoginLog struct { 14 | g.Meta `orm:"table:login_log, do:true"` 15 | Id interface{} // 16 | Uid interface{} // 17 | Username interface{} // 18 | Ip interface{} // 19 | CreatedAt *gtime.Time // 20 | UpdatedAt *gtime.Time // 21 | ClientAgent interface{} // 注册clientAgen头 22 | RoleId interface{} // 1用户2代理3管理 23 | PRoleId interface{} // 24 | RoleName interface{} // 25 | Pid interface{} // 26 | PUsername interface{} // 27 | } 28 | -------------------------------------------------------------------------------- /internal/model/do/provinces.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Provinces is the golang structure of table provinces for DAO operations like Where/Data. 13 | type Provinces struct { 14 | g.Meta `orm:"table:provinces, do:true"` 15 | Id interface{} // 省市区ID 16 | Title interface{} // 栏目名称 17 | Pinyin interface{} // 拼音 18 | Lng interface{} // 经度 19 | Lat interface{} // 纬度 20 | Pid interface{} // 父栏目 21 | Level interface{} // 关系树等级 22 | Tree interface{} // 关系 23 | Sort interface{} // 排序 24 | Status interface{} // 状态 25 | CreatedAt *gtime.Time // 创建时间 26 | UpdatedAt *gtime.Time // 更新时间 27 | } 28 | -------------------------------------------------------------------------------- /internal/dao/casbin_policy.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalCasbinPolicyDao is internal type for wrapping internal DAO implements. 12 | type internalCasbinPolicyDao = *internal.CasbinPolicyDao 13 | 14 | // casbinPolicyDao is the data access object for table casbin_policy. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type casbinPolicyDao struct { 17 | internalCasbinPolicyDao 18 | } 19 | 20 | var ( 21 | // CasbinPolicy is globally public accessible object for table casbin_policy operations. 22 | CasbinPolicy = casbinPolicyDao{ 23 | internal.NewCasbinPolicyDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/dao/user_relation.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalUserRelationDao is internal type for wrapping internal DAO implements. 12 | type internalUserRelationDao = *internal.UserRelationDao 13 | 14 | // userRelationDao is the data access object for table user_relation. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type userRelationDao struct { 17 | internalUserRelationDao 18 | } 19 | 20 | var ( 21 | // UserRelation is globally public accessible object for table user_relation operations. 22 | UserRelation = userRelationDao{ 23 | internal.NewUserRelationDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/model/entity/role.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Role is the golang structure for table role. 12 | type Role struct { 13 | Id uint `json:"id" description:""` 14 | Status uint `json:"status" description:"状态;1:正常2:禁用"` 15 | ListOrder uint `json:"listOrder" description:"排序"` 16 | Name string `json:"name" description:"角色名称"` 17 | Remark string `json:"remark" description:"备注"` 18 | DataScope uint `json:"dataScope" description:"数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限)"` 19 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 20 | UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` 21 | } 22 | -------------------------------------------------------------------------------- /internal/dao/notice_user_relation.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. 3 | // ================================================================================= 4 | 5 | package dao 6 | 7 | import ( 8 | "goframe-starter/internal/dao/internal" 9 | ) 10 | 11 | // internalNoticeUserRelationDao is internal type for wrapping internal DAO implements. 12 | type internalNoticeUserRelationDao = *internal.NoticeUserRelationDao 13 | 14 | // noticeUserRelationDao is the data access object for table notice_user_relation. 15 | // You can define custom methods on it to extend its functionality as you wish. 16 | type noticeUserRelationDao struct { 17 | internalNoticeUserRelationDao 18 | } 19 | 20 | var ( 21 | // NoticeUserRelation is globally public accessible object for table notice_user_relation operations. 22 | NoticeUserRelation = noticeUserRelationDao{ 23 | internal.NewNoticeUserRelationDao(), 24 | } 25 | ) 26 | 27 | // Fill with you ideas below. 28 | -------------------------------------------------------------------------------- /internal/model/entity/notice.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Notice is the golang structure for table notice. 12 | type Notice struct { 13 | Id int `json:"id" description:""` 14 | Title string `json:"title" description:""` 15 | Content string `json:"content" description:""` 16 | Creater string `json:"creater" description:"创建者username,发送者"` 17 | Receivers string `json:"receivers" description:"接收者用户id数组"` 18 | Sort int `json:"sort" description:""` 19 | Tag string `json:"tag" description:""` 20 | Remark string `json:"remark" description:""` 21 | CreatedAt *gtime.Time `json:"createdAt" description:""` 22 | UpdatedAt *gtime.Time `json:"updatedAt" description:""` 23 | } 24 | -------------------------------------------------------------------------------- /internal/model/entity/file.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // File is the golang structure for table file. 12 | type File struct { 13 | Id int `json:"id" description:""` 14 | Drive string `json:"drive" description:"上传驱动:本地,ucloud"` 15 | OriginName string `json:"originName" description:"文件原始名"` 16 | FileUrl string `json:"fileUrl" description:""` 17 | Size int64 `json:"size" description:"单位M"` 18 | Ext string `json:"ext" description:"扩展名"` 19 | Uid int `json:"uid" description:"上传者用户id"` 20 | CreatedAt *gtime.Time `json:"createdAt" description:""` 21 | UpdatedAt *gtime.Time `json:"updatedAt" description:""` 22 | Remark string `json:"remark" description:""` 23 | } 24 | -------------------------------------------------------------------------------- /internal/model/entity/dict.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Dict is the golang structure for table dict. 12 | type Dict struct { 13 | Id uint `json:"id" description:"参数主键"` 14 | ConfigName string `json:"configName" description:"参数名称"` 15 | ConfigKey string `json:"configKey" description:"参数键名"` 16 | ConfigValue string `json:"configValue" description:"参数键值"` 17 | ConfigType string `json:"configType" description:"字典类型"` 18 | CreateBy uint `json:"createBy" description:"创建者"` 19 | UpdateBy uint `json:"updateBy" description:"更新者"` 20 | Remark string `json:"remark" description:"备注"` 21 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 22 | UpdatedAt *gtime.Time `json:"updatedAt" description:"修改时间"` 23 | } 24 | -------------------------------------------------------------------------------- /internal/model/do/user.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // User is the golang structure of table user for DAO operations like Where/Data. 13 | type User struct { 14 | g.Meta `orm:"table:user, do:true"` 15 | Id interface{} // 16 | Username interface{} // 17 | Password interface{} // 18 | Nickname interface{} // 19 | Email interface{} // 20 | Phone interface{} // 21 | Status interface{} // 1正常2禁用3注销 22 | ClientAgent interface{} // 注册clientAgen头 23 | Ip interface{} // IP 24 | RoleId interface{} // 1用户3代理2管理 25 | CreatedAt *gtime.Time // 26 | UpdatedAt *gtime.Time // 27 | PRoleId interface{} // 28 | Pid interface{} // 29 | PUsername interface{} // 30 | RoleName interface{} // 31 | PRoleName interface{} // 32 | } 33 | -------------------------------------------------------------------------------- /internal/model/entity/provinces.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Provinces is the golang structure for table provinces. 12 | type Provinces struct { 13 | Id int64 `json:"id" description:"省市区ID"` 14 | Title string `json:"title" description:"栏目名称"` 15 | Pinyin string `json:"pinyin" description:"拼音"` 16 | Lng string `json:"lng" description:"经度"` 17 | Lat string `json:"lat" description:"纬度"` 18 | Pid int64 `json:"pid" description:"父栏目"` 19 | Level int `json:"level" description:"关系树等级"` 20 | Tree string `json:"tree" description:"关系"` 21 | Sort int `json:"sort" description:"排序"` 22 | Status int `json:"status" description:"状态"` 23 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 24 | UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` 25 | } 26 | -------------------------------------------------------------------------------- /internal/controller/file/file.go: -------------------------------------------------------------------------------- 1 | package file 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vfile" 6 | "goframe-starter/internal/service/fileService" 7 | ) 8 | 9 | type File struct{} 10 | 11 | var Ctrl = new(File) 12 | 13 | func (u *File) AddFile(ctx context.Context, req *vfile.AddFileReq) (res *vfile.AddFileRes, err error) { 14 | return fileService.AddFile(ctx, req) 15 | } 16 | 17 | func (u *File) DeleteFile(ctx context.Context, req *vfile.DeleteFileReq) (res *vfile.DeleteFileRes, err error) { 18 | return fileService.DeleteFile(ctx, req) 19 | } 20 | 21 | func (u *File) UpdateFile(ctx context.Context, req *vfile.UpdateFileReq) (res *vfile.UpdateFileRes, err error) { 22 | return fileService.UpdateFile(ctx, req) 23 | } 24 | 25 | func (u *File) ListFile(ctx context.Context, req *vfile.ListFileReq) (res *vfile.ListFileRes, err error) { 26 | return fileService.ListFile(ctx, req) 27 | } 28 | 29 | func (u *File) OneFile(ctx context.Context, req *vfile.OneFileReq) (res *vfile.OneFileRes, err error) { 30 | return fileService.OneFile(ctx, req) 31 | } 32 | 33 | func (u *File) UploadChunk(ctx context.Context, req *vfile.UploadChunkReq) (res *vfile.UploadChunkRes, err error) { 34 | return fileService.UploadChunk(ctx, req) 35 | } 36 | -------------------------------------------------------------------------------- /internal/model/entity/login_log.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // LoginLog is the golang structure for table login_log. 12 | type LoginLog struct { 13 | Id int `json:"id" description:""` 14 | Uid int `json:"uid" description:""` 15 | Username string `json:"username" description:""` 16 | Ip string `json:"ip" description:""` 17 | CreatedAt *gtime.Time `json:"createdAt" description:""` 18 | UpdatedAt *gtime.Time `json:"updatedAt" description:""` 19 | ClientAgent string `json:"clientAgent" description:"注册clientAgen头"` 20 | RoleId int `json:"roleId" description:"1用户2代理3管理"` 21 | PRoleId int `json:"pRoleId" description:""` 22 | RoleName string `json:"roleName" description:""` 23 | Pid int `json:"pid" description:""` 24 | PUsername string `json:"pUsername" description:""` 25 | } 26 | -------------------------------------------------------------------------------- /internal/controller/dict/dict.go: -------------------------------------------------------------------------------- 1 | package dict 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vdict" 6 | "goframe-starter/internal/service/dictService" 7 | ) 8 | 9 | type Dict struct{} 10 | 11 | var Ctrl = new(Dict) 12 | 13 | func (u *Dict) AddDict(ctx context.Context, req *vdict.AddDictReq) (res *vdict.AddDictRes, err error) { 14 | return dictService.AddDict(ctx, req) 15 | } 16 | 17 | func (u *Dict) DeleteDict(ctx context.Context, req *vdict.DeleteDictReq) (res *vdict.DeleteDictRes, err error) { 18 | return dictService.DeleteDict(ctx, req) 19 | } 20 | 21 | func (u *Dict) UpdateDict(ctx context.Context, req *vdict.UpdateDictReq) (res *vdict.UpdateDictRes, err error) { 22 | return dictService.UpdateDict(ctx, req) 23 | } 24 | 25 | func (u *Dict) ListDict(ctx context.Context, req *vdict.ListDictReq) (res *vdict.ListDictRes, err error) { 26 | return dictService.ListDict(ctx, req) 27 | } 28 | 29 | func (u *Dict) OneDict(ctx context.Context, req *vdict.OneDictReq) (res *vdict.OneDictRes, err error) { 30 | return dictService.OneDict(ctx, req) 31 | } 32 | 33 | func (u *Dict) ListDictByType(ctx context.Context, req *vdict.ListDictByTypeReq) (res *vdict.ListDictByTypeRes, err error) { 34 | return dictService.ListDictByType(ctx, req.ConfigType) 35 | } 36 | -------------------------------------------------------------------------------- /internal/controller/role/role.go: -------------------------------------------------------------------------------- 1 | package role 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vrole" 6 | "goframe-starter/internal/service/roleService" 7 | ) 8 | 9 | type Role struct{} 10 | 11 | var Ctrl = new(Role) 12 | 13 | func (u *Role) AddRole(ctx context.Context, req *vrole.AddRoleReq) (res *vrole.AddRoleRes, err error) { 14 | return roleService.AddRole(ctx, req) 15 | } 16 | 17 | func (u *Role) DeleteRole(ctx context.Context, req *vrole.DeleteRoleReq) (res *vrole.DeleteRoleRes, err error) { 18 | return roleService.DeleteRole(ctx, req) 19 | } 20 | 21 | func (u *Role) UpdateRole(ctx context.Context, req *vrole.UpdateRoleReq) (res *vrole.UpdateRoleRes, err error) { 22 | return roleService.UpdateRole(ctx, req) 23 | } 24 | 25 | func (u *Role) ListRole(ctx context.Context, req *vrole.ListRoleReq) (res *vrole.ListRoleRes, err error) { 26 | return roleService.ListRole(ctx, req) 27 | } 28 | 29 | func (u *Role) OneRole(ctx context.Context, req *vrole.OneRoleReq) (res *vrole.OneRoleRes, err error) { 30 | return roleService.OneRole(ctx, req) 31 | } 32 | 33 | func (u *Role) ListRoleForSelect(ctx context.Context, req *vrole.ListRoleForSelectReq) (res *vrole.ListRoleForSelectRes, err error) { 34 | return roleService.ListRoleForSelect(ctx, req) 35 | } 36 | -------------------------------------------------------------------------------- /internal/service/regionService/region.go: -------------------------------------------------------------------------------- 1 | package regionService 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vregion" 6 | "goframe-starter/internal/dao" 7 | "goframe-starter/internal/model/entity" 8 | "goframe-starter/utility/xcache" 9 | ) 10 | 11 | func GetTreeList(ctx context.Context, req *vregion.ListTreeReq) (res *vregion.ListTreeRes, err error) { 12 | value, err := xcache.Instance.GetOrSetFunc(ctx, "xcache:region", func(ctx context.Context) (value interface{}, err error) { 13 | var list []*entity.Provinces 14 | err = dao.Provinces.Ctx(ctx).Scan(&list) 15 | if err != nil { 16 | return nil, err 17 | } 18 | res = &vregion.ListTreeRes{ 19 | List: GenTreeList(list, 0), 20 | } 21 | return res, nil 22 | }, 0) 23 | if err != nil { 24 | return nil, err 25 | } 26 | err = value.Scan(&res) 27 | if err != nil { 28 | return nil, err 29 | } 30 | return 31 | } 32 | 33 | func GenTreeList(list []*entity.Provinces, pid int64) (res []*vregion.TreeItem) { 34 | res = make([]*vregion.TreeItem, 0) 35 | for _, item := range list { 36 | if item.Pid == pid { 37 | var obj = &vregion.TreeItem{ 38 | Provinces: item, 39 | } 40 | obj.Children = GenTreeList(list, item.Id) 41 | res = append(res, obj) 42 | } 43 | } 44 | return 45 | } 46 | -------------------------------------------------------------------------------- /internal/controller/api/api.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vapi" 6 | "goframe-starter/internal/service/apiService" 7 | ) 8 | 9 | type Api struct{} 10 | 11 | var Ctrl = new(Api) 12 | 13 | func (u *Api) AddApi(ctx context.Context, req *vapi.AddApiReq) (res *vapi.AddApiRes, err error) { 14 | return apiService.AddApi(ctx, req) 15 | } 16 | 17 | func (u *Api) DeleteApi(ctx context.Context, req *vapi.DeleteApiReq) (res *vapi.DeleteApiRes, err error) { 18 | return apiService.DeleteApi(ctx, req) 19 | } 20 | 21 | func (u *Api) UpdateApi(ctx context.Context, req *vapi.UpdateApiReq) (res *vapi.UpdateApiRes, err error) { 22 | return apiService.UpdateApi(ctx, req) 23 | } 24 | 25 | func (u *Api) ListApi(ctx context.Context, req *vapi.ListApiReq) (res *vapi.ListApiRes, err error) { 26 | return apiService.ListApi(ctx, req) 27 | } 28 | 29 | func (u *Api) OneApi(ctx context.Context, req *vapi.OneApiReq) (res *vapi.OneApiRes, err error) { 30 | return apiService.OneApi(ctx, req) 31 | } 32 | 33 | func (u *Api) AddApiForRole(ctx context.Context, req *vapi.ApiForRoleReq) (res *vapi.ApiForRoleRes, err error) { 34 | return apiService.AddApiForRole(ctx, req) 35 | } 36 | 37 | func (u *Api) GetApiByRole(ctx context.Context, req *vapi.ApiByRoleReq) (res *vapi.ApiByRoleRes, err error) { 38 | return apiService.GetApiByRole(ctx, req) 39 | } 40 | -------------------------------------------------------------------------------- /api/vdict/dict.go: -------------------------------------------------------------------------------- 1 | package vdict 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "goframe-starter/api/vcommon" 6 | "goframe-starter/internal/model/entity" 7 | ) 8 | 9 | type AddDictReq struct { 10 | g.Meta `tags:"字典" method:"post" path:"/dict" sm:"添加" dc:"添加字典" ` 11 | *entity.Dict 12 | } 13 | type AddDictRes struct{} 14 | 15 | type DeleteDictReq struct { 16 | g.Meta `tags:"字典" method:"delete" path:"/dict" sm:"删除" dc:"删除字典" ` 17 | Id uint `json:"id" v:"required" description:""` 18 | } 19 | type DeleteDictRes struct{} 20 | 21 | type UpdateDictReq struct { 22 | g.Meta `tags:"字典" method:"put" path:"/dict" sm:"修改" dc:"更新字典" ` 23 | *entity.Dict 24 | } 25 | type UpdateDictRes struct{} 26 | 27 | type ListDictReq struct { 28 | g.Meta `tags:"字典" method:"get" path:"/dict/list" sm:"列表" dc:"字典列表" ` 29 | *entity.Dict 30 | *vcommon.CommonPageReq 31 | } 32 | type ListDictRes struct { 33 | List []*entity.Dict `json:"list"` 34 | *vcommon.CommonPageRes 35 | } 36 | 37 | type OneDictReq struct { 38 | g.Meta `tags:"字典" method:"get" path:"/dict" sm:"单个" dc:"字典" ` 39 | Id uint `json:"id" v:"required" description:""` 40 | } 41 | type OneDictRes *entity.Dict 42 | 43 | type ListDictByTypeReq struct { 44 | g.Meta `tags:"字典" method:"get" path:"/dict/list/type" sm:"列表" dc:"字典列表(按类型区分)" ` 45 | ConfigType string `json:"configType" description:"字典类型"` 46 | } 47 | type ListDictByTypeRes struct { 48 | List []*entity.Dict `json:"list"` 49 | } 50 | -------------------------------------------------------------------------------- /api/vrole/role.go: -------------------------------------------------------------------------------- 1 | package vrole 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "goframe-starter/api/vcommon" 6 | "goframe-starter/internal/model/entity" 7 | ) 8 | 9 | type AddRoleReq struct { 10 | g.Meta `tags:"角色" method:"post" path:"/role" sm:"添加" dc:"添加角色" ` 11 | *entity.Role 12 | } 13 | type AddRoleRes struct{} 14 | 15 | type DeleteRoleReq struct { 16 | g.Meta `tags:"角色" method:"delete" path:"/role" sm:"添加" dc:"删除角色" ` 17 | Id uint `json:"id" v:"required" description:""` 18 | } 19 | type DeleteRoleRes struct{} 20 | 21 | type UpdateRoleReq struct { 22 | g.Meta `tags:"角色" method:"put" path:"/role" sm:"添加" dc:"更新角色" ` 23 | *entity.Role 24 | } 25 | type UpdateRoleRes struct{} 26 | 27 | type ListRoleReq struct { 28 | g.Meta `tags:"角色" method:"get" path:"/role/list" sm:"列表" dc:"角色列表" ` 29 | *entity.Role 30 | *vcommon.CommonPageReq 31 | } 32 | type ListRoleRes struct { 33 | List []*entity.Role `json:"list"` 34 | *vcommon.CommonPageRes 35 | } 36 | 37 | type OneRoleReq struct { 38 | g.Meta `tags:"角色" method:"get" path:"/role" sm:"单个" dc:"角色" ` 39 | Id uint `json:"id" v:"required" description:""` 40 | } 41 | type OneRoleRes *entity.Role 42 | type ListRoleForSelectReq struct { 43 | g.Meta `tags:"角色" method:"get" path:"/role/list/select" sm:"列表" dc:"角色下拉选择框" ` 44 | //Id uint `json:"id" v:"required" description:""` 45 | } 46 | type ListRoleForSelectRes struct { 47 | List []*entity.Role `json:"list"` 48 | } 49 | -------------------------------------------------------------------------------- /internal/controller/menu/menu.go: -------------------------------------------------------------------------------- 1 | package menu 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vmenu" 6 | "goframe-starter/internal/service/menuService" 7 | ) 8 | 9 | type Menu struct{} 10 | 11 | var Ctrl = new(Menu) 12 | 13 | func (u *Menu) AddMenu(ctx context.Context, req *vmenu.AddMenuReq) (res *vmenu.AddMenuRes, err error) { 14 | return menuService.AddMenu(ctx, req) 15 | } 16 | 17 | func (u *Menu) DeleteMenu(ctx context.Context, req *vmenu.DeleteMenuReq) (res *vmenu.DeleteMenuRes, err error) { 18 | return menuService.DeleteMenu(ctx, req) 19 | } 20 | 21 | func (u *Menu) UpdateMenu(ctx context.Context, req *vmenu.UpdateMenuReq) (res *vmenu.UpdateMenuRes, err error) { 22 | return menuService.UpdateMenu(ctx, req) 23 | } 24 | 25 | func (u *Menu) ListTreeMenus(ctx context.Context, req *vmenu.ListTreeMenuReq) (res *vmenu.ListTreeMenuRes, err error) { 26 | return menuService.ListTreeMenus(ctx, req) 27 | } 28 | 29 | func (u *Menu) ListVueMenus(ctx context.Context, req *vmenu.VueMenuReq) (res *vmenu.VueMenuRes, err error) { 30 | return menuService.ListVueMenus(ctx, req) 31 | } 32 | 33 | func (u *Menu) AddMenuForRole(ctx context.Context, req *vmenu.MenuForRoleReq) (res *vmenu.MenuForRoleRes, err error) { 34 | return menuService.AddMenuForRole(ctx, req) 35 | } 36 | 37 | func (u *Menu) GetMenuByRole(ctx context.Context, req *vmenu.MenuByRoleReq) (res *vmenu.MenuByRoleRes, err error) { 38 | return menuService.GetMenuByRole(ctx, req) 39 | } 40 | -------------------------------------------------------------------------------- /internal/middleware/middleware.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/goflyfox/gtoken/gtoken" 5 | "github.com/gogf/gf/v2/net/ghttp" 6 | "github.com/gogf/gf/v2/os/gctx" 7 | "github.com/gogf/gf/v2/text/gstr" 8 | "github.com/yudeguang/ratelimit" 9 | "goframe-starter/api/vapi" 10 | "goframe-starter/internal/model/entity" 11 | "goframe-starter/internal/service/apiService" 12 | "strings" 13 | "time" 14 | ) 15 | 16 | func DefaultCORS(r *ghttp.Request) { 17 | r.Response.CORSDefault() 18 | r.Middleware.Next() 19 | } 20 | 21 | var rule *ratelimit.Rule 22 | 23 | func RequestIpLimit(r *ghttp.Request) { 24 | ip := r.GetClientIp() 25 | if rule == nil { 26 | rule = ratelimit.NewRule() 27 | rule.AddRule(time.Hour, 10000) 28 | rule.AddRule(time.Minute, 600) 29 | rule.AddRule(time.Second, 60) 30 | } 31 | ok := rule.AllowVisit(ip) 32 | if !ok { 33 | g2 := gtoken.Resp{ 34 | Code: -999, 35 | Msg: "YOUR ACCESS IS ABNORMAL", 36 | } 37 | r.Response.WriteJsonExit(g2) 38 | 39 | } 40 | r.Middleware.Next() 41 | } 42 | 43 | func AutoAddApi(r *ghttp.Request) { 44 | r.Middleware.Next() 45 | if gstr.PosI(r.URL.Path, "/api/") == 0 { 46 | var ctx = gctx.New() 47 | flag := apiService.CheckApiExists(ctx, r.URL.Path, r.Method) 48 | if flag { 49 | return 50 | } 51 | // 自动添加api 52 | var req = &vapi.AddApiReq{ 53 | Api: &entity.Api{ 54 | Url: r.URL.Path, 55 | Method: r.Method, 56 | Group: strings.Join(strings.Split(r.URL.Path, "/")[:3], "/"), 57 | }, 58 | } 59 | _, _ = apiService.AddApi(ctx, req) 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /internal/model/entity/user.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // User is the golang structure for table user. 12 | type User struct { 13 | Id uint `json:"id" description:""` 14 | Username string `json:"username" description:""` 15 | Password string `json:"password" description:""` 16 | Nickname string `json:"nickname" description:""` 17 | Email string `json:"email" description:""` 18 | Phone string `json:"phone" description:""` 19 | Status int `json:"status" description:"1正常2禁用3注销"` 20 | ClientAgent string `json:"clientAgent" description:"注册clientAgen头"` 21 | Ip string `json:"ip" description:"IP"` 22 | RoleId int `json:"roleId" description:"1用户3代理2管理"` 23 | CreatedAt *gtime.Time `json:"createdAt" description:""` 24 | UpdatedAt *gtime.Time `json:"updatedAt" description:""` 25 | PRoleId int `json:"pRoleId" description:""` 26 | Pid int `json:"pid" description:""` 27 | PUsername string `json:"pUsername" description:""` 28 | RoleName string `json:"roleName" description:""` 29 | PRoleName string `json:"pRoleName" description:""` 30 | } 31 | -------------------------------------------------------------------------------- /internal/controller/user/user.go: -------------------------------------------------------------------------------- 1 | package user 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vuser" 6 | "goframe-starter/internal/service/userService" 7 | ) 8 | 9 | type User struct{} 10 | 11 | var Ctrl = new(User) 12 | 13 | func (u *User) AddUser(ctx context.Context, req *vuser.AddUserReq) (res *vuser.AddUserRes, err error) { 14 | return userService.AddUser(ctx, req) 15 | } 16 | 17 | func (u *User) DeleteUser(ctx context.Context, req *vuser.DeleteUserReq) (res *vuser.DeleteUserRes, err error) { 18 | return userService.DeleteUser(ctx, req) 19 | } 20 | 21 | func (u *User) UpdateUser(ctx context.Context, req *vuser.UpdateUserReq) (res *vuser.UpdateUserRes, err error) { 22 | return userService.UpdateUser(ctx, req) 23 | } 24 | 25 | func (u *User) UpdateUserPassword(ctx context.Context, req *vuser.UpdateUserPasswordReq) (res *vuser.UpdateUserPasswordRes, err error) { 26 | return userService.UpdateUserPassword(ctx, req) 27 | } 28 | 29 | func (u *User) ListUser(ctx context.Context, req *vuser.ListUserReq) (res *vuser.ListUserRes, err error) { 30 | return userService.ListUser(ctx, req) 31 | } 32 | 33 | func (u *User) OneUser(ctx context.Context, req *vuser.OneUserReq) (res *vuser.OneUserRes, err error) { 34 | return userService.OneUser(ctx, req) 35 | } 36 | 37 | func (u *User) UserInfo(ctx context.Context, req *vuser.UserInfoReq) (res *vuser.UserInfoRes, err error) { 38 | return userService.UserInfo(ctx, req) 39 | } 40 | 41 | func (u *User) TreeListUserScope(ctx context.Context, req *vuser.TreeListUserReq) (res *vuser.TreeListUserRes, err error) { 42 | return userService.TreeListUserScope(ctx, req) 43 | } 44 | -------------------------------------------------------------------------------- /internal/model/do/menu.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package do 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/frame/g" 9 | "github.com/gogf/gf/v2/os/gtime" 10 | ) 11 | 12 | // Menu is the golang structure of table menu for DAO operations like Where/Data. 13 | type Menu struct { 14 | g.Meta `orm:"table:menu, do:true"` 15 | Id interface{} // 菜单ID 16 | Pid interface{} // 父菜单ID,0表示根级 17 | Title interface{} // 菜单名称 18 | Name interface{} // 名称编码 19 | Path interface{} // 路由地址 20 | Icon interface{} // 菜单图标 21 | Type interface{} // 菜单类型(1目录 2菜单) 22 | Redirect interface{} // 重定向地址 23 | Permissions interface{} // 菜单包含权限集合 24 | PermissionName interface{} // 权限名称 25 | Component interface{} // 组件路径 26 | AlwaysShow interface{} // 取消自动计算根路由模式 1是2否 27 | ActiveMenu interface{} // 高亮菜单编码 28 | IsRoot interface{} // 是否跟路由 29 | IsFrame interface{} // 是否跳转外链 30 | FrameSrc interface{} // iframe地址 31 | KeepAlive interface{} // 缓存该路由,1是2否 32 | Hidden interface{} // 是否隐藏,1是2否 33 | Affix interface{} // 是否固定 34 | Level interface{} // 关系树等级 1根2子3孙 35 | Tree interface{} // 关系树 36 | Sort interface{} // 排序 37 | Remark interface{} // 备注 38 | Status interface{} // 菜单状态 39 | CreatedAt *gtime.Time // 创建时间 40 | UpdatedAt *gtime.Time // 更新时间 41 | } 42 | -------------------------------------------------------------------------------- /internal/service/buttonService/button_test.go: -------------------------------------------------------------------------------- 1 | package buttonService 2 | 3 | import ( 4 | "fmt" 5 | _ "github.com/gogf/gf/contrib/drivers/mysql/v2" 6 | "github.com/gogf/gf/v2/frame/g" 7 | "github.com/gogf/gf/v2/os/gctx" 8 | "github.com/gogf/gf/v2/os/gfile" 9 | "github.com/gogf/gf/v2/text/gstr" 10 | "goframe-starter/internal/dao" 11 | "testing" 12 | "time" 13 | ) 14 | 15 | func TestGroup(t *testing.T) { 16 | var ctx = gctx.New() 17 | value, err := dao.Button.Ctx(ctx).Fields("COUNT(*) total,menu_id").Group("menu_id").All() 18 | if err != nil { 19 | return 20 | } 21 | g.Dump(value) 22 | } 23 | 24 | func Test_aaa(t *testing.T) { 25 | var ctx = gctx.New() 26 | var folder = time.Now().Format("2006-01-02") 27 | var dirPath = g.Cfg().MustGet(ctx, "server.uploadRoot").String() + "/" + folder 28 | err := gfile.Remove(gfile.MainPkgPath() + "/" + dirPath + "/" + "cwbcxlyrbijkzaspxn.sql") 29 | if err != nil { 30 | g.Dump(err) 31 | return 32 | } 33 | var ( 34 | haystack = `/api/sdf/nn` 35 | needle = `/api/` 36 | result1 = gstr.PosI(haystack, needle) 37 | ) 38 | fmt.Println(result1) 39 | } 40 | 41 | func Test_b(t *testing.T) { 42 | // leftjoin跟innerjoin返回的结果是一样的 43 | array, err := g.Model("user u").LeftJoin("user_relation ud", "u.id=ud.user_id").Fields("u.id").Where("ud.user_id", 8).Array() 44 | if err != nil { 45 | return 46 | } 47 | g.Dump(array) 48 | array2, err := g.Model("user u").InnerJoin("user_relation ud", "u.id=ud.user_id").Fields("u.id").Where("ud.user_id", 8).Array() 49 | if err != nil { 50 | return 51 | } 52 | g.Dump(array2) 53 | } 54 | func Test111(t *testing.T) { 55 | g.Dump(gfile.Ext("go1.21.2.linux-amd64.tar.gz")) 56 | } 57 | -------------------------------------------------------------------------------- /internal/controller/button/button.go: -------------------------------------------------------------------------------- 1 | package button 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vbutton" 6 | "goframe-starter/internal/service/buttonService" 7 | ) 8 | 9 | type Button struct{} 10 | 11 | var Ctrl = new(Button) 12 | 13 | func (u *Button) AddButton(ctx context.Context, req *vbutton.AddButtonReq) (res *vbutton.AddButtonRes, err error) { 14 | return buttonService.AddButton(ctx, req) 15 | } 16 | 17 | func (u *Button) DeleteButton(ctx context.Context, req *vbutton.DeleteButtonReq) (res *vbutton.DeleteButtonRes, err error) { 18 | return buttonService.DeleteButton(ctx, req) 19 | } 20 | 21 | func (u *Button) UpdateButton(ctx context.Context, req *vbutton.UpdateButtonReq) (res *vbutton.UpdateButtonRes, err error) { 22 | return buttonService.UpdateButton(ctx, req) 23 | } 24 | 25 | func (u *Button) ListButton(ctx context.Context, req *vbutton.ListButtonReq) (res *vbutton.ListButtonRes, err error) { 26 | return buttonService.ListButton(ctx, req) 27 | } 28 | 29 | func (u *Button) OneButton(ctx context.Context, req *vbutton.OneButtonReq) (res *vbutton.OneButtonRes, err error) { 30 | return buttonService.OneButton(ctx, req) 31 | } 32 | 33 | func (u *Button) AddButtonForRole(ctx context.Context, req *vbutton.ButtonForRoleReq) (res *vbutton.ButtonForRoleRes, err error) { 34 | return buttonService.AddButtonForRole(ctx, req) 35 | } 36 | 37 | func (u *Button) GetButtonByRole(ctx context.Context, req *vbutton.ButtonByRoleReq) (res *vbutton.ButtonByRoleRes, err error) { 38 | return buttonService.GetButtonByRole(ctx, req) 39 | } 40 | 41 | func (u *Button) ButtonWhitelist(ctx context.Context, req *vbutton.ButtonWhitelistReq) (res *vbutton.ButtonWhitelistRes, err error) { 42 | return buttonService.ButtonWhitelist(ctx, req) 43 | } 44 | -------------------------------------------------------------------------------- /api/vapi/api.go: -------------------------------------------------------------------------------- 1 | package vapi 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "goframe-starter/api/vcommon" 6 | "goframe-starter/internal/model/entity" 7 | ) 8 | 9 | type AddApiReq struct { 10 | g.Meta `tags:"api" method:"post" path:"/api" sm:"添加" dc:"添加api" ` 11 | *entity.Api 12 | } 13 | type AddApiRes struct{} 14 | 15 | type DeleteApiReq struct { 16 | g.Meta `tags:"api" method:"delete" path:"/api" sm:"添加" dc:"删除api" ` 17 | Id uint `json:"id" v:"required" description:""` 18 | } 19 | type DeleteApiRes struct{} 20 | 21 | type UpdateApiReq struct { 22 | g.Meta `tags:"api" method:"put" path:"/api" sm:"修改" dc:"更新api" ` 23 | *entity.Api 24 | } 25 | type UpdateApiRes struct{} 26 | 27 | type ListApiReq struct { 28 | g.Meta `tags:"api" method:"get" path:"/api/list" sm:"列表" dc:"api列表" ` 29 | *entity.Api 30 | *vcommon.CommonPageReq 31 | } 32 | type ListApiRes struct { 33 | List []*entity.Api `json:"list"` 34 | *vcommon.CommonPageRes 35 | } 36 | 37 | type OneApiReq struct { 38 | g.Meta `tags:"api" method:"get" path:"/api" sm:"单个" dc:"api" ` 39 | Id uint `json:"id" v:"required" description:""` 40 | } 41 | type OneApiRes *entity.Api 42 | 43 | type ApiForRoleReq struct { 44 | g.Meta `tags:"api" method:"post" path:"/api/role" sm:"角色绑定api" dc:"为角色绑定api" ` 45 | RoleId uint `json:"roleId"` 46 | Apis []*entity.Api `json:"apis"` 47 | } 48 | 49 | type ApiForRoleRes struct{} 50 | 51 | type ApiByRoleReq struct { 52 | g.Meta `tags:"api" method:"get" path:"/api/role" sm:"角色绑定api" dc:"获取角色绑定的api" ` 53 | RoleId uint `json:"roleId"` 54 | } 55 | type ApiByRole struct { 56 | Method string `json:"method" description:""` 57 | Url string `json:"url" description:""` 58 | } 59 | type ApiByRoleRes struct { 60 | List []*ApiByRole `json:"list"` 61 | } 62 | -------------------------------------------------------------------------------- /internal/controller/log/log.go: -------------------------------------------------------------------------------- 1 | package log 2 | 3 | import ( 4 | "context" 5 | "github.com/gogf/gf/v2/util/gconv" 6 | "goframe-starter/api/vcommon" 7 | "goframe-starter/api/vlog" 8 | "goframe-starter/internal/consts" 9 | "goframe-starter/internal/dao" 10 | "goframe-starter/internal/model/entity" 11 | ) 12 | 13 | type Log struct{} 14 | 15 | var Ctrl = new(Log) 16 | 17 | func (u *Log) ListLoginLog(ctx context.Context, req *vlog.ListLoginLogReq) (res *vlog.ListLoginLogRes, err error) { 18 | res = &vlog.ListLoginLogRes{ 19 | List: make([]*entity.LoginLog, 0), 20 | CommonPageRes: &vcommon.CommonPageRes{}, 21 | } 22 | res.PageIndex = req.PageIndex 23 | res.PageSize = req.PageSize 24 | var cols = dao.LoginLog.Columns() 25 | var model = dao.LoginLog.Ctx(ctx).OrderDesc(cols.UpdatedAt) 26 | if req.Username != "" { 27 | model = model.WhereLike(cols.Username, "%"+req.Username+"%") 28 | } 29 | if req.Ip != "" { 30 | model = model.Where(cols.Ip, req.Ip) 31 | } 32 | if req.TimeBetween != nil && len(req.TimeBetween) == 2 { 33 | model = model.WhereBetween(cols.UpdatedAt, req.TimeBetween[0], req.TimeBetween[1]) 34 | } 35 | // 超级管理员返回全部用户,其他角色返回自己和自己的下级 36 | var roleId = gconv.Int(ctx.Value("roleId")) 37 | var uid = gconv.Int(ctx.Value("uid")) 38 | if roleId == consts.Role_Root_Code { 39 | } else { 40 | array, err := dao.UserRelation.Ctx(ctx).Where(dao.UserRelation.Columns().PUserId, uid).Array() 41 | if err != nil { 42 | return nil, err 43 | } 44 | var slice []int 45 | for _, value := range array { 46 | slice = append(slice, gconv.Int(value)) 47 | } 48 | slice = append(slice, uid) 49 | model = model.WhereIn(cols.Uid, slice) 50 | } 51 | err = model.Page(req.PageIndex, req.PageSize).ScanAndCount(&res.List, &res.Total, false) 52 | if err != nil { 53 | return nil, err 54 | } 55 | return 56 | } 57 | -------------------------------------------------------------------------------- /api/votp/otp.go: -------------------------------------------------------------------------------- 1 | package votp 2 | 3 | import "github.com/gogf/gf/v2/frame/g" 4 | 5 | type AddOtpReq struct { 6 | g.Meta `tags:"OTP校验码" method:"post" path:"/otp" sm:"添加" dc:"添加" ` 7 | Secret string `json:"secret" v:"required"` 8 | Code string `json:"code" v:"required" dc:"输入的校验码"` 9 | } 10 | type AddOtpRes struct{} 11 | 12 | type UpdateOtpReq struct { 13 | g.Meta `tags:"OTP校验码" method:"put" path:"/otp" sm:"更新" dc:"更新" ` 14 | Secret string `json:"secret" v:"required"` 15 | Code string `json:"code" v:"required" dc:"输入的校验码"` 16 | } 17 | type UpdateOtpRes struct{} 18 | 19 | type UpdateOtpStatusReq struct { 20 | g.Meta `tags:"OTP校验码" method:"put" path:"/otp/status" sm:"更新" dc:"更新开启与否" ` 21 | Status int `json:"status" ` 22 | } 23 | type UpdateOtpStatusRes struct{} 24 | 25 | type OtpReq struct { 26 | g.Meta `tags:"OTP校验码" method:"get" path:"/otp" sm:"获取" dc:"获取当前用户secret" ` 27 | } 28 | type OtpRes struct { 29 | Secret string `json:"secret"` 30 | Url string `json:"url"` 31 | } 32 | 33 | type OtpCheckReq struct { 34 | g.Meta `tags:"OTP校验码" method:"get" path:"/otp/check" sm:"获取" dc:"获取当前用户是否开启otp验证" ` 35 | } 36 | type OtpCheckRes struct { 37 | IsOpened bool `json:"isOpened"` 38 | IsSetted bool `json:"isSetted" dc:"是否设置了otp校验"` 39 | } 40 | 41 | type OtpCheckByUsernameReq struct { 42 | g.Meta `tags:"OTP校验码" method:"get" path:"/otp/username" sm:"获取" dc:"通过用户名获取当前用户是否开启otp验证,登录时用" ` 43 | Username string `json:"username" v:"required" description:""` 44 | } 45 | type OtpCheckByUsernameRes struct { 46 | IsOpened bool `json:"isOpened"` 47 | } 48 | 49 | type OtpValidateReq struct { 50 | g.Meta `tags:"OTP校验码" method:"post" path:"/otp/validate" sm:"校验" dc:"otp验证" ` 51 | Username string `json:"username" description:""` 52 | Code string `json:"code" v:"required" dc:"输入的校验码"` 53 | } 54 | type OtpValidateRes struct { 55 | } 56 | -------------------------------------------------------------------------------- /api/vbutton/button.go: -------------------------------------------------------------------------------- 1 | package vbutton 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "goframe-starter/api/vcommon" 6 | "goframe-starter/internal/model/entity" 7 | ) 8 | 9 | type AddButtonReq struct { 10 | g.Meta `tags:"按钮" method:"post" path:"/button" sm:"添加" dc:"添加按钮" ` 11 | *entity.Button 12 | } 13 | type AddButtonRes struct{} 14 | 15 | type DeleteButtonReq struct { 16 | g.Meta `tags:"按钮" method:"delete" path:"/button" sm:"添加" dc:"删除按钮" ` 17 | Id uint `json:"id" v:"required" description:""` 18 | } 19 | type DeleteButtonRes struct{} 20 | 21 | type UpdateButtonReq struct { 22 | g.Meta `tags:"按钮" method:"put" path:"/button" sm:"修改" dc:"更新按钮" ` 23 | *entity.Button 24 | } 25 | type UpdateButtonRes struct{} 26 | 27 | type ListButtonReq struct { 28 | g.Meta `tags:"按钮" method:"get" path:"/button/list" sm:"列表" dc:"按钮列表" ` 29 | *entity.Button 30 | *vcommon.CommonPageReq 31 | } 32 | type ListButtonRes struct { 33 | List []*entity.Button `json:"list"` 34 | *vcommon.CommonPageRes 35 | } 36 | 37 | type OneButtonReq struct { 38 | g.Meta `tags:"按钮" method:"get" path:"/button" sm:"单个" dc:"按钮" ` 39 | Id uint `json:"id" v:"required" description:""` 40 | } 41 | type OneButtonRes *entity.Button 42 | 43 | type ButtonForRoleReq struct { 44 | g.Meta `tags:"按钮" method:"post" path:"/button/role" sm:"角色绑定按钮" dc:"为角色绑定按钮" ` 45 | RoleId uint `json:"roleId"` 46 | ButtonIds []int `json:"buttonIds"` 47 | } 48 | 49 | type ButtonForRoleRes struct{} 50 | 51 | type ButtonByRoleReq struct { 52 | g.Meta `tags:"按钮" method:"get" path:"/button/role" sm:"角色绑定按钮" dc:"获取角色绑定的按钮" ` 53 | RoleId uint `json:"roleId"` 54 | } 55 | 56 | type ButtonByRoleRes struct { 57 | List []int `json:"list"` 58 | } 59 | 60 | type ButtonWhitelistReq struct { 61 | g.Meta `tags:"按钮" method:"get" path:"/button/whitelist" sm:"角色绑定按钮" dc:"获取当前角色绑定的按钮" ` 62 | } 63 | 64 | type ButtonWhitelistRes struct { 65 | List []int `json:"list"` 66 | } 67 | -------------------------------------------------------------------------------- /internal/cmd/cmd.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/internal/controller/api" 6 | "goframe-starter/internal/controller/button" 7 | "goframe-starter/internal/controller/dict" 8 | "goframe-starter/internal/controller/file" 9 | "goframe-starter/internal/controller/log" 10 | "goframe-starter/internal/controller/menu" 11 | "goframe-starter/internal/controller/notice" 12 | "goframe-starter/internal/controller/otp" 13 | "goframe-starter/internal/controller/region" 14 | "goframe-starter/internal/controller/role" 15 | "goframe-starter/internal/controller/user" 16 | "goframe-starter/internal/middleware" 17 | "goframe-starter/utility/xcache" 18 | "goframe-starter/utility/xcasbin" 19 | "goframe-starter/utility/xgtoken" 20 | 21 | _ "github.com/gogf/gf/contrib/drivers/mysql/v2" 22 | _ "github.com/gogf/gf/contrib/nosql/redis/v2" 23 | "github.com/gogf/gf/v2/frame/g" 24 | "github.com/gogf/gf/v2/net/ghttp" 25 | "github.com/gogf/gf/v2/os/gcmd" 26 | ) 27 | 28 | var ( 29 | Main = gcmd.Command{ 30 | Name: "main", 31 | Usage: "main", 32 | Brief: "start http server", 33 | Func: func(ctx context.Context, parser *gcmd.Parser) (err error) { 34 | s := g.Server(g.Cfg().MustGet(ctx, "server.name").String()) 35 | s.BindMiddlewareDefault(middleware.DefaultCORS, middleware.RequestIpLimit, middleware.AutoAddApi) 36 | xcasbin.Init() 37 | xcache.Init() 38 | s.Group("/", func(group *ghttp.RouterGroup) { 39 | group.Middleware(ghttp.MiddlewareHandlerResponse) 40 | group.Group("/api", func(group *ghttp.RouterGroup) { 41 | group.Bind( 42 | user.Ctrl, 43 | menu.Ctrl, 44 | role.Ctrl, 45 | button.Ctrl, 46 | region.Ctrl, 47 | dict.Ctrl, 48 | api.Ctrl, 49 | log.Ctrl, 50 | file.Ctrl, 51 | otp.Ctrl, 52 | notice.Ctrl, 53 | ) 54 | }) 55 | }) 56 | xgtoken.InitGtoken(ctx) 57 | s.Run() 58 | return nil 59 | }, 60 | } 61 | ) 62 | -------------------------------------------------------------------------------- /api/vfile/file.go: -------------------------------------------------------------------------------- 1 | package vfile 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "github.com/gogf/gf/v2/net/ghttp" 6 | "goframe-starter/api/vcommon" 7 | "goframe-starter/internal/model/entity" 8 | ) 9 | 10 | type AddFileReq struct { 11 | g.Meta `tags:"文件" method:"post" path:"/file" mime:"multipart/form-data" sm:"添加" dc:"添加文件" ` 12 | Drive string `json:"drive" description:"上传驱动:本地,ucloud"` 13 | File []*ghttp.UploadFile `json:"file" type:"file" ` 14 | } 15 | type AddFileRes struct { 16 | List []string `json:"list"` 17 | } 18 | 19 | type DeleteFileReq struct { 20 | g.Meta `tags:"文件" method:"delete" path:"/file" sm:"添加" dc:"删除文件" ` 21 | Id uint `json:"id" v:"required" description:""` 22 | } 23 | type DeleteFileRes struct{} 24 | 25 | type UpdateFileReq struct { 26 | g.Meta `tags:"文件" method:"put" path:"/file" sm:"修改" dc:"更新文件" ` 27 | *entity.File 28 | } 29 | type UpdateFileRes struct{} 30 | 31 | type ListFileReq struct { 32 | g.Meta `tags:"文件" method:"get" path:"/file/list" sm:"列表" dc:"文件列表" ` 33 | *entity.File 34 | *vcommon.CommonPageReq 35 | } 36 | type ListFileRes struct { 37 | List []*entity.File `json:"list"` 38 | *vcommon.CommonPageRes 39 | } 40 | 41 | type OneFileReq struct { 42 | g.Meta `tags:"文件" method:"get" path:"/file" sm:"单个" dc:"文件" ` 43 | Id uint `json:"id" v:"required" description:""` 44 | } 45 | type OneFileRes *entity.File 46 | 47 | type UploadChunkReq struct { 48 | g.Meta `tags:"文件" method:"post" path:"/file/chunk" mime:"multipart/form-data" sm:"添加" dc:"分片上传" ` 49 | Drive string `json:"drive" description:"上传驱动:本地,ucloud"` 50 | Chunk *ghttp.UploadFile `json:"chunk" type:"file" ` 51 | ChunkIndex int `json:"chunkIndex"` 52 | TotalChunks int `json:"totalChunks"` 53 | Temp string `json:"temp"` 54 | OriginName string `json:"originName"` 55 | Ext string `json:"ext"` 56 | Size uint64 `json:"size"` 57 | } 58 | type UploadChunkRes struct { 59 | FileUrl string `json:"fileUrl"` 60 | } 61 | -------------------------------------------------------------------------------- /utility/xgtoken/gtoken.go: -------------------------------------------------------------------------------- 1 | package xgtoken 2 | 3 | import ( 4 | "context" 5 | "github.com/goflyfox/gtoken/gtoken" 6 | "github.com/gogf/gf/v2/frame/g" 7 | "github.com/gogf/gf/v2/net/ghttp" 8 | "goframe-starter/internal/service/gtokenService" 9 | ) 10 | 11 | type GFToken struct{} 12 | 13 | var Gtoken = new(GFToken) 14 | var MyGtoken *gtoken.GfToken 15 | 16 | type GFTokenFunc interface { 17 | LoginBeforeFunc(r *ghttp.Request) (string, interface{}) 18 | //LoginAfterFunc(r *ghttp.Request, respData gtoken.Resp) 19 | //LogoutBeforeFunc(r *ghttp.Request) bool 20 | //LogoutAfterFunc(r *ghttp.Request, respData gtoken.Resp) 21 | //AuthBeforeFunc(r *ghttp.Request) bool 22 | AuthAfterFunc(r *ghttp.Request, respData gtoken.Resp) 23 | } 24 | 25 | func (s *GFToken) New(ctx context.Context, fn GFTokenFunc) *gtoken.GfToken { 26 | gfToken := >oken.GfToken{ 27 | ServerName: g.Cfg().MustGet(ctx, "server.name").String(), 28 | CacheKey: g.Cfg().MustGet(ctx, "gfToken.cacheKey").String(), 29 | CacheMode: g.Cfg().MustGet(ctx, "gfToken.cacheMode").Int8(), 30 | Timeout: g.Cfg().MustGet(ctx, "gfToken.timeOut").Int(), 31 | EncryptKey: g.Cfg().MustGet(ctx, "gfToken.encryptKey").Bytes(), 32 | MaxRefresh: g.Cfg().MustGet(ctx, "gfToken.maxRefresh").Int(), 33 | MultiLogin: g.Cfg().MustGet(ctx, "gfToken.multiLogin").Bool(), 34 | GlobalMiddleware: g.Cfg().MustGet(ctx, "gfToken.globalMiddleware").Bool(), 35 | LoginPath: g.Cfg().MustGet(ctx, "gfToken.loginPath").String(), 36 | LogoutPath: g.Cfg().MustGet(ctx, "gfToken.logoutPath").String(), 37 | AuthPaths: g.Cfg().MustGet(ctx, "gfToken.authPaths").Strings(), 38 | AuthExcludePaths: g.Cfg().MustGet(ctx, "gfToken.excludePaths").Strings(), 39 | LoginBeforeFunc: fn.LoginBeforeFunc, 40 | AuthAfterFunc: fn.AuthAfterFunc, 41 | } 42 | g.Dump(gfToken) 43 | return gfToken 44 | } 45 | 46 | func InitGtoken(ctx context.Context) { 47 | MyGtoken = Gtoken.New(ctx, gtokenService.GFtokenFnInstance) 48 | err := MyGtoken.Start() 49 | if err != nil { 50 | panic(err) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /internal/controller/notice/notice.go: -------------------------------------------------------------------------------- 1 | package notice 2 | 3 | import ( 4 | "context" 5 | "goframe-starter/api/vnotice" 6 | "goframe-starter/internal/service/noticeService" 7 | ) 8 | 9 | type Notice struct{} 10 | 11 | var Ctrl = new(Notice) 12 | 13 | func (u *Notice) AddNotice(ctx context.Context, req *vnotice.AddNoticeReq) (res *vnotice.AddNoticeRes, err error) { 14 | return noticeService.AddNotice(ctx, req) 15 | } 16 | 17 | func (u *Notice) DeleteNotice(ctx context.Context, req *vnotice.DeleteNoticeReq) (res *vnotice.DeleteNoticeRes, err error) { 18 | return noticeService.DeleteNotice(ctx, req) 19 | } 20 | 21 | func (u *Notice) UpdateNotice(ctx context.Context, req *vnotice.UpdateNoticeReq) (res *vnotice.UpdateNoticeRes, err error) { 22 | return noticeService.UpdateNotice(ctx, req) 23 | } 24 | 25 | func (u *Notice) ListNoticeForSender(ctx context.Context, req *vnotice.ListNoticeReq) (res *vnotice.ListNoticeRes, err error) { 26 | return noticeService.ListNoticeForSender(ctx, req) 27 | } 28 | 29 | func (u *Notice) OneNotice(ctx context.Context, req *vnotice.OneNoticeReq) (res *vnotice.OneNoticeRes, err error) { 30 | return noticeService.OneNotice(ctx, req) 31 | } 32 | 33 | func (u *Notice) ListNoticeForReceiver(ctx context.Context, req *vnotice.ListNoticeForReceiverReq) (res *vnotice.ListNoticeForReceiverRes, err error) { 34 | return noticeService.ListNoticeForReceiver(ctx, req) 35 | } 36 | 37 | func (u *Notice) DeleteNoticeForReceiver(ctx context.Context, req *vnotice.DeleteNoticeForReceiverReq) (res *vnotice.DeleteNoticeForReceiverRes, err error) { 38 | return noticeService.DeleteNoticeForReceiver(ctx, req) 39 | } 40 | 41 | func (u *Notice) UpdateNoticeStatusForReceiver(ctx context.Context, req *vnotice.UpdateNoticeForReceiverReq) (res *vnotice.UpdateNoticeForReceiverRes, err error) { 42 | return noticeService.UpdateNoticeStatusForReceiver(ctx, req) 43 | } 44 | 45 | func (u *Notice) GetNoticeUnreadCountForReceiver(ctx context.Context, req *vnotice.GetNoticeUnreadCountForReceiverReq) (res *vnotice.GetNoticeUnreadCountForReceiverRes, err error) { 46 | return noticeService.GetNoticeUnreadCountForReceiver(ctx, req) 47 | 48 | } 49 | -------------------------------------------------------------------------------- /hack/hack.mk: -------------------------------------------------------------------------------- 1 | include ./hack/hack-cli.mk 2 | 3 | # Update GoFrame and its CLI to latest stable version. 4 | .PHONY: up 5 | up: cli.install 6 | @gf up -a 7 | 8 | # Build binary using configuration from hack/config.yaml. 9 | .PHONY: build 10 | build: cli.install 11 | @gf build -ew 12 | 13 | # Parse api and generate controller/sdk. 14 | .PHONY: ctrl 15 | ctrl: cli.install 16 | @gf gen ctrl 17 | 18 | # Generate Go files for DAO/DO/Entity. 19 | .PHONY: dao 20 | dao: cli.install 21 | @gf gen dao 22 | 23 | # Parse current project go files and generate enums go file. 24 | .PHONY: enums 25 | enums: cli.install 26 | @gf gen enums 27 | 28 | # Generate Go files for Service. 29 | .PHONY: service 30 | service: cli.install 31 | @gf gen service 32 | 33 | 34 | # Build docker image. 35 | .PHONY: image 36 | image: cli.install 37 | $(eval _TAG = $(shell git describe --dirty --always --tags --abbrev=8 --match 'v*' | sed 's/-/./2' | sed 's/-/./2')) 38 | ifneq (, $(shell git status --porcelain 2>/dev/null)) 39 | $(eval _TAG = $(_TAG).dirty) 40 | endif 41 | $(eval _TAG = $(if ${TAG}, ${TAG}, $(_TAG))) 42 | $(eval _PUSH = $(if ${PUSH}, ${PUSH}, )) 43 | @gf docker ${_PUSH} -tn $(DOCKER_NAME):${_TAG}; 44 | 45 | 46 | # Build docker image and automatically push to docker repo. 47 | .PHONY: image.push 48 | image.push: 49 | @make image PUSH=-p; 50 | 51 | 52 | # Deploy image and yaml to current kubectl environment. 53 | .PHONY: deploy 54 | deploy: 55 | $(eval _TAG = $(if ${TAG}, ${TAG}, develop)) 56 | 57 | @set -e; \ 58 | mkdir -p $(ROOT_DIR)/temp/kustomize;\ 59 | cd $(ROOT_DIR)/manifest/deploy/kustomize/overlays/${_ENV};\ 60 | kustomize build > $(ROOT_DIR)/temp/kustomize.yaml;\ 61 | kubectl apply -f $(ROOT_DIR)/temp/kustomize.yaml; \ 62 | if [ $(DEPLOY_NAME) != "" ]; then \ 63 | kubectl patch -n $(NAMESPACE) deployment/$(DEPLOY_NAME) -p "{\"spec\":{\"template\":{\"metadata\":{\"labels\":{\"date\":\"$(shell date +%s)\"}}}}}"; \ 64 | fi; 65 | 66 | 67 | # Parsing protobuf files and generating go files. 68 | .PHONY: pb 69 | pb: cli.install 70 | @gf gen pb 71 | 72 | # Generate protobuf files for database tables. 73 | .PHONY: pbentity 74 | pbentity: cli.install 75 | @gf gen pbentity -------------------------------------------------------------------------------- /internal/model/entity/menu.go: -------------------------------------------------------------------------------- 1 | // ================================================================================= 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ================================================================================= 4 | 5 | package entity 6 | 7 | import ( 8 | "github.com/gogf/gf/v2/os/gtime" 9 | ) 10 | 11 | // Menu is the golang structure for table menu. 12 | type Menu struct { 13 | Id int64 `json:"id" description:"菜单ID"` 14 | Pid int64 `json:"pid" description:"父菜单ID,0表示根级"` 15 | Title string `json:"title" description:"菜单名称"` 16 | Name string `json:"name" description:"名称编码"` 17 | Path string `json:"path" description:"路由地址"` 18 | Icon string `json:"icon" description:"菜单图标"` 19 | Type int `json:"type" description:"菜单类型(1目录 2菜单)"` 20 | Redirect string `json:"redirect" description:"重定向地址"` 21 | Permissions string `json:"permissions" description:"菜单包含权限集合"` 22 | PermissionName string `json:"permissionName" description:"权限名称"` 23 | Component string `json:"component" description:"组件路径"` 24 | AlwaysShow int `json:"alwaysShow" description:"取消自动计算根路由模式 1是2否"` 25 | ActiveMenu string `json:"activeMenu" description:"高亮菜单编码"` 26 | IsRoot int `json:"isRoot" description:"是否跟路由"` 27 | IsFrame int `json:"isFrame" description:"是否跳转外链"` 28 | FrameSrc string `json:"frameSrc" description:"iframe地址"` 29 | KeepAlive int `json:"keepAlive" description:"缓存该路由,1是2否"` 30 | Hidden int `json:"hidden" description:"是否隐藏,1是2否"` 31 | Affix int `json:"affix" description:"是否固定"` 32 | Level int `json:"level" description:"关系树等级 1根2子3孙"` 33 | Tree string `json:"tree" description:"关系树"` 34 | Sort int `json:"sort" description:"排序"` 35 | Remark string `json:"remark" description:"备注"` 36 | Status int `json:"status" description:"菜单状态"` 37 | CreatedAt *gtime.Time `json:"createdAt" description:"创建时间"` 38 | UpdatedAt *gtime.Time `json:"updatedAt" description:"更新时间"` 39 | } 40 | -------------------------------------------------------------------------------- /api/vnotice/notice.go: -------------------------------------------------------------------------------- 1 | package vnotice 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "goframe-starter/api/vcommon" 6 | "goframe-starter/internal/model/entity" 7 | ) 8 | 9 | type AddNoticeReq struct { 10 | g.Meta `tags:"通告" method:"post" path:"/notice" sm:"添加" dc:"添加通告" ` 11 | *entity.Notice 12 | } 13 | type AddNoticeRes struct{} 14 | 15 | type DeleteNoticeReq struct { 16 | g.Meta `tags:"通告" method:"delete" path:"/notice" sm:"删除" dc:"删除通告" ` 17 | Id uint `json:"id" v:"required" description:""` 18 | } 19 | type DeleteNoticeRes struct{} 20 | 21 | type UpdateNoticeReq struct { 22 | g.Meta `tags:"通告" method:"put" path:"/notice" sm:"修改" dc:"更新通告" ` 23 | *entity.Notice 24 | } 25 | type UpdateNoticeRes struct{} 26 | 27 | type ListNoticeReq struct { 28 | g.Meta `tags:"通告" method:"get" path:"/notice/list" sm:"列表" dc:"通告列表" ` 29 | *entity.Notice 30 | *vcommon.CommonPageReq 31 | } 32 | type ListNoticeRes struct { 33 | List []*entity.Notice `json:"list"` 34 | *vcommon.CommonPageRes 35 | } 36 | 37 | type OneNoticeReq struct { 38 | g.Meta `tags:"通告" method:"get" path:"/notice" sm:"单个" dc:"通告" ` 39 | Id uint `json:"id" v:"required" description:""` 40 | } 41 | type OneNoticeRes *entity.Notice 42 | 43 | type ListNoticeForReceiverReq struct { 44 | g.Meta `tags:"通告" method:"get" path:"/notice/receive/list" sm:"列表" dc:"通告列表" ` 45 | *entity.Notice 46 | Status int `json:"status" description:"1未读2已读3隐藏,用户看过把status置为2"` 47 | *vcommon.CommonPageReq 48 | } 49 | 50 | type ItemNoticeForReceiver struct { 51 | *entity.Notice 52 | Uid uint `json:"uid" description:""` 53 | Status int `json:"status" ` 54 | } 55 | 56 | type ListNoticeForReceiverRes struct { 57 | List []*ItemNoticeForReceiver `json:"list"` 58 | *vcommon.CommonPageRes 59 | } 60 | 61 | type DeleteNoticeForReceiverReq struct { 62 | g.Meta `tags:"通告" method:"delete" path:"/notice/receive" sm:"删除" dc:"删除接收通告" ` 63 | Id uint `json:"id" v:"required" description:""` 64 | } 65 | type DeleteNoticeForReceiverRes struct{} 66 | 67 | type UpdateNoticeForReceiverReq struct { 68 | g.Meta `tags:"通告" method:"put" path:"/notice/receive" sm:"修改" dc:"设为已读" ` 69 | Status int `json:"status" v:"required" description:"1未读2已读3隐藏,用户看过把status置为2"` 70 | Id uint `json:"id" v:"required" description:""` 71 | } 72 | type UpdateNoticeForReceiverRes struct{} 73 | 74 | type GetNoticeUnreadCountForReceiverReq struct { 75 | g.Meta `tags:"通告" method:"get" path:"/notice/receive/unread" sm:"获取" dc:"获取未读消息个数" ` 76 | } 77 | 78 | type GetNoticeUnreadCountForReceiverRes struct { 79 | Count int `json:"count"` 80 | } 81 | -------------------------------------------------------------------------------- /manifest/config/config.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | name: "goframe-starter" 3 | address: ":8888" 4 | serverRoot: "resource/public" 5 | uploadRoot: "resource/public/upload" 6 | openapiPath: "/api.json" 7 | swaggerPath: "/swagger" 8 | # Logging配置 9 | logPath: "logs/server" # 日志文件存储目录路径,建议使用绝对路径。默认为空,表示关闭 10 | logStdout: true # 日志是否输出到终端。默认为true 11 | errorStack: true # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true 12 | errorLogEnabled: true # 是否记录异常日志信息到日志中。默认为true 13 | errorLogPattern: "error-{Ymd}.log" # 异常错误日志文件格式。默认为"error-{Ymd}.log" 14 | accessLogEnabled: true # 是否记录访问日志。默认为false 15 | accessLogPattern: "access-{Ymd}.log" # 访问日志文件格式。默认为"access-{Ymd}.log" 16 | 17 | logger: 18 | path: "logs/run" 19 | file: "{Y-m-d}.log" 20 | level : "all" 21 | stdout: true 22 | cache: 23 | model: 2 #缓存模式 1memory OR 2 redis 24 | prefix: "xcache:" #缓存前缀 25 | gfToken: 26 | cacheKey: "gfToken:" 27 | cacheMode: 2 # 1 gcache 2 redis 3 file 28 | timeOut: 10800 29 | encryptKey: "49c54195e750b04e74a8429b17896586" 30 | maxRefresh: 5400 31 | multiLogin: true 32 | globalMiddleware: true 33 | loginPath: "/api/login" 34 | logoutPath: "/api/logout" 35 | authPaths: 36 | - "/api/" 37 | excludePaths: 38 | - "/api/login" 39 | - "/api/otp/username" 40 | - "/api/otp/validate" 41 | 42 | # Database. 43 | database: 44 | logger: 45 | level: "all" 46 | stdout: true 47 | Path: "logs/sql" 48 | 49 | default: 50 | # link: "mysql:starter:HPxNd6sT48yehDCr@tcp(163.197.246.80:3306)/starter?loc=Local&parseTime=true" 51 | link: "mysql:root:123456@tcp(127.0.0.1:3306)/starter?loc=Local&parseTime=true" 52 | debug: true 53 | charset: "utf8mb4" #数据库编码 54 | dryRun: false #空跑 55 | maxIdle: 10 #连接池最大闲置的连接数 56 | maxOpen: 10 #连接池最大打开的连接数 57 | maxLifetime: "30s" #(单位秒)连接对象可重复使用的时间长度 58 | 59 | # Redis 配置示例 60 | redis: 61 | # 单实例配置 62 | default: 63 | address: 127.0.0.1:6379 64 | db: 1 65 | idleTimeout: "60s" #连接最大空闲时间,使用时间字符串例如30s/1m/1d 66 | maxConnLifetime: "90s" #连接最长存活时间,使用时间字符串例如30s/1m/1d 67 | waitTimeout: "60s" #等待连接池连接的超时时间,使用时间字符串例如30s/1m/1d 68 | dialTimeout: "30s" #TCP连接的超时时间,使用时间字符串例如30s/1m/1d 69 | readTimeout: "30s" #TCP的Read操作超时时间,使用时间字符串例如30s/1m/1d 70 | writeTimeout: "30s" #TCP的Write操作超时时间,使用时间字符串例如30s/1m/1d 71 | maxActive: 1000 72 | 73 | #casbin配置 74 | casbin: 75 | modelFile: "./resource/casbin/model.conf" 76 | policyFile: "./resource/casbin/policy.csv" 77 | 78 | #消息推送配置 79 | pusher: 80 | appId: "1675714" 81 | key: "06d4f5c8c305bf2ca68e" 82 | secret: "1c72caae84c5342fbe80" 83 | cluster: "ap3" 84 | -------------------------------------------------------------------------------- /api/vmenu/menu.go: -------------------------------------------------------------------------------- 1 | package vmenu 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "goframe-starter/internal/model/entity" 6 | ) 7 | 8 | type AddMenuReq struct { 9 | g.Meta `tags:"菜单" method:"post" path:"/menu" sm:"添加" dc:"添加菜单" ` 10 | *entity.Menu 11 | } 12 | type AddMenuRes struct{} 13 | 14 | type UpdateMenuReq struct { 15 | g.Meta `tags:"菜单" method:"put" path:"/menu" sm:"修改" dc:"修改菜单" ` 16 | *entity.Menu 17 | } 18 | type UpdateMenuRes struct{} 19 | 20 | type ListMenuReq struct { 21 | g.Meta `tags:"菜单" method:"get" path:"/menu/list" sm:"列表" dc:"菜单列表" ` 22 | *entity.Menu 23 | //*vcommon.CommonPageReq 24 | } 25 | 26 | type ListMenuRes struct { 27 | List []*entity.Menu `json:"list"` 28 | //*vcommon.CommonPageRes 29 | } 30 | 31 | type DeleteMenuReq struct { 32 | g.Meta `tags:"菜单" method:"delete" path:"/menu" sm:"删除" dc:"删除菜单" ` 33 | Id int64 `json:"id" v:"required" description:"菜单ID"` 34 | } 35 | type DeleteMenuRes struct{} 36 | 37 | type TreeMenuItem struct { 38 | *entity.Menu 39 | Children []*TreeMenuItem `json:"children"` 40 | } 41 | type ListTreeMenuReq struct { 42 | g.Meta `tags:"菜单" method:"get" path:"/menu/tree" sm:"列表" dc:"菜单管理树形列表" ` 43 | } 44 | type ListTreeMenuRes struct { 45 | List []*TreeMenuItem `json:"list"` 46 | } 47 | type VueMenuMeta struct { 48 | Title string `json:"title"` 49 | Icon string `json:"icon"` 50 | //expanded boolean 51 | OrderNo int `json:"orderNo"` 52 | Hidden bool `json:"hidden"` 53 | HiddenBreadcrumb bool `json:"hiddenBreadcrumb"` 54 | Single bool `json:"single"` 55 | KeepAlive bool `json:"keepAlive"` 56 | FrameSrc string `json:"frameSrc"` 57 | IsFrame bool `json:"isFrame"` 58 | Affix bool `json:"affix"` 59 | } 60 | type VueMenu struct { 61 | Path string `json:"path"` 62 | Name string `json:"name"` 63 | Component string `json:"component"` 64 | Redirect string `json:"redirect"` 65 | Meta *VueMenuMeta `json:"meta"` 66 | Children []*VueMenu `json:"children"` 67 | } 68 | type VueMenuReq struct { 69 | g.Meta `tags:"菜单" method:"get" path:"/menu/vue" sm:"列表" dc:"返回给前端做动态路由" ` 70 | } 71 | type VueMenuRes struct { 72 | List []*VueMenu `json:"list"` 73 | } 74 | 75 | type MenuForRoleReq struct { 76 | g.Meta `tags:"菜单" method:"post" path:"/menu/role" sm:"角色绑定菜单" dc:"为角色绑定菜单" ` 77 | RoleId uint `json:"roleId"` 78 | MenuIds []int `json:"menuIds"` 79 | } 80 | 81 | type MenuForRoleRes struct{} 82 | 83 | type MenuByRoleReq struct { 84 | g.Meta `tags:"菜单" method:"get" path:"/menu/role" sm:"角色绑定菜单" dc:"获取角色绑定的菜单" ` 85 | RoleId uint `json:"roleId"` 86 | } 87 | 88 | type MenuByRoleRes struct { 89 | List []int `json:"list"` 90 | } 91 | -------------------------------------------------------------------------------- /manifest/config/config.dev.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | name: "goframe-starter" 3 | address: ":8888" 4 | serverRoot: "resource/public" 5 | uploadRoot: "resource/public/upload" 6 | openapiPath: "/api.json" 7 | swaggerPath: "/swagger" 8 | # Logging配置 9 | logPath: "logs/server" # 日志文件存储目录路径,建议使用绝对路径。默认为空,表示关闭 10 | logStdout: true # 日志是否输出到终端。默认为true 11 | errorStack: true # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true 12 | errorLogEnabled: true # 是否记录异常日志信息到日志中。默认为true 13 | errorLogPattern: "error-{Ymd}.log" # 异常错误日志文件格式。默认为"error-{Ymd}.log" 14 | accessLogEnabled: true # 是否记录访问日志。默认为false 15 | accessLogPattern: "access-{Ymd}.log" # 访问日志文件格式。默认为"access-{Ymd}.log" 16 | # PProf配置 17 | pprofEnabled: false # 是否开启PProf性能调试特性。默认为false 18 | pprofPattern: "/pprof" # 开启PProf时有效,表示PProf特性的页面访问路径,对当前Server绑定的所有域名有效。 19 | logger: 20 | path: "logs/run" 21 | file: "{Y-m-d}.log" 22 | level : "all" 23 | stdout: true 24 | cache: 25 | model: 2 #缓存模式 1memory OR 2 redis 26 | prefix: "xcache:" #缓存前缀 27 | gfToken: 28 | cacheKey: "gfToken:" 29 | cacheMode: 2 # 1 gcache 2 redis 3 file 30 | timeOut: 86400000 31 | encryptKey: "49c54195e750b04e74a8429b17896586" 32 | maxRefresh: 5400 33 | multiLogin: true 34 | globalMiddleware: true 35 | loginPath: "/api/login" 36 | logoutPath: "/api/logout" 37 | authPaths: 38 | - "/api/" 39 | excludePaths: 40 | - "/api/login" 41 | - "/api/otp/username" 42 | - "/api/otp/validate" 43 | 44 | # Database. 45 | database: 46 | logger: 47 | level: "all" 48 | stdout: true 49 | Path: "logs/sql" 50 | 51 | default: 52 | link: "mysql:starter:HPxNd6sT48yehDCr@tcp(163.197.246.80:3306)/starter?loc=Local&parseTime=true" 53 | debug: true 54 | charset: "utf8mb4" #数据库编码 55 | dryRun: false #空跑 56 | maxIdle: 10 #连接池最大闲置的连接数 57 | maxOpen: 10 #连接池最大打开的连接数 58 | maxLifetime: "30s" #(单位秒)连接对象可重复使用的时间长度 59 | 60 | # Redis 配置示例 61 | redis: 62 | # 单实例配置 63 | default: 64 | address: 127.0.0.1:6379 65 | db: 1 66 | idleTimeout: "60s" #连接最大空闲时间,使用时间字符串例如30s/1m/1d 67 | maxConnLifetime: "90s" #连接最长存活时间,使用时间字符串例如30s/1m/1d 68 | waitTimeout: "60s" #等待连接池连接的超时时间,使用时间字符串例如30s/1m/1d 69 | dialTimeout: "30s" #TCP连接的超时时间,使用时间字符串例如30s/1m/1d 70 | readTimeout: "30s" #TCP的Read操作超时时间,使用时间字符串例如30s/1m/1d 71 | writeTimeout: "30s" #TCP的Write操作超时时间,使用时间字符串例如30s/1m/1d 72 | maxActive: 100 73 | 74 | #casbin配置 75 | casbin: 76 | modelFile: "./resource/casbin/model.conf" 77 | policyFile: "./resource/casbin/policy.csv" 78 | 79 | #消息推送配置 80 | pusher: 81 | appId: "1675714" 82 | key: "06d4f5c8c305bf2ca68e" 83 | secret: "1c72caae84c5342fbe80" 84 | cluster: "ap3" 85 | -------------------------------------------------------------------------------- /manifest/config/config.prod.yaml: -------------------------------------------------------------------------------- 1 | server: 2 | name: "goframe-starter" 3 | address: ":8888" 4 | serverRoot: "resource/public" 5 | uploadRoot: "resource/public/upload" 6 | openapiPath: "/api.json" 7 | swaggerPath: "/swagger" 8 | # Logging配置 9 | logPath: "logs/server" # 日志文件存储目录路径,建议使用绝对路径。默认为空,表示关闭 10 | logStdout: true # 日志是否输出到终端。默认为true 11 | errorStack: true # 当Server捕获到异常时是否记录堆栈信息到日志中。默认为true 12 | errorLogEnabled: true # 是否记录异常日志信息到日志中。默认为true 13 | errorLogPattern: "error-{Ymd}.log" # 异常错误日志文件格式。默认为"error-{Ymd}.log" 14 | accessLogEnabled: true # 是否记录访问日志。默认为false 15 | accessLogPattern: "access-{Ymd}.log" # 访问日志文件格式。默认为"access-{Ymd}.log" 16 | # PProf配置 17 | pprofEnabled: false # 是否开启PProf性能调试特性。默认为false 18 | pprofPattern: "/pprof" # 开启PProf时有效,表示PProf特性的页面访问路径,对当前Server绑定的所有域名有效。 19 | logger: 20 | path: "logs/run" 21 | file: "{Y-m-d}.log" 22 | level : "all" 23 | stdout: true 24 | cache: 25 | model: 2 #缓存模式 1memory OR 2 redis 26 | prefix: "xcache:" #缓存前缀 27 | gfToken: 28 | cacheKey: "gfToken:" 29 | cacheMode: 2 # 1 gcache 2 redis 3 file 30 | timeOut: 86400000 31 | encryptKey: "49c54195e750b04e74a8429b17896586" 32 | maxRefresh: 5400 33 | multiLogin: true 34 | globalMiddleware: true 35 | loginPath: "/api/login" 36 | logoutPath: "/api/logout" 37 | authPaths: 38 | - "/api/" 39 | excludePaths: 40 | - "/api/login" 41 | - "/api/otp/username" 42 | - "/api/otp/validate" 43 | 44 | # Database. 45 | database: 46 | logger: 47 | level: "all" 48 | stdout: true 49 | Path: "logs/sql" 50 | 51 | default: 52 | link: "mysql:starter:HPxNd6sT48yehDCr@tcp(163.197.246.80:3306)/starter?loc=Local&parseTime=true" 53 | debug: true 54 | charset: "utf8mb4" #数据库编码 55 | dryRun: false #空跑 56 | maxIdle: 10 #连接池最大闲置的连接数 57 | maxOpen: 10 #连接池最大打开的连接数 58 | maxLifetime: "30s" #(单位秒)连接对象可重复使用的时间长度 59 | 60 | # Redis 配置示例 61 | redis: 62 | # 单实例配置 63 | default: 64 | address: 127.0.0.1:6379 65 | db: 1 66 | idleTimeout: "60s" #连接最大空闲时间,使用时间字符串例如30s/1m/1d 67 | maxConnLifetime: "90s" #连接最长存活时间,使用时间字符串例如30s/1m/1d 68 | waitTimeout: "60s" #等待连接池连接的超时时间,使用时间字符串例如30s/1m/1d 69 | dialTimeout: "30s" #TCP连接的超时时间,使用时间字符串例如30s/1m/1d 70 | readTimeout: "30s" #TCP的Read操作超时时间,使用时间字符串例如30s/1m/1d 71 | writeTimeout: "30s" #TCP的Write操作超时时间,使用时间字符串例如30s/1m/1d 72 | maxActive: 100 73 | 74 | #casbin配置 75 | casbin: 76 | modelFile: "./resource/casbin/model.conf" 77 | policyFile: "./resource/casbin/policy.csv" 78 | 79 | #消息推送配置 80 | pusher: 81 | appId: "1675714" 82 | key: "06d4f5c8c305bf2ca68e" 83 | secret: "1c72caae84c5342fbe80" 84 | cluster: "ap3" 85 | -------------------------------------------------------------------------------- /internal/dao/internal/otp_auth.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // OtpAuthDao is the data access object for table otp_auth. 15 | type OtpAuthDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns OtpAuthColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // OtpAuthColumns defines and stores column names for table otp_auth. 22 | type OtpAuthColumns struct { 23 | Id string // 24 | Uid string // 25 | Username string // 26 | Secret string // 27 | Status string // 1开2关 28 | } 29 | 30 | // otpAuthColumns holds the columns for table otp_auth. 31 | var otpAuthColumns = OtpAuthColumns{ 32 | Id: "id", 33 | Uid: "uid", 34 | Username: "username", 35 | Secret: "secret", 36 | Status: "status", 37 | } 38 | 39 | // NewOtpAuthDao creates and returns a new DAO object for table data access. 40 | func NewOtpAuthDao() *OtpAuthDao { 41 | return &OtpAuthDao{ 42 | group: "default", 43 | table: "otp_auth", 44 | columns: otpAuthColumns, 45 | } 46 | } 47 | 48 | // DB retrieves and returns the underlying raw database management object of current DAO. 49 | func (dao *OtpAuthDao) DB() gdb.DB { 50 | return g.DB(dao.group) 51 | } 52 | 53 | // Table returns the table name of current dao. 54 | func (dao *OtpAuthDao) Table() string { 55 | return dao.table 56 | } 57 | 58 | // Columns returns all column names of current dao. 59 | func (dao *OtpAuthDao) Columns() OtpAuthColumns { 60 | return dao.columns 61 | } 62 | 63 | // Group returns the configuration group name of database of current dao. 64 | func (dao *OtpAuthDao) Group() string { 65 | return dao.group 66 | } 67 | 68 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 69 | func (dao *OtpAuthDao) Ctx(ctx context.Context) *gdb.Model { 70 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 71 | } 72 | 73 | // Transaction wraps the transaction logic using function f. 74 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 75 | // It commits the transaction and returns nil if function f returns nil. 76 | // 77 | // Note that, you should not Commit or Rollback the transaction in function f 78 | // as it is automatically handled by this function. 79 | func (dao *OtpAuthDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 80 | return dao.Ctx(ctx).Transaction(ctx, f) 81 | } 82 | -------------------------------------------------------------------------------- /internal/dao/internal/api.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // ApiDao is the data access object for table api. 15 | type ApiDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns ApiColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // ApiColumns defines and stores column names for table api. 22 | type ApiColumns struct { 23 | Id string // 24 | Url string // 25 | Method string // 26 | Group string // 27 | Remark string // 28 | CreatedAt string // 29 | UpdatedAt string // 30 | } 31 | 32 | // apiColumns holds the columns for table api. 33 | var apiColumns = ApiColumns{ 34 | Id: "id", 35 | Url: "url", 36 | Method: "method", 37 | Group: "group", 38 | Remark: "remark", 39 | CreatedAt: "created_at", 40 | UpdatedAt: "updated_at", 41 | } 42 | 43 | // NewApiDao creates and returns a new DAO object for table data access. 44 | func NewApiDao() *ApiDao { 45 | return &ApiDao{ 46 | group: "default", 47 | table: "api", 48 | columns: apiColumns, 49 | } 50 | } 51 | 52 | // DB retrieves and returns the underlying raw database management object of current DAO. 53 | func (dao *ApiDao) DB() gdb.DB { 54 | return g.DB(dao.group) 55 | } 56 | 57 | // Table returns the table name of current dao. 58 | func (dao *ApiDao) Table() string { 59 | return dao.table 60 | } 61 | 62 | // Columns returns all column names of current dao. 63 | func (dao *ApiDao) Columns() ApiColumns { 64 | return dao.columns 65 | } 66 | 67 | // Group returns the configuration group name of database of current dao. 68 | func (dao *ApiDao) Group() string { 69 | return dao.group 70 | } 71 | 72 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 73 | func (dao *ApiDao) Ctx(ctx context.Context) *gdb.Model { 74 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 75 | } 76 | 77 | // Transaction wraps the transaction logic using function f. 78 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 79 | // It commits the transaction and returns nil if function f returns nil. 80 | // 81 | // Note that, you should not Commit or Rollback the transaction in function f 82 | // as it is automatically handled by this function. 83 | func (dao *ApiDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 84 | return dao.Ctx(ctx).Transaction(ctx, f) 85 | } 86 | -------------------------------------------------------------------------------- /internal/dao/internal/button.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // ButtonDao is the data access object for table button. 15 | type ButtonDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns ButtonColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // ButtonColumns defines and stores column names for table button. 22 | type ButtonColumns struct { 23 | Id string // 24 | MenuId string // 按钮所在菜单id 25 | MenuTitle string // 按钮所在菜单名称 26 | Name string // 按钮标识符 27 | Title string // 按钮名称 28 | Remark string // 29 | } 30 | 31 | // buttonColumns holds the columns for table button. 32 | var buttonColumns = ButtonColumns{ 33 | Id: "id", 34 | MenuId: "menu_id", 35 | MenuTitle: "menu_title", 36 | Name: "name", 37 | Title: "title", 38 | Remark: "remark", 39 | } 40 | 41 | // NewButtonDao creates and returns a new DAO object for table data access. 42 | func NewButtonDao() *ButtonDao { 43 | return &ButtonDao{ 44 | group: "default", 45 | table: "button", 46 | columns: buttonColumns, 47 | } 48 | } 49 | 50 | // DB retrieves and returns the underlying raw database management object of current DAO. 51 | func (dao *ButtonDao) DB() gdb.DB { 52 | return g.DB(dao.group) 53 | } 54 | 55 | // Table returns the table name of current dao. 56 | func (dao *ButtonDao) Table() string { 57 | return dao.table 58 | } 59 | 60 | // Columns returns all column names of current dao. 61 | func (dao *ButtonDao) Columns() ButtonColumns { 62 | return dao.columns 63 | } 64 | 65 | // Group returns the configuration group name of database of current dao. 66 | func (dao *ButtonDao) Group() string { 67 | return dao.group 68 | } 69 | 70 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 71 | func (dao *ButtonDao) Ctx(ctx context.Context) *gdb.Model { 72 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 73 | } 74 | 75 | // Transaction wraps the transaction logic using function f. 76 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 77 | // It commits the transaction and returns nil if function f returns nil. 78 | // 79 | // Note that, you should not Commit or Rollback the transaction in function f 80 | // as it is automatically handled by this function. 81 | func (dao *ButtonDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 82 | return dao.Ctx(ctx).Transaction(ctx, f) 83 | } 84 | -------------------------------------------------------------------------------- /internal/dao/internal/user_relation.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // UserRelationDao is the data access object for table user_relation. 15 | type UserRelationDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns UserRelationColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // UserRelationColumns defines and stores column names for table user_relation. 22 | type UserRelationColumns struct { 23 | Id string // 24 | PUserId string // 25 | Level string // 代理层级 26 | UserId string // 27 | } 28 | 29 | // userRelationColumns holds the columns for table user_relation. 30 | var userRelationColumns = UserRelationColumns{ 31 | Id: "id", 32 | PUserId: "p_user_id", 33 | Level: "level", 34 | UserId: "user_id", 35 | } 36 | 37 | // NewUserRelationDao creates and returns a new DAO object for table data access. 38 | func NewUserRelationDao() *UserRelationDao { 39 | return &UserRelationDao{ 40 | group: "default", 41 | table: "user_relation", 42 | columns: userRelationColumns, 43 | } 44 | } 45 | 46 | // DB retrieves and returns the underlying raw database management object of current DAO. 47 | func (dao *UserRelationDao) DB() gdb.DB { 48 | return g.DB(dao.group) 49 | } 50 | 51 | // Table returns the table name of current dao. 52 | func (dao *UserRelationDao) Table() string { 53 | return dao.table 54 | } 55 | 56 | // Columns returns all column names of current dao. 57 | func (dao *UserRelationDao) Columns() UserRelationColumns { 58 | return dao.columns 59 | } 60 | 61 | // Group returns the configuration group name of database of current dao. 62 | func (dao *UserRelationDao) Group() string { 63 | return dao.group 64 | } 65 | 66 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 67 | func (dao *UserRelationDao) Ctx(ctx context.Context) *gdb.Model { 68 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 69 | } 70 | 71 | // Transaction wraps the transaction logic using function f. 72 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 73 | // It commits the transaction and returns nil if function f returns nil. 74 | // 75 | // Note that, you should not Commit or Rollback the transaction in function f 76 | // as it is automatically handled by this function. 77 | func (dao *UserRelationDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 78 | return dao.Ctx(ctx).Transaction(ctx, f) 79 | } 80 | -------------------------------------------------------------------------------- /internal/dao/internal/blacklist.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // BlacklistDao is the data access object for table blacklist. 15 | type BlacklistDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns BlacklistColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // BlacklistColumns defines and stores column names for table blacklist. 22 | type BlacklistColumns struct { 23 | Id string // 黑名单ID 24 | Ip string // IP地址 25 | Remark string // 备注 26 | Status string // 状态 27 | CreatedAt string // 创建时间 28 | UpdatedAt string // 更新时间 29 | } 30 | 31 | // blacklistColumns holds the columns for table blacklist. 32 | var blacklistColumns = BlacklistColumns{ 33 | Id: "id", 34 | Ip: "ip", 35 | Remark: "remark", 36 | Status: "status", 37 | CreatedAt: "created_at", 38 | UpdatedAt: "updated_at", 39 | } 40 | 41 | // NewBlacklistDao creates and returns a new DAO object for table data access. 42 | func NewBlacklistDao() *BlacklistDao { 43 | return &BlacklistDao{ 44 | group: "default", 45 | table: "blacklist", 46 | columns: blacklistColumns, 47 | } 48 | } 49 | 50 | // DB retrieves and returns the underlying raw database management object of current DAO. 51 | func (dao *BlacklistDao) DB() gdb.DB { 52 | return g.DB(dao.group) 53 | } 54 | 55 | // Table returns the table name of current dao. 56 | func (dao *BlacklistDao) Table() string { 57 | return dao.table 58 | } 59 | 60 | // Columns returns all column names of current dao. 61 | func (dao *BlacklistDao) Columns() BlacklistColumns { 62 | return dao.columns 63 | } 64 | 65 | // Group returns the configuration group name of database of current dao. 66 | func (dao *BlacklistDao) Group() string { 67 | return dao.group 68 | } 69 | 70 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 71 | func (dao *BlacklistDao) Ctx(ctx context.Context) *gdb.Model { 72 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 73 | } 74 | 75 | // Transaction wraps the transaction logic using function f. 76 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 77 | // It commits the transaction and returns nil if function f returns nil. 78 | // 79 | // Note that, you should not Commit or Rollback the transaction in function f 80 | // as it is automatically handled by this function. 81 | func (dao *BlacklistDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 82 | return dao.Ctx(ctx).Transaction(ctx, f) 83 | } 84 | -------------------------------------------------------------------------------- /internal/dao/internal/casbin_policy.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // CasbinPolicyDao is the data access object for table casbin_policy. 15 | type CasbinPolicyDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns CasbinPolicyColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // CasbinPolicyColumns defines and stores column names for table casbin_policy. 22 | type CasbinPolicyColumns struct { 23 | Ptype string // 24 | V0 string // 25 | V1 string // 26 | V2 string // 27 | V3 string // 28 | V4 string // 29 | V5 string // 30 | } 31 | 32 | // casbinPolicyColumns holds the columns for table casbin_policy. 33 | var casbinPolicyColumns = CasbinPolicyColumns{ 34 | Ptype: "ptype", 35 | V0: "v0", 36 | V1: "v1", 37 | V2: "v2", 38 | V3: "v3", 39 | V4: "v4", 40 | V5: "v5", 41 | } 42 | 43 | // NewCasbinPolicyDao creates and returns a new DAO object for table data access. 44 | func NewCasbinPolicyDao() *CasbinPolicyDao { 45 | return &CasbinPolicyDao{ 46 | group: "default", 47 | table: "casbin_policy", 48 | columns: casbinPolicyColumns, 49 | } 50 | } 51 | 52 | // DB retrieves and returns the underlying raw database management object of current DAO. 53 | func (dao *CasbinPolicyDao) DB() gdb.DB { 54 | return g.DB(dao.group) 55 | } 56 | 57 | // Table returns the table name of current dao. 58 | func (dao *CasbinPolicyDao) Table() string { 59 | return dao.table 60 | } 61 | 62 | // Columns returns all column names of current dao. 63 | func (dao *CasbinPolicyDao) Columns() CasbinPolicyColumns { 64 | return dao.columns 65 | } 66 | 67 | // Group returns the configuration group name of database of current dao. 68 | func (dao *CasbinPolicyDao) Group() string { 69 | return dao.group 70 | } 71 | 72 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 73 | func (dao *CasbinPolicyDao) Ctx(ctx context.Context) *gdb.Model { 74 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 75 | } 76 | 77 | // Transaction wraps the transaction logic using function f. 78 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 79 | // It commits the transaction and returns nil if function f returns nil. 80 | // 81 | // Note that, you should not Commit or Rollback the transaction in function f 82 | // as it is automatically handled by this function. 83 | func (dao *CasbinPolicyDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 84 | return dao.Ctx(ctx).Transaction(ctx, f) 85 | } 86 | -------------------------------------------------------------------------------- /internal/dao/internal/role.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // RoleDao is the data access object for table role. 15 | type RoleDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns RoleColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // RoleColumns defines and stores column names for table role. 22 | type RoleColumns struct { 23 | Id string // 24 | Status string // 状态;1:正常2:禁用 25 | ListOrder string // 排序 26 | Name string // 角色名称 27 | Remark string // 备注 28 | DataScope string // 数据范围(1:全部数据权限 2:自定数据权限 3:本部门数据权限 4:本部门及以下数据权限) 29 | CreatedAt string // 创建时间 30 | UpdatedAt string // 更新时间 31 | } 32 | 33 | // roleColumns holds the columns for table role. 34 | var roleColumns = RoleColumns{ 35 | Id: "id", 36 | Status: "status", 37 | ListOrder: "list_order", 38 | Name: "name", 39 | Remark: "remark", 40 | DataScope: "data_scope", 41 | CreatedAt: "created_at", 42 | UpdatedAt: "updated_at", 43 | } 44 | 45 | // NewRoleDao creates and returns a new DAO object for table data access. 46 | func NewRoleDao() *RoleDao { 47 | return &RoleDao{ 48 | group: "default", 49 | table: "role", 50 | columns: roleColumns, 51 | } 52 | } 53 | 54 | // DB retrieves and returns the underlying raw database management object of current DAO. 55 | func (dao *RoleDao) DB() gdb.DB { 56 | return g.DB(dao.group) 57 | } 58 | 59 | // Table returns the table name of current dao. 60 | func (dao *RoleDao) Table() string { 61 | return dao.table 62 | } 63 | 64 | // Columns returns all column names of current dao. 65 | func (dao *RoleDao) Columns() RoleColumns { 66 | return dao.columns 67 | } 68 | 69 | // Group returns the configuration group name of database of current dao. 70 | func (dao *RoleDao) Group() string { 71 | return dao.group 72 | } 73 | 74 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 75 | func (dao *RoleDao) Ctx(ctx context.Context) *gdb.Model { 76 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 77 | } 78 | 79 | // Transaction wraps the transaction logic using function f. 80 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 81 | // It commits the transaction and returns nil if function f returns nil. 82 | // 83 | // Note that, you should not Commit or Rollback the transaction in function f 84 | // as it is automatically handled by this function. 85 | func (dao *RoleDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 86 | return dao.Ctx(ctx).Transaction(ctx, f) 87 | } 88 | -------------------------------------------------------------------------------- /internal/dao/internal/file.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // FileDao is the data access object for table file. 15 | type FileDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns FileColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // FileColumns defines and stores column names for table file. 22 | type FileColumns struct { 23 | Id string // 24 | Drive string // 上传驱动:本地,ucloud 25 | OriginName string // 文件原始名 26 | FileUrl string // 27 | Size string // 单位M 28 | Ext string // 扩展名 29 | Uid string // 上传者用户id 30 | CreatedAt string // 31 | UpdatedAt string // 32 | Remark string // 33 | } 34 | 35 | // fileColumns holds the columns for table file. 36 | var fileColumns = FileColumns{ 37 | Id: "id", 38 | Drive: "drive", 39 | OriginName: "origin_name", 40 | FileUrl: "file_url", 41 | Size: "size", 42 | Ext: "ext", 43 | Uid: "uid", 44 | CreatedAt: "created_at", 45 | UpdatedAt: "updated_at", 46 | Remark: "remark", 47 | } 48 | 49 | // NewFileDao creates and returns a new DAO object for table data access. 50 | func NewFileDao() *FileDao { 51 | return &FileDao{ 52 | group: "default", 53 | table: "file", 54 | columns: fileColumns, 55 | } 56 | } 57 | 58 | // DB retrieves and returns the underlying raw database management object of current DAO. 59 | func (dao *FileDao) DB() gdb.DB { 60 | return g.DB(dao.group) 61 | } 62 | 63 | // Table returns the table name of current dao. 64 | func (dao *FileDao) Table() string { 65 | return dao.table 66 | } 67 | 68 | // Columns returns all column names of current dao. 69 | func (dao *FileDao) Columns() FileColumns { 70 | return dao.columns 71 | } 72 | 73 | // Group returns the configuration group name of database of current dao. 74 | func (dao *FileDao) Group() string { 75 | return dao.group 76 | } 77 | 78 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 79 | func (dao *FileDao) Ctx(ctx context.Context) *gdb.Model { 80 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 81 | } 82 | 83 | // Transaction wraps the transaction logic using function f. 84 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 85 | // It commits the transaction and returns nil if function f returns nil. 86 | // 87 | // Note that, you should not Commit or Rollback the transaction in function f 88 | // as it is automatically handled by this function. 89 | func (dao *FileDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 90 | return dao.Ctx(ctx).Transaction(ctx, f) 91 | } 92 | -------------------------------------------------------------------------------- /internal/dao/internal/notice.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // NoticeDao is the data access object for table notice. 15 | type NoticeDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns NoticeColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // NoticeColumns defines and stores column names for table notice. 22 | type NoticeColumns struct { 23 | Id string // 24 | Title string // 25 | Content string // 26 | Creater string // 创建者username,发送者 27 | Receivers string // 接收者用户id数组 28 | Sort string // 29 | Tag string // 30 | Remark string // 31 | CreatedAt string // 32 | UpdatedAt string // 33 | } 34 | 35 | // noticeColumns holds the columns for table notice. 36 | var noticeColumns = NoticeColumns{ 37 | Id: "id", 38 | Title: "title", 39 | Content: "content", 40 | Creater: "creater", 41 | Receivers: "receivers", 42 | Sort: "sort", 43 | Tag: "tag", 44 | Remark: "remark", 45 | CreatedAt: "created_at", 46 | UpdatedAt: "updated_at", 47 | } 48 | 49 | // NewNoticeDao creates and returns a new DAO object for table data access. 50 | func NewNoticeDao() *NoticeDao { 51 | return &NoticeDao{ 52 | group: "default", 53 | table: "notice", 54 | columns: noticeColumns, 55 | } 56 | } 57 | 58 | // DB retrieves and returns the underlying raw database management object of current DAO. 59 | func (dao *NoticeDao) DB() gdb.DB { 60 | return g.DB(dao.group) 61 | } 62 | 63 | // Table returns the table name of current dao. 64 | func (dao *NoticeDao) Table() string { 65 | return dao.table 66 | } 67 | 68 | // Columns returns all column names of current dao. 69 | func (dao *NoticeDao) Columns() NoticeColumns { 70 | return dao.columns 71 | } 72 | 73 | // Group returns the configuration group name of database of current dao. 74 | func (dao *NoticeDao) Group() string { 75 | return dao.group 76 | } 77 | 78 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 79 | func (dao *NoticeDao) Ctx(ctx context.Context) *gdb.Model { 80 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 81 | } 82 | 83 | // Transaction wraps the transaction logic using function f. 84 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 85 | // It commits the transaction and returns nil if function f returns nil. 86 | // 87 | // Note that, you should not Commit or Rollback the transaction in function f 88 | // as it is automatically handled by this function. 89 | func (dao *NoticeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 90 | return dao.Ctx(ctx).Transaction(ctx, f) 91 | } 92 | -------------------------------------------------------------------------------- /internal/dao/internal/dict.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // DictDao is the data access object for table dict. 15 | type DictDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns DictColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // DictColumns defines and stores column names for table dict. 22 | type DictColumns struct { 23 | Id string // 参数主键 24 | ConfigName string // 参数名称 25 | ConfigKey string // 参数键名 26 | ConfigValue string // 参数键值 27 | ConfigType string // 字典类型 28 | CreateBy string // 创建者 29 | UpdateBy string // 更新者 30 | Remark string // 备注 31 | CreatedAt string // 创建时间 32 | UpdatedAt string // 修改时间 33 | } 34 | 35 | // dictColumns holds the columns for table dict. 36 | var dictColumns = DictColumns{ 37 | Id: "id", 38 | ConfigName: "config_name", 39 | ConfigKey: "config_key", 40 | ConfigValue: "config_value", 41 | ConfigType: "config_type", 42 | CreateBy: "create_by", 43 | UpdateBy: "update_by", 44 | Remark: "remark", 45 | CreatedAt: "created_at", 46 | UpdatedAt: "updated_at", 47 | } 48 | 49 | // NewDictDao creates and returns a new DAO object for table data access. 50 | func NewDictDao() *DictDao { 51 | return &DictDao{ 52 | group: "default", 53 | table: "dict", 54 | columns: dictColumns, 55 | } 56 | } 57 | 58 | // DB retrieves and returns the underlying raw database management object of current DAO. 59 | func (dao *DictDao) DB() gdb.DB { 60 | return g.DB(dao.group) 61 | } 62 | 63 | // Table returns the table name of current dao. 64 | func (dao *DictDao) Table() string { 65 | return dao.table 66 | } 67 | 68 | // Columns returns all column names of current dao. 69 | func (dao *DictDao) Columns() DictColumns { 70 | return dao.columns 71 | } 72 | 73 | // Group returns the configuration group name of database of current dao. 74 | func (dao *DictDao) Group() string { 75 | return dao.group 76 | } 77 | 78 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 79 | func (dao *DictDao) Ctx(ctx context.Context) *gdb.Model { 80 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 81 | } 82 | 83 | // Transaction wraps the transaction logic using function f. 84 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 85 | // It commits the transaction and returns nil if function f returns nil. 86 | // 87 | // Note that, you should not Commit or Rollback the transaction in function f 88 | // as it is automatically handled by this function. 89 | func (dao *DictDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 90 | return dao.Ctx(ctx).Transaction(ctx, f) 91 | } 92 | -------------------------------------------------------------------------------- /internal/dao/internal/notice_user_relation.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // NoticeUserRelationDao is the data access object for table notice_user_relation. 15 | type NoticeUserRelationDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns NoticeUserRelationColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // NoticeUserRelationColumns defines and stores column names for table notice_user_relation. 22 | type NoticeUserRelationColumns struct { 23 | Id string // 24 | NoticeId string // 25 | Uid string // 26 | Status string // 1未读2已读3隐藏,用户看过把status置为2,看完后选择删除就把status置为3 27 | CreatedAt string // 创建时间 28 | UpdatedAt string // 更新时间 29 | } 30 | 31 | // noticeUserRelationColumns holds the columns for table notice_user_relation. 32 | var noticeUserRelationColumns = NoticeUserRelationColumns{ 33 | Id: "id", 34 | NoticeId: "notice_id", 35 | Uid: "uid", 36 | Status: "status", 37 | CreatedAt: "created_at", 38 | UpdatedAt: "updated_at", 39 | } 40 | 41 | // NewNoticeUserRelationDao creates and returns a new DAO object for table data access. 42 | func NewNoticeUserRelationDao() *NoticeUserRelationDao { 43 | return &NoticeUserRelationDao{ 44 | group: "default", 45 | table: "notice_user_relation", 46 | columns: noticeUserRelationColumns, 47 | } 48 | } 49 | 50 | // DB retrieves and returns the underlying raw database management object of current DAO. 51 | func (dao *NoticeUserRelationDao) DB() gdb.DB { 52 | return g.DB(dao.group) 53 | } 54 | 55 | // Table returns the table name of current dao. 56 | func (dao *NoticeUserRelationDao) Table() string { 57 | return dao.table 58 | } 59 | 60 | // Columns returns all column names of current dao. 61 | func (dao *NoticeUserRelationDao) Columns() NoticeUserRelationColumns { 62 | return dao.columns 63 | } 64 | 65 | // Group returns the configuration group name of database of current dao. 66 | func (dao *NoticeUserRelationDao) Group() string { 67 | return dao.group 68 | } 69 | 70 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 71 | func (dao *NoticeUserRelationDao) Ctx(ctx context.Context) *gdb.Model { 72 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 73 | } 74 | 75 | // Transaction wraps the transaction logic using function f. 76 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 77 | // It commits the transaction and returns nil if function f returns nil. 78 | // 79 | // Note that, you should not Commit or Rollback the transaction in function f 80 | // as it is automatically handled by this function. 81 | func (dao *NoticeUserRelationDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 82 | return dao.Ctx(ctx).Transaction(ctx, f) 83 | } 84 | -------------------------------------------------------------------------------- /internal/dao/internal/provinces.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // ProvincesDao is the data access object for table provinces. 15 | type ProvincesDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns ProvincesColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // ProvincesColumns defines and stores column names for table provinces. 22 | type ProvincesColumns struct { 23 | Id string // 省市区ID 24 | Title string // 栏目名称 25 | Pinyin string // 拼音 26 | Lng string // 经度 27 | Lat string // 纬度 28 | Pid string // 父栏目 29 | Level string // 关系树等级 30 | Tree string // 关系 31 | Sort string // 排序 32 | Status string // 状态 33 | CreatedAt string // 创建时间 34 | UpdatedAt string // 更新时间 35 | } 36 | 37 | // provincesColumns holds the columns for table provinces. 38 | var provincesColumns = ProvincesColumns{ 39 | Id: "id", 40 | Title: "title", 41 | Pinyin: "pinyin", 42 | Lng: "lng", 43 | Lat: "lat", 44 | Pid: "pid", 45 | Level: "level", 46 | Tree: "tree", 47 | Sort: "sort", 48 | Status: "status", 49 | CreatedAt: "created_at", 50 | UpdatedAt: "updated_at", 51 | } 52 | 53 | // NewProvincesDao creates and returns a new DAO object for table data access. 54 | func NewProvincesDao() *ProvincesDao { 55 | return &ProvincesDao{ 56 | group: "default", 57 | table: "provinces", 58 | columns: provincesColumns, 59 | } 60 | } 61 | 62 | // DB retrieves and returns the underlying raw database management object of current DAO. 63 | func (dao *ProvincesDao) DB() gdb.DB { 64 | return g.DB(dao.group) 65 | } 66 | 67 | // Table returns the table name of current dao. 68 | func (dao *ProvincesDao) Table() string { 69 | return dao.table 70 | } 71 | 72 | // Columns returns all column names of current dao. 73 | func (dao *ProvincesDao) Columns() ProvincesColumns { 74 | return dao.columns 75 | } 76 | 77 | // Group returns the configuration group name of database of current dao. 78 | func (dao *ProvincesDao) Group() string { 79 | return dao.group 80 | } 81 | 82 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 83 | func (dao *ProvincesDao) Ctx(ctx context.Context) *gdb.Model { 84 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 85 | } 86 | 87 | // Transaction wraps the transaction logic using function f. 88 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 89 | // It commits the transaction and returns nil if function f returns nil. 90 | // 91 | // Note that, you should not Commit or Rollback the transaction in function f 92 | // as it is automatically handled by this function. 93 | func (dao *ProvincesDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 94 | return dao.Ctx(ctx).Transaction(ctx, f) 95 | } 96 | -------------------------------------------------------------------------------- /internal/dao/internal/login_log.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // LoginLogDao is the data access object for table login_log. 15 | type LoginLogDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns LoginLogColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // LoginLogColumns defines and stores column names for table login_log. 22 | type LoginLogColumns struct { 23 | Id string // 24 | Uid string // 25 | Username string // 26 | Ip string // 27 | CreatedAt string // 28 | UpdatedAt string // 29 | ClientAgent string // 注册clientAgen头 30 | RoleId string // 1用户2代理3管理 31 | PRoleId string // 32 | RoleName string // 33 | Pid string // 34 | PUsername string // 35 | } 36 | 37 | // loginLogColumns holds the columns for table login_log. 38 | var loginLogColumns = LoginLogColumns{ 39 | Id: "id", 40 | Uid: "uid", 41 | Username: "username", 42 | Ip: "ip", 43 | CreatedAt: "created_at", 44 | UpdatedAt: "updated_at", 45 | ClientAgent: "client_agent", 46 | RoleId: "role_id", 47 | PRoleId: "p_role_id", 48 | RoleName: "role_name", 49 | Pid: "pid", 50 | PUsername: "p_username", 51 | } 52 | 53 | // NewLoginLogDao creates and returns a new DAO object for table data access. 54 | func NewLoginLogDao() *LoginLogDao { 55 | return &LoginLogDao{ 56 | group: "default", 57 | table: "login_log", 58 | columns: loginLogColumns, 59 | } 60 | } 61 | 62 | // DB retrieves and returns the underlying raw database management object of current DAO. 63 | func (dao *LoginLogDao) DB() gdb.DB { 64 | return g.DB(dao.group) 65 | } 66 | 67 | // Table returns the table name of current dao. 68 | func (dao *LoginLogDao) Table() string { 69 | return dao.table 70 | } 71 | 72 | // Columns returns all column names of current dao. 73 | func (dao *LoginLogDao) Columns() LoginLogColumns { 74 | return dao.columns 75 | } 76 | 77 | // Group returns the configuration group name of database of current dao. 78 | func (dao *LoginLogDao) Group() string { 79 | return dao.group 80 | } 81 | 82 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 83 | func (dao *LoginLogDao) Ctx(ctx context.Context) *gdb.Model { 84 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 85 | } 86 | 87 | // Transaction wraps the transaction logic using function f. 88 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 89 | // It commits the transaction and returns nil if function f returns nil. 90 | // 91 | // Note that, you should not Commit or Rollback the transaction in function f 92 | // as it is automatically handled by this function. 93 | func (dao *LoginLogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 94 | return dao.Ctx(ctx).Transaction(ctx, f) 95 | } 96 | -------------------------------------------------------------------------------- /api/vuser/user.go: -------------------------------------------------------------------------------- 1 | package vuser 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/frame/g" 5 | "github.com/gogf/gf/v2/os/gtime" 6 | "goframe-starter/api/vcommon" 7 | "goframe-starter/internal/model/entity" 8 | ) 9 | 10 | type AddUserReq struct { 11 | g.Meta `tags:"用户" method:"post" path:"/user" sm:"添加" dc:"添加用户" ` 12 | Username string `v:"required" dc:"账号" json:"username"` 13 | Password string `v:"required" dc:"密码" json:"password"` 14 | RoleId int `json:"roleId" description:"1用户2代理3管理"` 15 | } 16 | type AddUserRes struct{} 17 | type DeleteUserReq struct { 18 | g.Meta `tags:"用户" method:"delete" path:"/user" sm:"添加" dc:"删除用户" ` 19 | Id uint `json:"id" v:"required" description:""` 20 | } 21 | type DeleteUserRes struct{} 22 | 23 | type UpdateUserReq struct { 24 | g.Meta `tags:"用户" method:"put" path:"/user" sm:"修改" dc:"更新用户" ` 25 | *entity.User 26 | } 27 | type UpdateUserRes struct{} 28 | 29 | type UpdateUserPasswordReq struct { 30 | g.Meta `tags:"用户" method:"put" path:"/user/password" sm:"修改" dc:"更新用户密码" ` 31 | Password string `json:"password"` 32 | PasswordNew string `json:"passwordNew"` 33 | } 34 | type UpdateUserPasswordRes struct{} 35 | 36 | type ListUserReq struct { 37 | g.Meta `tags:"用户" method:"get" path:"/user/list" sm:"列表" dc:"用户列表" ` 38 | *entity.User 39 | *vcommon.CommonPageReq 40 | } 41 | type UserInfo struct { 42 | Id uint `json:"id" description:""` 43 | Username string `json:"username" description:""` 44 | Nickname string `json:"nickname" description:""` 45 | Email string `json:"email" description:""` 46 | Phone string `json:"phone" description:""` 47 | Status int `json:"status" description:"1正常2禁用"` 48 | ClientAgent string `json:"clientAgent" description:"注册clientAgen头"` 49 | Ip string `json:"ip" description:"IP"` 50 | RoleId int `json:"roleId" description:"1用户2代理3管理"` 51 | CreatedAt *gtime.Time `json:"createdAt" description:""` 52 | UpdatedAt *gtime.Time `json:"updatedAt" description:""` 53 | PRoleId int `json:"pRoleId" description:""` 54 | Pid int `json:"pid" description:""` 55 | PUsername string `json:"pUsername" description:""` 56 | RoleName string `json:"roleName" description:""` 57 | PRoleName string `json:"pRoleName" description:""` 58 | } 59 | type ItemUser struct { 60 | *UserInfo 61 | Level uint `json:"level" description:""` 62 | } 63 | type ListUserRes struct { 64 | List []*ItemUser `json:"list"` 65 | *vcommon.CommonPageRes 66 | } 67 | 68 | type OneUserReq struct { 69 | g.Meta `tags:"用户" method:"get" path:"/user" sm:"单个" dc:"用户" ` 70 | Id uint `json:"id" v:"required" description:""` 71 | } 72 | type OneUserRes *entity.User 73 | 74 | type UserInfoReq struct { 75 | g.Meta `tags:"用户" method:"get" path:"/user/info" sm:"用户信息" dc:"获取当前登录用户信息" ` 76 | //Id uint `json:"id" v:"required" description:""` 77 | } 78 | type UserInfoRes UserInfo 79 | 80 | // TreeListUserReq 上下级树 81 | type TreeListUserReq struct { 82 | g.Meta `tags:"用户" method:"get" path:"/user/tree" sm:"单个" dc:"用户树" ` 83 | } 84 | 85 | type TreeNodeUser struct { 86 | *entity.User 87 | Children []*TreeNodeUser `json:"children"` 88 | } 89 | 90 | type TreeListUserRes struct { 91 | List []*TreeNodeUser `json:"list"` 92 | } 93 | 94 | type LogoutReq struct { 95 | g.Meta `tags:"用户" method:"get" path:"/logout" sm:"登出" dc:"登出" ` 96 | } 97 | 98 | type LogoutRes struct{} 99 | -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # goframe-admin 2 |
3 | goframe-admin 4 |

goframe-admin V1.0.0

5 |

6 | 7 | goframe 8 | 9 | 10 | vue 11 | 12 | 13 | tdesign-vue-next 14 | 15 | 16 | typescript 17 | 18 | 19 | vite 20 | 21 | 22 | license 23 | 24 |

25 |
26 | 27 | ## 平台简介 28 | * 基于[goframe2.5.4](https://goframe.org/pages/viewpage.action?pageId=1114119)、[vue3](https://v3.vuejs.org/)、[tdesign-vue-next](https://tdesign.tencent.com/vue-next)开发的全栈前后端分离的管理系统。 29 | * 前端采用[tdesign-vue-next-starter](https://github.com/Tencent/tdesign-vue-next-starter) 、vue3、pinia、tdesign-vue-next。 30 | 31 | ## 特征 32 | * 高生产率:几分钟即可搭建一个后台管理系统 33 | * 认证机制:采用gtoken的用户状态认证及casbin的权限认证,支持按钮级别的权限 34 | * 路由模式:得益于goframe提供了规范化的路由注册方式,无需注解自动生成api文档 35 | * 面向接口开发 36 | 37 | ## 内置功能 38 | 1. 菜单管理:包含菜单、按钮、API的管理,后端配置菜单,前端获取菜单配置动态生成路由。 39 | 2. 用户管理:用户的增删改查,整个用户列表是一个树形结构,支持上下级,管理员只能查看到自己的下级用户。 40 | 3. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 41 | 4. 文件管理:本地文件上传,通过分片上传的方式支持1G以上的大文件上传。 42 | 5. 角色管理:角色菜单权限分配、设置角色按机构进行数据范围权限划分。 43 | 6. 字典管理:对系统中经常使用的一些较为固定的数据进行维护。 44 | 7. 登录日志:系统登录日志记录查询。 45 | 8. 个人中心:包含个人资料的修改,密码修改,2FA登录设置(OTP二步校验)。 46 | 9. 消息通知:包含通知的发送以及查看。 47 | 48 | ## 演示地址 49 | [http://admin.wxfk.one](http://admin.wxfk.one) 50 | - 超级管理员:`root`,密码:`1`; 51 | - 管理员:`admin`,密码:`1`; 52 | ## 配置 53 | 项目数据库文件 `resource/db.sql` 创建数据库导入后修改配置 `manifest/config/config.yaml` 54 | 55 | database配置改成自己的数据库连接 56 | ```yaml 57 | link: "mysql:root:123456@tcp(127.0.0.1:3306)/starter?loc=Local&parseTime=true" 58 | ``` 59 | redis部分也要改成自己的地址 60 | 61 | ## 前端部分 62 | 项目为前后端分离,前端github仓库地址:[https://github.com/apple1563/goframe-admin-ui](https://github.com/apple1563/goframe-admin-ui) 63 | 64 | ## 演示图 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 |
84 | 85 | ## 感谢(排名不分先后) 86 | > goframe [https://github.com/gogf/gf](https://github.com/gogf/gf) 87 | > 88 | > tdesign-vue-next-starter [https://github.com/Tencent/tdesign-vue-next-starter](https://github.com/Tencent/tdesign-vue-next-starter) 89 | > 90 | > gtoken [https://github.com/goflyfox/gtoken](https://github.com/goflyfox/gtoken) 91 | > 92 | > casbin [https://github.com/casbin/casbin](https://github.com/casbin/casbin) 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /internal/dao/internal/user.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // UserDao is the data access object for table user. 15 | type UserDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns UserColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // UserColumns defines and stores column names for table user. 22 | type UserColumns struct { 23 | Id string // 24 | Username string // 25 | Password string // 26 | Nickname string // 27 | Email string // 28 | Phone string // 29 | Status string // 1正常2禁用3注销 30 | ClientAgent string // 注册clientAgen头 31 | Ip string // IP 32 | RoleId string // 1用户3代理2管理 33 | CreatedAt string // 34 | UpdatedAt string // 35 | PRoleId string // 36 | Pid string // 37 | PUsername string // 38 | RoleName string // 39 | PRoleName string // 40 | } 41 | 42 | // userColumns holds the columns for table user. 43 | var userColumns = UserColumns{ 44 | Id: "id", 45 | Username: "username", 46 | Password: "password", 47 | Nickname: "nickname", 48 | Email: "email", 49 | Phone: "phone", 50 | Status: "status", 51 | ClientAgent: "client_agent", 52 | Ip: "ip", 53 | RoleId: "role_id", 54 | CreatedAt: "created_at", 55 | UpdatedAt: "updated_at", 56 | PRoleId: "p_role_id", 57 | Pid: "pid", 58 | PUsername: "p_username", 59 | RoleName: "role_name", 60 | PRoleName: "p_role_name", 61 | } 62 | 63 | // NewUserDao creates and returns a new DAO object for table data access. 64 | func NewUserDao() *UserDao { 65 | return &UserDao{ 66 | group: "default", 67 | table: "user", 68 | columns: userColumns, 69 | } 70 | } 71 | 72 | // DB retrieves and returns the underlying raw database management object of current DAO. 73 | func (dao *UserDao) DB() gdb.DB { 74 | return g.DB(dao.group) 75 | } 76 | 77 | // Table returns the table name of current dao. 78 | func (dao *UserDao) Table() string { 79 | return dao.table 80 | } 81 | 82 | // Columns returns all column names of current dao. 83 | func (dao *UserDao) Columns() UserColumns { 84 | return dao.columns 85 | } 86 | 87 | // Group returns the configuration group name of database of current dao. 88 | func (dao *UserDao) Group() string { 89 | return dao.group 90 | } 91 | 92 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 93 | func (dao *UserDao) Ctx(ctx context.Context) *gdb.Model { 94 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 95 | } 96 | 97 | // Transaction wraps the transaction logic using function f. 98 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 99 | // It commits the transaction and returns nil if function f returns nil. 100 | // 101 | // Note that, you should not Commit or Rollback the transaction in function f 102 | // as it is automatically handled by this function. 103 | func (dao *UserDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 104 | return dao.Ctx(ctx).Transaction(ctx, f) 105 | } 106 | -------------------------------------------------------------------------------- /internal/consts/consts.go: -------------------------------------------------------------------------------- 1 | package consts 2 | 3 | import ( 4 | "github.com/gogf/gf/v2/errors/gcode" 5 | "github.com/gogf/gf/v2/errors/gerror" 6 | ) 7 | 8 | var ( 9 | ErrTryAgain = gerror.NewCode(gcode.New(-4, "失败请重试", "")) 10 | ErrRepeatedSubmit = gerror.NewCode(gcode.New(-5, "请不要重复提交", "")) 11 | ErrSql = gerror.NewCode(gcode.New(-6, "sql执行异常", "")) 12 | ErrTypeAssertion = gerror.NewCode(gcode.New(-7, "类型断言错误", "")) 13 | ErrCaptcha = gerror.NewCode(gcode.New(-8, "验证码错误", "")) 14 | 15 | ErrLogin = gerror.NewCode(gcode.New(-100, "用户名或密码错误", "")) 16 | ErrPassEmpty = gerror.NewCode(gcode.New(-101, "密码不能为空", "")) 17 | ErrFormatEmail = gerror.NewCode(gcode.New(-102, "邮箱格式不正确", "")) 18 | ErrUnameExist = gerror.NewCode(gcode.New(-103, "用户名已存在", "")) 19 | ErrUnameFormat = gerror.NewCode(gcode.New(-104, "用户名长度在4到12位之间", "")) 20 | ErrPassFormat = gerror.NewCode(gcode.New(-105, "密码格式为任意可见字符,长度在6~18之间", "")) 21 | ErrPassErrorTooMany = gerror.NewCode(gcode.New(-106, "密码错误次数太多", "")) 22 | ErrOldPassNotMatch = gerror.NewCode(gcode.New(-107, "旧密码不正确", "")) 23 | ErrNicknameEmpty = gerror.NewCode(gcode.New(-108, "昵称不能为空", "")) 24 | ErrMaxLengthSixTy = gerror.NewCode(gcode.New(-109, "允许的最长字符为16", "")) 25 | ErrIconEmpty = gerror.NewCode(gcode.New(-110, "图片不能为空", "")) 26 | ErrUserDoesNotExist = gerror.NewCode(gcode.New(-111, "用户不存在", "")) 27 | ErrBalance = gerror.NewCode(gcode.New(-112, "用户余额错误", "")) 28 | ErrUserDead = gerror.NewCode(gcode.New(-113, "账号已注销", "")) 29 | ErrUserDisable = gerror.NewCode(gcode.New(-114, "账号已禁用", "")) 30 | ErrUserRole = gerror.NewCode(gcode.New(-115, "角色无登录权限", "")) 31 | ErrOtpCode = gerror.NewCode(gcode.New(-116, "OTP验证码错误", "")) 32 | 33 | ErrAreaCode = gerror.NewCode(gcode.New(-216, "手机区号错误", "")) 34 | ErrPhoneEmpty = gerror.NewCode(gcode.New(-120, "手机号不能为空", "")) 35 | ErrPhoneLength5 = gerror.NewCode(gcode.New(-121, "手机号长度最小5位数", "")) 36 | ErrUsernameExists = gerror.NewCode(gcode.New(-122, "用户名已存在", "")) 37 | 38 | ErrDepositClosed = gerror.NewCode(gcode.New(-1000, "充值通道已关闭", "")) 39 | ErrDepositIncorrect = gerror.NewCode(gcode.New(-1001, "充值金额不正确", "")) 40 | ErrDepositMin = gerror.NewCode(gcode.New(-1002, "最低充值额度100USDT", "")) 41 | 42 | ErrWithdrawClose = gerror.NewCode(gcode.New(-2000, "提现通道已关闭", "")) 43 | ErrWithdrawIncorrect = gerror.NewCode(gcode.New(-2001, "提现金额不正确", "")) 44 | ErrWithdrawBindAccount = gerror.NewCode(gcode.New(-2002, "请先绑定提现账号", "")) 45 | ErrWithdrawMin = gerror.NewCode(gcode.New(-2003, "低于最低提现额度", "")) 46 | ErrBindBankcard = gerror.NewCode(gcode.New(-2004, "您已绑定过银行卡", "")) 47 | 48 | ErrMenuPathExists = gerror.NewCode(gcode.New(-3000, "该path已存在", "")) 49 | ErrMenuPathDeleteChildren = gerror.NewCode(gcode.New(-3001, "请先删除该菜单下的所有菜单及按钮", "")) 50 | 51 | ErrButtonNameExists = gerror.NewCode(gcode.New(-3002, "该按钮标识码已存在", "")) 52 | ErrApiNameExists = gerror.NewCode(gcode.New(-3003, "该api已存在", "")) 53 | 54 | ErrRoleNameExists = gerror.NewCode(gcode.New(-4000, "角色名称已存在", "")) 55 | ErrRoleDelete = gerror.NewCode(gcode.New(-4001, "角色已被用户关联,请将关联用户设为其他角色", "")) 56 | 57 | ErrNoFileInput = gerror.NewCode(gcode.New(-5000, "没有上传文件", "")) 58 | ErrFileInput = gerror.NewCode(gcode.New(-5001, "上传出错", "")) 59 | 60 | ErrNoticeReceivers = gerror.NewCode(gcode.New(-6000, "请填写接收人", "")) 61 | ErrNoticeContent = gerror.NewCode(gcode.New(-6001, "内容不能为空", "")) 62 | ) 63 | 64 | const Role_Root_Code = 1024 //超级管理员 65 | const Role_User_Code = 1 66 | const Role_Admin_Code = 2 67 | const Role_Agent_Code = 3 68 | const Role_Caiwu_Code = 4 69 | 70 | const USER_STATUS_ENABLE = 1 71 | const USER_STATUS_DISABLE = 2 72 | const USER_STATUS_DEAD = 3 73 | 74 | const Cache_Mode_Memory = 1 75 | const Cache_Mode_Redis = 2 76 | 77 | // casbin sub前缀 78 | const Role_Api_Prefix = "role-api " 79 | const Role_Menu_Prefix = "role-menu " 80 | const Role_Button_Prefix = "role-button " 81 | 82 | // otp开关 83 | const OTP_STATUS_ON = 1 84 | const OTP_STATUS_OFF = 2 85 | -------------------------------------------------------------------------------- /internal/controller/otp/otp.go: -------------------------------------------------------------------------------- 1 | package otp 2 | 3 | import ( 4 | "context" 5 | "github.com/gogf/gf/v2/frame/g" 6 | "github.com/gogf/gf/v2/util/gconv" 7 | "goframe-starter/api/votp" 8 | "goframe-starter/internal/consts" 9 | "goframe-starter/internal/dao" 10 | "goframe-starter/internal/model/do" 11 | "goframe-starter/internal/model/entity" 12 | "goframe-starter/utility/xotp" 13 | ) 14 | 15 | type MyOtp struct{} 16 | 17 | var Ctrl = new(MyOtp) 18 | var cols = dao.OtpAuth.Columns() 19 | 20 | func (u *MyOtp) AddOtp(ctx context.Context, req *votp.AddOtpReq) (res *votp.AddOtpRes, err error) { 21 | var flag = xotp.ValidateOtp(req.Code, req.Secret) 22 | if flag { 23 | _, err = dao.OtpAuth.Ctx(ctx).Data(do.OtpAuth{ 24 | Uid: ctx.Value("uid"), 25 | Username: ctx.Value("username"), 26 | Secret: req.Secret, 27 | }).Insert() 28 | if err != nil { 29 | return nil, err 30 | } 31 | return 32 | } else { 33 | return nil, consts.ErrOtpCode 34 | } 35 | } 36 | 37 | func (u *MyOtp) UpdateOtp(ctx context.Context, req *votp.UpdateOtpReq) (res *votp.UpdateOtpRes, err error) { 38 | var flag = xotp.ValidateOtp(req.Code, req.Secret) 39 | if flag { 40 | var data = g.Map{} 41 | data[cols.Secret] = req.Secret 42 | data[cols.Uid] = gconv.Uint(ctx.Value("uid")) 43 | _, err = dao.OtpAuth.Ctx(ctx).Where(cols.Uid, ctx.Value("uid")).Data(data).Update() 44 | if err != nil { 45 | return nil, err 46 | } 47 | return 48 | } else { 49 | return nil, consts.ErrOtpCode 50 | } 51 | } 52 | 53 | func (u *MyOtp) UpdateOtpStatus(ctx context.Context, req *votp.UpdateOtpStatusReq) (res *votp.UpdateOtpStatusRes, err error) { 54 | _, err = dao.OtpAuth.Ctx(ctx).Where(cols.Uid, ctx.Value("uid")).Data(g.Map{ 55 | cols.Status: req.Status, 56 | }).Update() 57 | if err != nil { 58 | return nil, err 59 | } 60 | return 61 | } 62 | 63 | func (u *MyOtp) GetOtp(ctx context.Context, req *votp.OtpReq) (res *votp.OtpRes, err error) { 64 | res = &votp.OtpRes{} 65 | /*var count int 66 | err = dao.OtpAuth.Ctx(ctx).Where(cols.Uid, ctx.Value("uid")).ScanAndCount(&res, &count, false) 67 | if err != nil { 68 | return nil, err 69 | } 70 | // 没有设置过,则生成 71 | if count < 1 {*/ 72 | otp, err := xotp.GenerateOtp(gconv.String(ctx.Value("uid")), "goframe-admin") 73 | if err != nil { 74 | return nil, err 75 | } 76 | res.Url = otp.String() 77 | res.Secret = otp.Secret() 78 | //} 79 | 80 | return 81 | } 82 | 83 | func (u *MyOtp) OtpCheck(ctx context.Context, req *votp.OtpCheckReq) (res *votp.OtpCheckRes, err error) { 84 | res = &votp.OtpCheckRes{} 85 | var data *entity.OtpAuth 86 | var count int 87 | err = dao.OtpAuth.Ctx(ctx).Where(cols.Uid, ctx.Value("uid")).ScanAndCount(&data, &count, false) 88 | if err != nil { 89 | return nil, err 90 | } 91 | if count < 1 { 92 | res.IsSetted = false 93 | res.IsOpened = false 94 | } else { 95 | res.IsSetted = true 96 | res.IsOpened = data.Status == consts.OTP_STATUS_ON 97 | } 98 | return 99 | } 100 | 101 | func (u *MyOtp) OtpCheckByUsername(ctx context.Context, req *votp.OtpCheckByUsernameReq) (res *votp.OtpCheckByUsernameRes, err error) { 102 | res = &votp.OtpCheckByUsernameRes{} 103 | var data *entity.OtpAuth 104 | var count int 105 | err = dao.OtpAuth.Ctx(ctx).Where(cols.Username, req.Username).ScanAndCount(&data, &count, false) 106 | if err != nil { 107 | return nil, err 108 | } 109 | if count < 1 { 110 | res.IsOpened = false 111 | } else { 112 | res.IsOpened = data.Status == consts.OTP_STATUS_ON 113 | } 114 | return 115 | } 116 | 117 | func (u *MyOtp) OtpValidate(ctx context.Context, req *votp.OtpValidateReq) (res *votp.OtpValidateRes, err error) { 118 | res = &votp.OtpValidateRes{} 119 | var data *entity.OtpAuth 120 | err = dao.OtpAuth.Ctx(ctx).Where(cols.Username, req.Username).Scan(&data) 121 | if err != nil { 122 | return nil, err 123 | } 124 | var flag = xotp.ValidateOtp(req.Code, data.Secret) 125 | if flag { 126 | return 127 | } else { 128 | return nil, consts.ErrOtpCode 129 | } 130 | } 131 | -------------------------------------------------------------------------------- /internal/service/dictService/dict.go: -------------------------------------------------------------------------------- 1 | package dictService 2 | 3 | import ( 4 | "context" 5 | "github.com/gogf/gf/v2/frame/g" 6 | "goframe-starter/api/vcommon" 7 | "goframe-starter/api/vdict" 8 | "goframe-starter/internal/dao" 9 | "goframe-starter/internal/model/entity" 10 | ) 11 | 12 | var dictCols = dao.Dict.Columns() 13 | 14 | func AddDict(ctx context.Context, req *vdict.AddDictReq) (res *vdict.AddDictRes, err error) { 15 | var data = g.Map{} 16 | data[dictCols.CreateBy] = ctx.Value("uid") 17 | if req.Remark != "" { 18 | data[dictCols.Remark] = req.Remark 19 | } 20 | if req.ConfigType != "" { 21 | data[dictCols.ConfigType] = req.ConfigType 22 | } 23 | if req.ConfigName != "" { 24 | data[dictCols.ConfigName] = req.ConfigName 25 | } 26 | if req.ConfigKey != "" { 27 | data[dictCols.ConfigKey] = req.ConfigKey 28 | } 29 | if req.ConfigValue != "" { 30 | data[dictCols.ConfigValue] = req.ConfigValue 31 | } 32 | _, err = dao.Dict.Ctx(ctx).Data(data).Insert() 33 | if err != nil { 34 | return nil, err 35 | } 36 | return 37 | } 38 | 39 | func UpdateDict(ctx context.Context, req *vdict.UpdateDictReq) (res *vdict.UpdateDictRes, err error) { 40 | var data = g.Map{} 41 | data[dictCols.UpdateBy] = ctx.Value("uid") 42 | if req.Remark != "" { 43 | data[dictCols.Remark] = req.Remark 44 | } 45 | if req.ConfigType != "" { 46 | data[dictCols.ConfigType] = req.ConfigType 47 | } 48 | if req.ConfigName != "" { 49 | data[dictCols.ConfigName] = req.ConfigName 50 | } 51 | if req.ConfigKey != "" { 52 | data[dictCols.ConfigKey] = req.ConfigKey 53 | } 54 | if req.ConfigValue != "" { 55 | data[dictCols.ConfigValue] = req.ConfigValue 56 | } 57 | _, err = dao.Dict.Ctx(ctx).Where(dictCols.Id, req.Id).Data(data).Update() 58 | if err != nil { 59 | return nil, err 60 | } 61 | return 62 | } 63 | 64 | func DeleteDict(ctx context.Context, req *vdict.DeleteDictReq) (res *vdict.DeleteDictRes, err error) { 65 | _, err = dao.Dict.Ctx(ctx).WherePri(req.Id).Delete() 66 | if err != nil { 67 | return nil, err 68 | } 69 | return 70 | } 71 | 72 | func ListDict(ctx context.Context, req *vdict.ListDictReq) (res *vdict.ListDictRes, err error) { 73 | var resp = &vdict.ListDictRes{ 74 | List: make([]*entity.Dict, 0), 75 | CommonPageRes: &vcommon.CommonPageRes{}, 76 | } 77 | var data = g.Map{} 78 | if req.ConfigName != "" { 79 | data[dictCols.ConfigName+" like ?"] = "%" + req.ConfigName + "%" 80 | } 81 | if req.Id != 0 { 82 | data[dictCols.Id] = req.Id 83 | } 84 | if req.ConfigKey != "" { 85 | data[dictCols.ConfigKey] = req.ConfigKey 86 | } 87 | if req.ConfigType != "" { 88 | data[dictCols.ConfigType] = req.ConfigType 89 | } 90 | if req.CreateBy != 0 { 91 | data[dictCols.CreateBy] = req.CreateBy 92 | } 93 | if req.UpdateBy != 0 { 94 | data[dictCols.UpdateBy] = req.UpdateBy 95 | } 96 | var model = dao.Dict.Ctx(ctx).Where(data).Order(dictCols.ConfigType) 97 | if req.PageSize != 0 { 98 | resp.PageIndex = req.PageIndex 99 | resp.PageSize = req.PageSize 100 | model = model.Page(req.PageIndex, req.PageSize) 101 | } 102 | err = model.ScanAndCount(&resp.List, &resp.Total, false) 103 | if err != nil { 104 | return nil, err 105 | } 106 | return resp, nil 107 | } 108 | 109 | func OneDict(ctx context.Context, req *vdict.OneDictReq) (res *vdict.OneDictRes, err error) { 110 | err = dao.Dict.Ctx(ctx).Where(dictCols.Id, req.Id).Scan(&res) 111 | if err != nil { 112 | return nil, err 113 | } 114 | return 115 | } 116 | 117 | func GetValueByKey(ctx context.Context, key string) string { 118 | value, err := dao.Dict.Ctx(ctx).Where(dictCols.ConfigKey, key).Fields(dictCols.ConfigValue).Value() 119 | if err != nil { 120 | return "" 121 | } 122 | return value.String() 123 | } 124 | 125 | // 根据上传类型返回字典列表 126 | func ListDictByType(ctx context.Context, configType string) (res *vdict.ListDictByTypeRes, err error) { 127 | res = &vdict.ListDictByTypeRes{ 128 | List: make([]*entity.Dict, 0), 129 | } 130 | err = dao.Dict.Ctx(ctx).Where(dictCols.ConfigType, configType).Scan(&res.List) 131 | if err != nil { 132 | return nil, err 133 | } 134 | return 135 | } 136 | -------------------------------------------------------------------------------- /internal/service/apiService/api.go: -------------------------------------------------------------------------------- 1 | package apiService 2 | 3 | import ( 4 | "context" 5 | "github.com/gogf/gf/v2/frame/g" 6 | "github.com/gogf/gf/v2/util/gconv" 7 | "goframe-starter/api/vapi" 8 | "goframe-starter/api/vcommon" 9 | "goframe-starter/internal/consts" 10 | "goframe-starter/internal/dao" 11 | "goframe-starter/internal/model/entity" 12 | "goframe-starter/utility/xcasbin" 13 | ) 14 | 15 | var apiCols = dao.Api.Columns() 16 | 17 | func AddApi(ctx context.Context, req *vapi.AddApiReq) (res *vapi.AddApiRes, err error) { 18 | _, err = dao.Api.Ctx(ctx).Data(g.Map{ 19 | apiCols.Url: req.Url, 20 | apiCols.Group: req.Group, 21 | apiCols.Method: req.Method, 22 | apiCols.Remark: req.Remark, 23 | }).Insert() 24 | if err != nil { 25 | return nil, err 26 | } 27 | return 28 | } 29 | 30 | func UpdateApi(ctx context.Context, req *vapi.UpdateApiReq) (res *vapi.UpdateApiRes, err error) { 31 | _, err = dao.Api.Ctx(ctx).Where(apiCols.Id, req.Id).Data(g.Map{ 32 | apiCols.Url: req.Url, 33 | apiCols.Group: req.Group, 34 | apiCols.Method: req.Method, 35 | apiCols.Remark: req.Remark, 36 | }).Update() 37 | if err != nil { 38 | return nil, err 39 | } 40 | return 41 | } 42 | 43 | func DeleteApi(ctx context.Context, req *vapi.DeleteApiReq) (res *vapi.DeleteApiRes, err error) { 44 | var api *entity.Api 45 | err = dao.Api.Ctx(ctx).Where(apiCols.Id, req.Id).Scan(&api) 46 | if err != nil { 47 | return nil, err 48 | } 49 | _, err = dao.Api.Ctx(ctx).Where(apiCols.Id, req.Id).Delete() 50 | if err != nil { 51 | return nil, err 52 | } 53 | // 删除关联的casbin,删除角色与按钮关联 54 | var obj = api.Url 55 | var act = api.Method 56 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(1, obj, act) 57 | if err != nil { 58 | return nil, err 59 | } 60 | return 61 | } 62 | 63 | func ListApi(ctx context.Context, req *vapi.ListApiReq) (res *vapi.ListApiRes, err error) { 64 | var resp = &vapi.ListApiRes{ 65 | List: make([]*entity.Api, 0), 66 | CommonPageRes: &vcommon.CommonPageRes{}, 67 | } 68 | var data = g.Map{} 69 | if req.Url != "" { 70 | data[apiCols.Url+" like ?"] = "%" + req.Url + "%" 71 | } 72 | if req.Group != "" { 73 | data[apiCols.Group] = req.Group 74 | } 75 | var model = dao.Api.Ctx(ctx).Where(data).OrderDesc(apiCols.CreatedAt).OrderAsc(apiCols.Group) 76 | if req.PageSize != 0 { 77 | resp.PageIndex = req.PageIndex 78 | resp.PageSize = req.PageSize 79 | model = model.Page(req.PageIndex, req.PageSize) 80 | } 81 | err = model.ScanAndCount(&resp.List, &resp.Total, false) 82 | if err != nil { 83 | return nil, err 84 | } 85 | return resp, nil 86 | } 87 | 88 | func OneApi(ctx context.Context, req *vapi.OneApiReq) (res *vapi.OneApiRes, err error) { 89 | err = dao.Api.Ctx(ctx).Where(apiCols.Id, req.Id).Scan(&res) 90 | if err != nil { 91 | return nil, err 92 | } 93 | return 94 | } 95 | 96 | func AddApiForRole(ctx context.Context, req *vapi.ApiForRoleReq) (res *vapi.ApiForRoleRes, err error) { 97 | var sub = consts.Role_Api_Prefix + gconv.String(req.RoleId) 98 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(0, sub) 99 | if err != nil { 100 | return nil, err 101 | } 102 | for _, api := range req.Apis { 103 | _, err := xcasbin.Enforcer.AddPolicy(sub, api.Url, api.Method) 104 | if err != nil { 105 | return nil, err 106 | } 107 | } 108 | return 109 | } 110 | func GetApiByRole(ctx context.Context, req *vapi.ApiByRoleReq) (res *vapi.ApiByRoleRes, err error) { 111 | var sub = consts.Role_Api_Prefix + gconv.String(req.RoleId) 112 | var resp = &vapi.ApiByRoleRes{ 113 | List: make([]*vapi.ApiByRole, 0), 114 | } 115 | var rules = xcasbin.Enforcer.GetFilteredPolicy(0, sub) 116 | for _, rule := range rules { 117 | var apiByRole = &vapi.ApiByRole{ 118 | Url: rule[1], 119 | Method: rule[2], 120 | } 121 | resp.List = append(resp.List, apiByRole) 122 | } 123 | return resp, nil 124 | } 125 | 126 | func CheckApiExists(ctx context.Context, url string, method string) bool { 127 | count, err := dao.Api.Ctx(ctx).Where(g.Map{ 128 | apiCols.Url: url, 129 | apiCols.Method: method, 130 | }).Count() 131 | if err != nil { 132 | return true 133 | } 134 | if count > 0 { 135 | return true 136 | } 137 | return false 138 | } 139 | -------------------------------------------------------------------------------- /internal/dao/internal/menu.go: -------------------------------------------------------------------------------- 1 | // ========================================================================== 2 | // Code generated and maintained by GoFrame CLI tool. DO NOT EDIT. 3 | // ========================================================================== 4 | 5 | package internal 6 | 7 | import ( 8 | "context" 9 | 10 | "github.com/gogf/gf/v2/database/gdb" 11 | "github.com/gogf/gf/v2/frame/g" 12 | ) 13 | 14 | // MenuDao is the data access object for table menu. 15 | type MenuDao struct { 16 | table string // table is the underlying table name of the DAO. 17 | group string // group is the database configuration group name of current DAO. 18 | columns MenuColumns // columns contains all the column names of Table for convenient usage. 19 | } 20 | 21 | // MenuColumns defines and stores column names for table menu. 22 | type MenuColumns struct { 23 | Id string // 菜单ID 24 | Pid string // 父菜单ID,0表示根级 25 | Title string // 菜单名称 26 | Name string // 名称编码 27 | Path string // 路由地址 28 | Icon string // 菜单图标 29 | Type string // 菜单类型(1目录 2菜单) 30 | Redirect string // 重定向地址 31 | Permissions string // 菜单包含权限集合 32 | PermissionName string // 权限名称 33 | Component string // 组件路径 34 | AlwaysShow string // 取消自动计算根路由模式 1是2否 35 | ActiveMenu string // 高亮菜单编码 36 | IsRoot string // 是否跟路由 37 | IsFrame string // 是否跳转外链 38 | FrameSrc string // iframe地址 39 | KeepAlive string // 缓存该路由,1是2否 40 | Hidden string // 是否隐藏,1是2否 41 | Affix string // 是否固定 42 | Level string // 关系树等级 1根2子3孙 43 | Tree string // 关系树 44 | Sort string // 排序 45 | Remark string // 备注 46 | Status string // 菜单状态 47 | CreatedAt string // 创建时间 48 | UpdatedAt string // 更新时间 49 | } 50 | 51 | // menuColumns holds the columns for table menu. 52 | var menuColumns = MenuColumns{ 53 | Id: "id", 54 | Pid: "pid", 55 | Title: "title", 56 | Name: "name", 57 | Path: "path", 58 | Icon: "icon", 59 | Type: "type", 60 | Redirect: "redirect", 61 | Permissions: "permissions", 62 | PermissionName: "permission_name", 63 | Component: "component", 64 | AlwaysShow: "always_show", 65 | ActiveMenu: "active_menu", 66 | IsRoot: "is_root", 67 | IsFrame: "is_frame", 68 | FrameSrc: "frame_src", 69 | KeepAlive: "keep_alive", 70 | Hidden: "hidden", 71 | Affix: "affix", 72 | Level: "level", 73 | Tree: "tree", 74 | Sort: "sort", 75 | Remark: "remark", 76 | Status: "status", 77 | CreatedAt: "created_at", 78 | UpdatedAt: "updated_at", 79 | } 80 | 81 | // NewMenuDao creates and returns a new DAO object for table data access. 82 | func NewMenuDao() *MenuDao { 83 | return &MenuDao{ 84 | group: "default", 85 | table: "menu", 86 | columns: menuColumns, 87 | } 88 | } 89 | 90 | // DB retrieves and returns the underlying raw database management object of current DAO. 91 | func (dao *MenuDao) DB() gdb.DB { 92 | return g.DB(dao.group) 93 | } 94 | 95 | // Table returns the table name of current dao. 96 | func (dao *MenuDao) Table() string { 97 | return dao.table 98 | } 99 | 100 | // Columns returns all column names of current dao. 101 | func (dao *MenuDao) Columns() MenuColumns { 102 | return dao.columns 103 | } 104 | 105 | // Group returns the configuration group name of database of current dao. 106 | func (dao *MenuDao) Group() string { 107 | return dao.group 108 | } 109 | 110 | // Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. 111 | func (dao *MenuDao) Ctx(ctx context.Context) *gdb.Model { 112 | return dao.DB().Model(dao.table).Safe().Ctx(ctx) 113 | } 114 | 115 | // Transaction wraps the transaction logic using function f. 116 | // It rollbacks the transaction and returns the error from function f if it returns non-nil error. 117 | // It commits the transaction and returns nil if function f returns nil. 118 | // 119 | // Note that, you should not Commit or Rollback the transaction in function f 120 | // as it is automatically handled by this function. 121 | func (dao *MenuDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { 122 | return dao.Ctx(ctx).Transaction(ctx, f) 123 | } 124 | -------------------------------------------------------------------------------- /internal/service/roleService/role.go: -------------------------------------------------------------------------------- 1 | package roleService 2 | 3 | import ( 4 | "context" 5 | "github.com/gogf/gf/v2/frame/g" 6 | "github.com/gogf/gf/v2/util/gconv" 7 | "goframe-starter/api/vcommon" 8 | "goframe-starter/api/vrole" 9 | "goframe-starter/internal/consts" 10 | "goframe-starter/internal/dao" 11 | "goframe-starter/internal/model/entity" 12 | "goframe-starter/utility/xcasbin" 13 | ) 14 | 15 | var roleCols = dao.Role.Columns() 16 | var userCols = dao.User.Columns() 17 | 18 | func AddRole(ctx context.Context, req *vrole.AddRoleReq) (res *vrole.AddRoleRes, err error) { 19 | count, err := dao.Role.Ctx(ctx).Where(roleCols.Name, req.Name).Count() 20 | if err != nil { 21 | return nil, err 22 | } 23 | if count > 0 { 24 | return nil, consts.ErrRoleNameExists 25 | } 26 | _, err = dao.Role.Ctx(ctx).Data(g.Map{ 27 | roleCols.ListOrder: req.ListOrder, 28 | roleCols.Name: req.Name, 29 | roleCols.Remark: req.Remark, 30 | }).Insert() 31 | if err != nil { 32 | return nil, err 33 | } 34 | return 35 | } 36 | 37 | func UpdateRole(ctx context.Context, req *vrole.UpdateRoleReq) (res *vrole.UpdateRoleRes, err error) { 38 | _, err = dao.Role.Ctx(ctx).Where(roleCols.Id, req.Id).Data(g.Map{ 39 | roleCols.ListOrder: req.ListOrder, 40 | roleCols.Name: req.Name, 41 | roleCols.Remark: req.Remark, 42 | }).Update() 43 | if err != nil { 44 | return nil, err 45 | } 46 | return 47 | } 48 | 49 | func DeleteRole(ctx context.Context, req *vrole.DeleteRoleReq) (res *vrole.DeleteRoleRes, err error) { 50 | // 删之前还要判断下这个角色有没有被其他用户绑定 51 | count, err := dao.User.Ctx(ctx).Where(userCols.RoleId, req.Id).Count() 52 | if err != nil { 53 | return nil, err 54 | } 55 | if count > 0 { 56 | return nil, consts.ErrRoleDelete 57 | } 58 | _, err = dao.Role.Ctx(ctx).WherePri(req.Id).Delete() 59 | if err != nil { 60 | return nil, err 61 | } 62 | // 角色绑定的权限规则,如casbin也要删除 63 | var sub = consts.Role_Menu_Prefix + gconv.String(req.Id) 64 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(0, sub) 65 | if err != nil { 66 | return nil, err 67 | } 68 | // 按钮绑定的权限规则,如casbin也要删除 69 | var sub2 = consts.Role_Button_Prefix + gconv.String(req.Id) 70 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(0, sub2) 71 | if err != nil { 72 | return nil, err 73 | } 74 | // api绑定的权限规则,如casbin也要删除 75 | var sub3 = consts.Role_Api_Prefix + gconv.String(req.Id) 76 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(0, sub3) 77 | if err != nil { 78 | return nil, err 79 | } 80 | return 81 | } 82 | 83 | func ListRole(ctx context.Context, req *vrole.ListRoleReq) (res *vrole.ListRoleRes, err error) { 84 | var resp = &vrole.ListRoleRes{ 85 | List: make([]*entity.Role, 0), 86 | CommonPageRes: &vcommon.CommonPageRes{}, 87 | } 88 | var data = g.Map{} 89 | if req.Name != "" { 90 | data[roleCols.Name+" like ?"] = "%" + req.Name + "%" 91 | } 92 | if req.Id != 0 { 93 | data[roleCols.Id] = req.Id 94 | } 95 | var model = dao.Role.Ctx(ctx).Where(data).Order(roleCols.ListOrder) 96 | if req.PageSize != 0 { 97 | resp.PageIndex = req.PageIndex 98 | resp.PageSize = req.PageSize 99 | model = model.Page(req.PageIndex, req.PageSize) 100 | } 101 | err = model.ScanAndCount(&resp.List, &resp.Total, false) 102 | if err != nil { 103 | return nil, err 104 | } 105 | return resp, nil 106 | } 107 | 108 | func OneRole(ctx context.Context, req *vrole.OneRoleReq) (res *vrole.OneRoleRes, err error) { 109 | err = dao.Role.Ctx(ctx).Where(roleCols.Id, req.Id).Scan(&res) 110 | if err != nil { 111 | return nil, err 112 | } 113 | return 114 | } 115 | 116 | // ListRoleForSelect 添加用户的角色下拉选择框,管理员新增用户可选任意角色。代理新增用户只能选代理和用户两个角色 117 | func ListRoleForSelect(ctx context.Context, req *vrole.ListRoleForSelectReq) (res *vrole.ListRoleForSelectRes, err error) { 118 | var resp = &vrole.ListRoleForSelectRes{ 119 | List: make([]*entity.Role, 0), 120 | } 121 | var roleId = gconv.Uint(ctx.Value("roleId")) 122 | //超级管理员 123 | if roleId == consts.Role_Root_Code { 124 | err := dao.Role.Ctx(ctx).WhereNot(roleCols.Id, roleId).Scan(&resp.List) 125 | if err != nil { 126 | return nil, err 127 | } 128 | } else if roleId == consts.Role_Admin_Code { 129 | // 管理员可以选择管理员,代理,用户 130 | err := dao.Role.Ctx(ctx).WhereIn(roleCols.Id, g.Slice{1, 3, roleId}).Scan(&resp.List) 131 | if err != nil { 132 | return nil, err 133 | } 134 | } else { 135 | //菲超级管理员新增用户只能选自身角色和用户角色,用户角色为1 136 | err := dao.Role.Ctx(ctx).WhereIn(roleCols.Id, g.Slice{1, roleId}).Scan(&resp.List) 137 | if err != nil { 138 | return nil, err 139 | } 140 | } 141 | return resp, nil 142 | } 143 | -------------------------------------------------------------------------------- /internal/service/gtokenService/gtoken.go: -------------------------------------------------------------------------------- 1 | package gtokenService 2 | 3 | import ( 4 | "github.com/goflyfox/gtoken/gtoken" 5 | "github.com/gogf/gf/v2/encoding/gjson" 6 | "github.com/gogf/gf/v2/frame/g" 7 | "github.com/gogf/gf/v2/net/ghttp" 8 | "github.com/gogf/gf/v2/util/gconv" 9 | "goframe-starter/internal/consts" 10 | "goframe-starter/internal/dao" 11 | "goframe-starter/internal/model/entity" 12 | "goframe-starter/utility/xcasbin" 13 | "goframe-starter/utility/xpwd" 14 | ) 15 | 16 | type GFtokenFn struct { 17 | } 18 | 19 | var GFtokenFnInstance = new(GFtokenFn) 20 | 21 | func (*GFtokenFn) LoginBeforeFunc(r *ghttp.Request) (string, interface{}) { 22 | var ( 23 | ctx = r.Context() 24 | username = r.Get("username").String() 25 | password = r.Get("password").String() 26 | ) 27 | if username == "" || password == "" { 28 | r.Response.WriteJson(gtoken.Fail("ACCOUNT OR PASSWORD CANNOT BE EMPTY.")) 29 | r.ExitAll() 30 | } 31 | var user *entity.User 32 | var count int 33 | var userCols = dao.User.Columns() 34 | // 检验账号密码 35 | err := dao.User.Ctx(ctx).Where(g.Map{ 36 | userCols.Username: username, 37 | }).ScanAndCount(&user, &count, false) 38 | if err != nil { 39 | r.Response.WriteJson(err) 40 | r.ExitAll() 41 | } 42 | if count < 1 { 43 | r.Response.WriteJson(gtoken.Fail("ACCOUNT NOT EXISTED.")) 44 | r.ExitAll() 45 | } 46 | // 根据status判断用户可否登录 47 | if user.Status == consts.USER_STATUS_DEAD { 48 | r.Response.WriteJson(gtoken.Fail(consts.ErrUserDead.Error())) 49 | r.ExitAll() 50 | } 51 | if user.Status == consts.USER_STATUS_DISABLE { 52 | r.Response.WriteJson(gtoken.Fail(consts.ErrUserDisable.Error())) 53 | r.ExitAll() 54 | } 55 | if !xpwd.ComparePassword(user.Password, password) { 56 | r.Response.WriteJson(gtoken.Fail("WRONG PASSWORD.")) 57 | r.ExitAll() 58 | } 59 | // 用户角色不能登录后台 60 | /*if user.RoleId == consts.Role_User_Code { 61 | r.Response.WriteJson(consts.ErrUserRole) 62 | r.ExitAll() 63 | }*/ 64 | // 判断角色有无登录后台权限 65 | enforce, _ := xcasbin.Enforcer.Enforce(consts.Role_Api_Prefix+gconv.String(user.RoleId), r.URL.Path, r.Method) 66 | if !enforce { 67 | r.Response.WriteJson(gtoken.Fail(consts.ErrUserRole.Error())) 68 | r.ExitAll() 69 | } 70 | // 写入登录日志 71 | var loginLogCols = dao.LoginLog.Columns() 72 | _, err = dao.LoginLog.Ctx(ctx).Data(g.Map{ 73 | loginLogCols.Uid: user.Id, 74 | loginLogCols.RoleId: user.RoleId, 75 | loginLogCols.RoleName: user.RoleName, 76 | loginLogCols.Username: user.Username, 77 | loginLogCols.ClientAgent: r.UserAgent(), 78 | loginLogCols.PRoleId: user.PRoleId, 79 | loginLogCols.Pid: user.Pid, 80 | loginLogCols.PUsername: user.PUsername, 81 | loginLogCols.Ip: r.GetClientIp(), 82 | }).Insert() 83 | if err != nil { 84 | r.Response.WriteJson(gtoken.Fail("SAVE LOGIN LOG ERROR.")) 85 | r.ExitAll() 86 | } 87 | 88 | return username, user 89 | } 90 | 91 | /*func (*GFtokenFn) AuthBeforeFunc(r *ghttp.Request) bool { 92 | return true 93 | }*/ 94 | 95 | func (*GFtokenFn) AuthAfterFunc(r *ghttp.Request, respData gtoken.Resp) { 96 | if respData.Code != 0 { 97 | switch r.Method { 98 | case "PUT", "DELETE", "GET", "POST": 99 | r.Response.WriteJsonExit(respData) 100 | } 101 | return 102 | } 103 | var userInfo *entity.User 104 | err := gjson.New(respData.Data).Get("data").Struct(&userInfo) 105 | if err != nil { 106 | r.Response.WriteJsonExit(err) 107 | return 108 | } 109 | //r.SetCtxVar("userInfo", userInfo) 110 | r.SetCtxVar("uid", userInfo.Id) 111 | r.SetCtxVar("username", userInfo.Username) 112 | r.SetCtxVar("pid", userInfo.Pid) 113 | r.SetCtxVar("roleId", userInfo.RoleId) 114 | 115 | // 登录校验后 casbin权限校验 116 | enforce, _ := xcasbin.Enforcer.Enforce(consts.Role_Api_Prefix+gconv.String(userInfo.RoleId), r.URL.Path, r.Method) 117 | if !enforce { 118 | respData.Code = -403 119 | respData.Data = "未授权" 120 | r.Response.Status = 403 121 | r.Response.WriteJsonExit(respData) 122 | return 123 | } 124 | r.Middleware.Next() 125 | //elapsedTime := time.Since(timeStart) 126 | //requestBody := r.GetBodyString() 127 | //写入操作日志 128 | /*go func(ctx1 context.Context) { 129 | log := model.OperateLog{ 130 | Ip: u.ClientIp, 131 | Path: r.URL.Path, 132 | Method: r.Method, 133 | Account: u.Account, 134 | RoleName: u.RuleName, 135 | Request: fmt.Sprint(requestBody), 136 | Response: r.Response.BufferString(), 137 | CreatedAt: time.Now(), 138 | ElapsedTime: elapsedTime.Milliseconds(), 139 | } 140 | format := time.Now().Format("2006-01-02") 141 | sprint := fmt.Sprint("admin_operate_log_", format) 142 | xelastic.Create(ctx1, sprint, log) 143 | }(context.Background())*/ 144 | } 145 | -------------------------------------------------------------------------------- /internal/service/buttonService/button.go: -------------------------------------------------------------------------------- 1 | package buttonService 2 | 3 | import ( 4 | "context" 5 | "github.com/gogf/gf/v2/frame/g" 6 | "github.com/gogf/gf/v2/util/gconv" 7 | "goframe-starter/api/vbutton" 8 | "goframe-starter/api/vcommon" 9 | "goframe-starter/internal/consts" 10 | "goframe-starter/internal/dao" 11 | "goframe-starter/internal/model/entity" 12 | "goframe-starter/utility/xcasbin" 13 | "strings" 14 | ) 15 | 16 | var buttonCols = dao.Button.Columns() 17 | 18 | func AddButton(ctx context.Context, req *vbutton.AddButtonReq) (res *vbutton.AddButtonRes, err error) { 19 | count, err := dao.Button.Ctx(ctx).Where(g.Map{ 20 | buttonCols.Name: req.Name, 21 | buttonCols.MenuId: req.MenuId, 22 | }).Count() 23 | if err != nil { 24 | return nil, err 25 | } 26 | if count > 0 { 27 | return nil, consts.ErrButtonNameExists 28 | } 29 | _, err = dao.Button.Ctx(ctx).Data(g.Map{ 30 | buttonCols.MenuId: req.MenuId, 31 | buttonCols.MenuTitle: req.MenuTitle, 32 | buttonCols.Name: req.Name, 33 | buttonCols.Title: req.Title, 34 | buttonCols.Remark: req.Remark, 35 | }).Insert() 36 | if err != nil { 37 | return nil, err 38 | } 39 | return 40 | } 41 | 42 | func UpdateButton(ctx context.Context, req *vbutton.UpdateButtonReq) (res *vbutton.UpdateButtonRes, err error) { 43 | _, err = dao.Button.Ctx(ctx).Where(buttonCols.Id, req.Id).Data(g.Map{ 44 | buttonCols.MenuId: req.MenuId, 45 | buttonCols.MenuTitle: req.MenuTitle, 46 | buttonCols.Name: req.Name, 47 | buttonCols.Title: req.Title, 48 | buttonCols.Remark: req.Remark, 49 | }).Update() 50 | if err != nil { 51 | return nil, err 52 | } 53 | return 54 | } 55 | 56 | func DeleteButton(ctx context.Context, req *vbutton.DeleteButtonReq) (res *vbutton.DeleteButtonRes, err error) { 57 | _, err = dao.Button.Ctx(ctx).WherePri(req.Id).Delete() 58 | if err != nil { 59 | return nil, err 60 | } 61 | // 删除关联的casbin,删除角色与按钮关联 62 | var obj = "button " + gconv.String(req.Id) 63 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(1, obj) 64 | if err != nil { 65 | return nil, err 66 | } 67 | return 68 | } 69 | 70 | func ListButton(ctx context.Context, req *vbutton.ListButtonReq) (res *vbutton.ListButtonRes, err error) { 71 | var resp = &vbutton.ListButtonRes{ 72 | List: make([]*entity.Button, 0), 73 | CommonPageRes: &vcommon.CommonPageRes{}, 74 | } 75 | var data = g.Map{} 76 | if req.Name != "" { 77 | data[buttonCols.Name+" like ?"] = "%" + req.Name + "%" 78 | } 79 | if req.Title != "" { 80 | data[buttonCols.Title+" like ?"] = "%" + req.Title + "%" 81 | } 82 | if req.MenuTitle != "" { 83 | data[buttonCols.MenuTitle+" like ?"] = "%" + req.MenuTitle + "%" 84 | } 85 | if req.Id != 0 { 86 | data[buttonCols.Id] = req.Id 87 | } 88 | var model = dao.Button.Ctx(ctx).Where(data).Order(buttonCols.MenuId) 89 | if req.PageSize != 0 { 90 | resp.PageIndex = req.PageIndex 91 | resp.PageSize = req.PageSize 92 | model = model.Page(req.PageIndex, req.PageSize) 93 | } 94 | err = model.ScanAndCount(&resp.List, &resp.Total, false) 95 | if err != nil { 96 | return nil, err 97 | } 98 | return resp, nil 99 | } 100 | 101 | func OneButton(ctx context.Context, req *vbutton.OneButtonReq) (res *vbutton.OneButtonRes, err error) { 102 | err = dao.Button.Ctx(ctx).Where(buttonCols.Id, req.Id).Scan(&res) 103 | if err != nil { 104 | return nil, err 105 | } 106 | return 107 | } 108 | 109 | func AddButtonForRole(ctx context.Context, req *vbutton.ButtonForRoleReq) (res *vbutton.ButtonForRoleRes, err error) { 110 | var sub = consts.Role_Button_Prefix + gconv.String(req.RoleId) 111 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(0, sub) 112 | if err != nil { 113 | return nil, err 114 | } 115 | for _, buttonId := range req.ButtonIds { 116 | var obj = "button " + gconv.String(buttonId) 117 | _, err := xcasbin.Enforcer.AddPolicy(sub, gconv.String(obj), "ALL") 118 | if err != nil { 119 | return nil, err 120 | } 121 | } 122 | return 123 | } 124 | func getRoleButtonIds(roleId uint) []int { 125 | var sub = consts.Role_Button_Prefix + gconv.String(roleId) 126 | var rules = xcasbin.Enforcer.GetFilteredPolicy(0, sub) 127 | var res = make([]int, 0) 128 | for _, rule := range rules { 129 | parts := strings.Split(rule[1], " ") 130 | res = append(res, gconv.Int(parts[1])) 131 | } 132 | return res 133 | } 134 | func GetButtonByRole(ctx context.Context, req *vbutton.ButtonByRoleReq) (res *vbutton.ButtonByRoleRes, err error) { 135 | var resp = &vbutton.ButtonByRoleRes{ 136 | List: make([]int, 0), 137 | } 138 | var ids = getRoleButtonIds(req.RoleId) 139 | for _, id := range ids { 140 | resp.List = append(resp.List, id) 141 | } 142 | return resp, nil 143 | } 144 | func ButtonWhitelist(ctx context.Context, req *vbutton.ButtonWhitelistReq) (res *vbutton.ButtonWhitelistRes, err error) { 145 | var resp = &vbutton.ButtonWhitelistRes{ 146 | List: make([]int, 0), 147 | } 148 | // 超级管理员返回所有按钮,其他角色按权限设置的来 149 | var roleId = gconv.Uint(ctx.Value("roleId")) 150 | if roleId == 1024 { // 1024为超级管理员 151 | array, err := dao.Button.Ctx(ctx).Fields(buttonCols.Id).Array() 152 | if err != nil { 153 | return nil, err 154 | } 155 | for _, value := range array { 156 | resp.List = append(resp.List, value.Int()) 157 | } 158 | } else { 159 | resp.List = getRoleButtonIds(roleId) 160 | } 161 | 162 | return resp, nil 163 | } 164 | -------------------------------------------------------------------------------- /internal/service/fileService/file.go: -------------------------------------------------------------------------------- 1 | package fileService 2 | 3 | import ( 4 | "context" 5 | "github.com/gogf/gf/v2/frame/g" 6 | "github.com/gogf/gf/v2/net/ghttp" 7 | "github.com/gogf/gf/v2/os/gfile" 8 | "github.com/gogf/gf/v2/text/gstr" 9 | "github.com/gogf/gf/v2/util/gconv" 10 | "github.com/gogf/gf/v2/util/guid" 11 | "goframe-starter/api/vcommon" 12 | "goframe-starter/api/vfile" 13 | "goframe-starter/internal/consts" 14 | "goframe-starter/internal/dao" 15 | "goframe-starter/internal/model/entity" 16 | "io" 17 | "os" 18 | "path/filepath" 19 | "sync" 20 | "time" 21 | ) 22 | 23 | var fileCols = dao.File.Columns() 24 | 25 | func AddFile(ctx context.Context, req *vfile.AddFileReq) (res *vfile.AddFileRes, err error) { 26 | if req.File == nil { 27 | return nil, consts.ErrNoFileInput 28 | } 29 | var wg sync.WaitGroup 30 | errCh := make(chan error, len(req.File)) 31 | res = &vfile.AddFileRes{ 32 | List: make([]string, 0), 33 | } 34 | for _, file := range req.File { 35 | wg.Add(1) 36 | if file == nil { 37 | continue // 跳过空文件 38 | } 39 | go func(f *ghttp.UploadFile) { 40 | defer wg.Done() 41 | var folder = time.Now().Format("2006-01-02") 42 | var dirPath = g.Cfg().MustGet(ctx, "server.uploadRoot").String() + "/" + folder 43 | filename, err := f.Save(dirPath, true) 44 | if err != nil { 45 | errCh <- err 46 | return 47 | } 48 | var slice = gstr.SplitAndTrim(f.Filename, ".") 49 | _, err = dao.File.Ctx(ctx).Data(g.Map{ 50 | fileCols.FileUrl: "upload/" + folder + "/" + filename, 51 | fileCols.Size: f.Size, 52 | fileCols.Drive: req.Drive, 53 | fileCols.OriginName: f.Filename, 54 | fileCols.Ext: slice[len(slice)-1], 55 | fileCols.Uid: ctx.Value("uid"), 56 | }).Insert() 57 | if err != nil { 58 | _ = gfile.Remove(filepath.Join(gfile.MainPkgPath() + dirPath + filename)) 59 | return 60 | } 61 | res.List = append(res.List, filename) 62 | }(file) 63 | 64 | } 65 | go func() { 66 | wg.Wait() 67 | close(errCh) // 关闭通道,表示不会再有错误传递 68 | }() 69 | // 在这里可以从 errCh 通道读取错误 70 | for err := range errCh { 71 | // 处理错误,可以将错误记录到日志或其他操作 72 | if err != nil { 73 | return nil, err 74 | } 75 | } 76 | return 77 | } 78 | 79 | func UpdateFile(ctx context.Context, req *vfile.UpdateFileReq) (res *vfile.UpdateFileRes, err error) { 80 | var data = g.Map{} 81 | data[fileCols.Remark] = req.Remark 82 | _, err = dao.File.Ctx(ctx).Where(fileCols.Id, req.Id).Data(data).Update() 83 | if err != nil { 84 | return nil, err 85 | } 86 | return 87 | } 88 | 89 | func DeleteFile(ctx context.Context, req *vfile.DeleteFileReq) (res *vfile.DeleteFileRes, err error) { 90 | value, err := dao.File.Ctx(ctx).WherePri(req.Id).Fields(fileCols.FileUrl).Value() 91 | if err != nil { 92 | return nil, err 93 | } 94 | _, err = dao.File.Ctx(ctx).WherePri(req.Id).Delete() 95 | if err != nil { 96 | return nil, err 97 | } 98 | _ = gfile.Remove(gfile.MainPkgPath() + "/" + g.Cfg().MustGet(ctx, "server.uploadRoot").String() + "/" + value.String()) 99 | return 100 | } 101 | 102 | func ListFile(ctx context.Context, req *vfile.ListFileReq) (res *vfile.ListFileRes, err error) { 103 | res = &vfile.ListFileRes{ 104 | List: make([]*entity.File, 0), 105 | CommonPageRes: &vcommon.CommonPageRes{}, 106 | } 107 | res.PageIndex = req.PageIndex 108 | res.PageSize = req.PageSize 109 | var model = dao.File.Ctx(ctx).OrderDesc(fileCols.UpdatedAt) 110 | if req.Drive != "" { 111 | model = model.Where(fileCols.Drive, req.Drive) 112 | } 113 | if req.OriginName != "" { 114 | model = model.WhereLike(fileCols.OriginName, "%"+req.OriginName+"%") 115 | } 116 | if req.Ext != "" { 117 | model = model.WhereLike(fileCols.Ext, "%"+req.Ext+"%") 118 | } 119 | err = model.Page(req.PageIndex, req.PageSize).ScanAndCount(&res.List, &res.Total, false) 120 | if err != nil { 121 | return nil, err 122 | } 123 | return 124 | } 125 | 126 | func OneFile(ctx context.Context, req *vfile.OneFileReq) (res *vfile.OneFileRes, err error) { 127 | err = dao.File.Ctx(ctx).Where(fileCols.Id, req.Id).Scan(&res) 128 | if err != nil { 129 | return nil, err 130 | } 131 | return 132 | } 133 | 134 | func UploadChunk(ctx context.Context, req *vfile.UploadChunkReq) (res *vfile.UploadChunkRes, err error) { 135 | res = &vfile.UploadChunkRes{} 136 | if req.Chunk == nil { 137 | return nil, consts.ErrNoFileInput 138 | } 139 | // 保存到临时目录 140 | var folder = req.Temp 141 | var uploadPath = g.Cfg().MustGet(ctx, "server.uploadRoot").String() + "/" 142 | var tempPath = uploadPath + folder 143 | _, err = req.Chunk.Save(tempPath) 144 | if err != nil { 145 | return nil, err 146 | } 147 | // 分片上完,合并分片 148 | if req.ChunkIndex+1 == req.TotalChunks { 149 | var folder = time.Now().Format("2006-01-02") 150 | var dirPath = uploadPath + folder 151 | _ = os.Mkdir(dirPath, 0777) 152 | var filename = guid.S() + "." + req.OriginName 153 | var outputFilePath = dirPath + "/" + filename 154 | err = combineChunks(req.TotalChunks, outputFilePath, tempPath) 155 | if err != nil { 156 | return nil, err 157 | } 158 | // 插入数据库 159 | var fileUrl = folder + "/" + filename 160 | _, err = dao.File.Ctx(ctx).Data(g.Map{ 161 | fileCols.FileUrl: "upload/" + fileUrl, 162 | fileCols.Size: req.Size, 163 | fileCols.Drive: req.Drive, 164 | fileCols.OriginName: req.OriginName, 165 | fileCols.Ext: req.Ext, 166 | fileCols.Uid: ctx.Value("uid"), 167 | }).Insert() 168 | res.FileUrl = fileUrl 169 | if err != nil { 170 | _ = gfile.Remove(filepath.Join(gfile.MainPkgPath() + dirPath + filename)) 171 | return nil, err 172 | } 173 | } 174 | return 175 | } 176 | func combineChunks(totalChunks int, outputFilePath string, tempDir string) error { 177 | // 创建最终文件 178 | outputFile, err := os.Create(outputFilePath) 179 | if err != nil { 180 | return err 181 | } 182 | 183 | for i := 0; i < totalChunks; i++ { 184 | chunkFilePath := filepath.Join(gfile.MainPkgPath(), tempDir, gconv.String(i)) 185 | 186 | // 打开分片文件 187 | chunkFile, err := os.Open(chunkFilePath) 188 | if err != nil { 189 | return err 190 | } 191 | // 从分片文件中读取数据并写入最终文件 192 | _, err = io.Copy(outputFile, chunkFile) 193 | if err != nil { 194 | err2 := chunkFile.Close() 195 | if err2 != nil { 196 | return err2 197 | } 198 | return err 199 | } 200 | err = chunkFile.Close() 201 | if err != nil { 202 | return err 203 | } 204 | } 205 | err = outputFile.Close() 206 | if err != nil { 207 | return err 208 | } 209 | _ = os.RemoveAll(tempDir) 210 | 211 | return nil 212 | } 213 | -------------------------------------------------------------------------------- /internal/service/menuService/menu.go: -------------------------------------------------------------------------------- 1 | package menuService 2 | 3 | import ( 4 | "context" 5 | "github.com/gogf/gf/v2/frame/g" 6 | "github.com/gogf/gf/v2/util/gconv" 7 | "goframe-starter/api/vmenu" 8 | "goframe-starter/internal/consts" 9 | "goframe-starter/internal/dao" 10 | "goframe-starter/internal/model/entity" 11 | "goframe-starter/utility/xcasbin" 12 | "strings" 13 | ) 14 | 15 | var menuCols = dao.Menu.Columns() 16 | 17 | func AddMenu(ctx context.Context, req *vmenu.AddMenuReq) (res *vmenu.AddMenuRes, err error) { 18 | count, err := dao.Menu.Ctx(ctx).Where(g.Map{ 19 | menuCols.Path: req.Path, 20 | menuCols.Pid: req.Pid, 21 | }).Count() 22 | if err != nil { 23 | return nil, err 24 | } 25 | if count > 0 { 26 | return nil, consts.ErrMenuPathExists 27 | } 28 | _, err = dao.Menu.Ctx(ctx).Data(req).Insert() 29 | if err != nil { 30 | return nil, err 31 | } 32 | return 33 | } 34 | func DeleteMenu(ctx context.Context, req *vmenu.DeleteMenuReq) (res *vmenu.DeleteMenuRes, err error) { 35 | count, err := dao.Menu.Ctx(ctx).Where(menuCols.Pid, req.Id).Count() 36 | if err != nil { 37 | return nil, err 38 | } 39 | if count > 0 { 40 | return nil, consts.ErrMenuPathDeleteChildren 41 | } 42 | count, err = dao.Button.Ctx(ctx).Where(dao.Button.Columns().MenuId, req.Id).Count() 43 | if err != nil { 44 | return nil, err 45 | } 46 | if count > 0 { 47 | return nil, consts.ErrMenuPathDeleteChildren 48 | } 49 | _, err = dao.Menu.Ctx(ctx).Where(menuCols.Id, req.Id).Delete() 50 | if err != nil { 51 | return nil, err 52 | } 53 | // 删除关联的casbin,删除角色与菜单关联 54 | var obj = "menu " + gconv.String(req.Id) 55 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(1, obj) 56 | if err != nil { 57 | return nil, err 58 | } 59 | return 60 | } 61 | func AddMenuForRole(ctx context.Context, req *vmenu.MenuForRoleReq) (res *vmenu.MenuForRoleRes, err error) { 62 | var sub = consts.Role_Menu_Prefix + gconv.String(req.RoleId) 63 | _, err = xcasbin.Enforcer.RemoveFilteredPolicy(0, sub) 64 | if err != nil { 65 | return nil, err 66 | } 67 | for _, menuId := range req.MenuIds { 68 | var obj = "menu " + gconv.String(menuId) 69 | _, err := xcasbin.Enforcer.AddPolicy(sub, gconv.String(obj), "ALL") 70 | if err != nil { 71 | return nil, err 72 | } 73 | } 74 | return 75 | } 76 | func getRoleMenuIds(roleId uint) []int { 77 | var sub = consts.Role_Menu_Prefix + gconv.String(roleId) 78 | var rules = xcasbin.Enforcer.GetFilteredPolicy(0, sub) 79 | var res = make([]int, 0) 80 | for _, rule := range rules { 81 | parts := strings.Split(rule[1], " ") 82 | res = append(res, gconv.Int(parts[1])) 83 | } 84 | return res 85 | } 86 | func GetMenuByRole(ctx context.Context, req *vmenu.MenuByRoleReq) (res *vmenu.MenuByRoleRes, err error) { 87 | var resp = &vmenu.MenuByRoleRes{ 88 | List: make([]int, 0), 89 | } 90 | var ids = getRoleMenuIds(req.RoleId) 91 | for _, id := range ids { 92 | resp.List = append(resp.List, id) 93 | } 94 | return resp, nil 95 | } 96 | func UpdateMenu(ctx context.Context, req *vmenu.UpdateMenuReq) (res *vmenu.UpdateMenuRes, err error) { 97 | _, err = dao.Menu.Ctx(ctx).Where(menuCols.Id, req.Id).Data(g.Map{ 98 | menuCols.Pid: req.Pid, 99 | menuCols.Title: req.Title, 100 | menuCols.Name: req.Name, 101 | menuCols.Path: req.Path, 102 | menuCols.Icon: req.Icon, 103 | menuCols.Type: req.Type, 104 | menuCols.Redirect: req.Redirect, 105 | menuCols.Permissions: req.Permissions, 106 | menuCols.PermissionName: req.PermissionName, 107 | menuCols.Component: req.Component, 108 | menuCols.AlwaysShow: req.AlwaysShow, 109 | menuCols.ActiveMenu: req.ActiveMenu, 110 | menuCols.IsRoot: req.IsRoot, 111 | menuCols.IsFrame: req.IsFrame, 112 | menuCols.FrameSrc: req.FrameSrc, 113 | menuCols.KeepAlive: req.KeepAlive, 114 | menuCols.Hidden: req.Hidden, 115 | menuCols.Affix: req.Affix, 116 | menuCols.Level: req.Level, 117 | menuCols.Tree: req.Tree, 118 | menuCols.Sort: req.Sort, 119 | menuCols.Status: req.Status, 120 | }).Update() 121 | if err != nil { 122 | return nil, err 123 | } 124 | return 125 | } 126 | 127 | // getAllMenus 从数据库获取所有菜单,再把菜单生成树形结构 128 | func getAllMenus(ctx context.Context) (res []*entity.Menu, err error) { 129 | res = make([]*entity.Menu, 0) 130 | // 超级管理员返回所有菜单,其他角色按权限设置的来 131 | var roleId = gconv.Uint(ctx.Value("roleId")) 132 | if roleId == 1024 { // 1024为超级管理员 133 | err = dao.Menu.Ctx(ctx).OrderAsc(menuCols.Sort).Scan(&res) 134 | } else { 135 | err = dao.Menu.Ctx(ctx).WhereIn(menuCols.Id, getRoleMenuIds(roleId)).OrderAsc(menuCols.Sort).Scan(&res) 136 | } 137 | if err != nil { 138 | return nil, err 139 | } 140 | return 141 | } 142 | 143 | /*树形tree开始*/ 144 | func genTreeMenus(ctx context.Context) (res []*vmenu.TreeMenuItem, err error) { 145 | allMenus, err := getAllMenus(ctx) 146 | if err != nil { 147 | return nil, err 148 | } 149 | // 根级为0 150 | res = buildTreeMenus(allMenus, 0) 151 | return 152 | } 153 | 154 | func ListTreeMenus(ctx context.Context, req *vmenu.ListTreeMenuReq) (res *vmenu.ListTreeMenuRes, err error) { 155 | res = &vmenu.ListTreeMenuRes{} 156 | res.List = make([]*vmenu.TreeMenuItem, 0) 157 | menus, err := genTreeMenus(ctx) 158 | if err != nil { 159 | return nil, err 160 | } 161 | res.List = append(res.List, menus...) 162 | return 163 | } 164 | 165 | func buildTreeMenus(menus []*entity.Menu, pid int64) (res []*vmenu.TreeMenuItem) { 166 | for _, menu := range menus { 167 | if menu.Pid == pid { 168 | var treeMenuItem = &vmenu.TreeMenuItem{ 169 | Menu: menu, 170 | } 171 | treeMenuItem.Children = buildTreeMenus(menus, menu.Id) 172 | res = append(res, treeMenuItem) 173 | } 174 | } 175 | return res 176 | } 177 | 178 | /*树形tree结束*/ 179 | 180 | /*vueRouter开始*/ 181 | func genVueMenus(menus []*vmenu.TreeMenuItem) (sources []*vmenu.VueMenu) { 182 | for _, men := range menus { 183 | var source = new(vmenu.VueMenu) 184 | source.Name = men.Name 185 | source.Path = men.Path 186 | source.Redirect = men.Redirect 187 | source.Component = men.Component 188 | source.Meta = &vmenu.VueMenuMeta{ 189 | Title: men.Title, 190 | Icon: men.Icon, 191 | OrderNo: men.Sort, 192 | Hidden: men.Hidden == 1, 193 | HiddenBreadcrumb: men.AlwaysShow == 1, 194 | KeepAlive: men.KeepAlive == 1, 195 | FrameSrc: men.FrameSrc, 196 | IsFrame: men.IsFrame == 1, 197 | Affix: men.Affix == 1, 198 | /* 199 | ActiveMenu: men.ActiveMenu, 200 | IsRoot: men.IsRoot == 1, 201 | //Permissions: men.Permissions, 202 | Type: men.Type,*/ 203 | } 204 | if len(men.Children) > 0 { 205 | source.Children = append(source.Children, genVueMenus(men.Children)...) 206 | } 207 | sources = append(sources, source) 208 | } 209 | return 210 | } 211 | 212 | func ListVueMenus(ctx context.Context, req *vmenu.VueMenuReq) (res *vmenu.VueMenuRes, err error) { 213 | res = &vmenu.VueMenuRes{} 214 | res.List = make([]*vmenu.VueMenu, 0) 215 | treeMenus, err := genTreeMenus(ctx) // type 3 为按钮,不计入 216 | if err != nil { 217 | return nil, err 218 | } 219 | vueMenus := genVueMenus(treeMenus) 220 | 221 | res.List = append(res.List, vueMenus...) 222 | return 223 | } 224 | 225 | /*vueRouter结束*/ 226 | -------------------------------------------------------------------------------- /internal/service/noticeService/notice.go: -------------------------------------------------------------------------------- 1 | package noticeService 2 | 3 | import ( 4 | "context" 5 | "encoding/json" 6 | "github.com/gogf/gf/v2/database/gdb" 7 | "github.com/gogf/gf/v2/frame/g" 8 | "github.com/gogf/gf/v2/util/gconv" 9 | "goframe-starter/api/vcommon" 10 | "goframe-starter/api/vnotice" 11 | "goframe-starter/internal/consts" 12 | "goframe-starter/internal/dao" 13 | "goframe-starter/internal/model/do" 14 | "goframe-starter/internal/model/entity" 15 | "sync" 16 | ) 17 | 18 | var noticeCols = dao.Notice.Columns() 19 | 20 | func AddNotice(ctx context.Context, req *vnotice.AddNoticeReq) (res *vnotice.AddNoticeRes, err error) { 21 | g.DumpWithType(req.Receivers) 22 | if req.Receivers == "" { 23 | return nil, consts.ErrNoticeReceivers 24 | } 25 | if req.Content == "" { 26 | return nil, consts.ErrNoticeContent 27 | } 28 | var data = g.Map{} 29 | data[noticeCols.Creater] = ctx.Value("username") 30 | data[noticeCols.Receivers] = req.Receivers 31 | data[noticeCols.Content] = req.Content 32 | if req.Title != "" { 33 | data[noticeCols.Title] = req.Title 34 | } 35 | if req.Tag != "" { 36 | data[noticeCols.Tag] = req.Tag 37 | } 38 | if req.Sort != 0 { 39 | data[noticeCols.Sort] = req.Sort 40 | } 41 | if req.Remark != "" { 42 | data[noticeCols.Remark] = req.Remark 43 | } 44 | err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error { 45 | noticeId, err := dao.Notice.Ctx(ctx).TX(tx).Data(data).InsertAndGetId() 46 | if err != nil { 47 | return err 48 | } 49 | var receivers []uint 50 | err = json.Unmarshal([]byte(req.Receivers), &receivers) 51 | if err != nil { 52 | return err 53 | } 54 | // 插入notice_relation表 用事务 55 | var wg sync.WaitGroup 56 | var errChan = make(chan error) 57 | for _, receiver := range receivers { 58 | wg.Add(1) 59 | go func(receiver uint) { 60 | defer wg.Done() 61 | _, err := dao.NoticeUserRelation.Ctx(ctx).TX(tx).Data(do.NoticeUserRelation{ 62 | NoticeId: noticeId, 63 | Uid: receiver, 64 | }).Insert() 65 | if err != nil { 66 | errChan <- err 67 | } 68 | }(receiver) 69 | } 70 | go func() { 71 | wg.Wait() 72 | close(errChan) 73 | }() 74 | for ec := range errChan { 75 | //todo 可以考虑将发送失败的用户放到定时任务里,直到发送成功 76 | g.Log().Error(ctx, "发送通告失败", ec) 77 | //return ec 78 | } 79 | return nil 80 | }) 81 | if err != nil { 82 | return nil, err 83 | } 84 | 85 | return 86 | } 87 | 88 | func UpdateNotice(ctx context.Context, req *vnotice.UpdateNoticeReq) (res *vnotice.UpdateNoticeRes, err error) { 89 | var data = g.Map{} 90 | if req.Receivers != "" { 91 | data[noticeCols.Receivers] = req.Receivers 92 | } 93 | if req.Title != "" { 94 | data[noticeCols.Title] = req.Title 95 | } 96 | if req.Content != "" { 97 | data[noticeCols.Content] = req.Content 98 | } 99 | if req.Tag != "" { 100 | data[noticeCols.Tag] = req.Tag 101 | } 102 | if req.Sort != 0 { 103 | data[noticeCols.Sort] = req.Sort 104 | } 105 | if req.Remark != "" { 106 | data[noticeCols.Remark] = req.Remark 107 | } 108 | _, err = dao.Notice.Ctx(ctx).Where(noticeCols.Id, req.Id).Data(data).Update() 109 | if err != nil { 110 | return nil, err 111 | } 112 | return 113 | } 114 | 115 | func DeleteNotice(ctx context.Context, req *vnotice.DeleteNoticeReq) (res *vnotice.DeleteNoticeRes, err error) { 116 | _, err = dao.Notice.Ctx(ctx).WherePri(req.Id).Delete() 117 | if err != nil { 118 | return nil, err 119 | } 120 | return 121 | } 122 | 123 | func ListNoticeForSender(ctx context.Context, req *vnotice.ListNoticeReq) (res *vnotice.ListNoticeRes, err error) { 124 | var resp = &vnotice.ListNoticeRes{ 125 | List: make([]*entity.Notice, 0), 126 | CommonPageRes: &vcommon.CommonPageRes{}, 127 | } 128 | var data = g.Map{} 129 | var roleId = gconv.Int(ctx.Value("roleId")) 130 | if roleId == consts.Role_Root_Code { 131 | // 超级管理员可以看所有的公告,非超管只能看自己创建的公告 132 | } else { 133 | data[noticeCols.Creater] = ctx.Value("username") 134 | } 135 | if req.Title != "" { 136 | data[noticeCols.Title+" like ?"] = "%" + req.Title + "%" 137 | } 138 | if req.Content != "" { 139 | data[noticeCols.Content+" like ?"] = "%" + req.Content + "%" 140 | } 141 | if req.Tag != "" { 142 | data[noticeCols.Tag+" like ?"] = "%" + req.Tag + "%" 143 | } 144 | if req.Creater != "" { 145 | data[noticeCols.Creater+" like ?"] = "%" + req.Creater + "%" 146 | } 147 | if req.Id != 0 { 148 | data[noticeCols.Id] = req.Id 149 | } 150 | 151 | var model = dao.Notice.Ctx(ctx).Where(data).OrderAsc(noticeCols.Sort).OrderDesc(noticeCols.CreatedAt) 152 | if req.PageSize != 0 { 153 | resp.PageIndex = req.PageIndex 154 | resp.PageSize = req.PageSize 155 | model = model.Page(req.PageIndex, req.PageSize) 156 | } 157 | err = model.ScanAndCount(&resp.List, &resp.Total, false) 158 | if err != nil { 159 | return nil, err 160 | } 161 | return resp, nil 162 | } 163 | 164 | func OneNotice(ctx context.Context, req *vnotice.OneNoticeReq) (res *vnotice.OneNoticeRes, err error) { 165 | err = dao.Notice.Ctx(ctx).Where(noticeCols.Id, req.Id).Scan(&res) 166 | if err != nil { 167 | return nil, err 168 | } 169 | return 170 | } 171 | 172 | // 接收端 173 | var noticeForReceiverCols = dao.NoticeUserRelation.Columns() 174 | 175 | func ListNoticeForReceiver(ctx context.Context, req *vnotice.ListNoticeForReceiverReq) (res *vnotice.ListNoticeForReceiverRes, err error) { 176 | // 在添加公告的时候在公告与个人的关联表写入数据,查询的时候join这个表 177 | var resp = &vnotice.ListNoticeForReceiverRes{ 178 | List: make([]*vnotice.ItemNoticeForReceiver, 0), 179 | CommonPageRes: &vcommon.CommonPageRes{}, 180 | } 181 | var uid = ctx.Value("uid") 182 | var model = g.Model(dao.NoticeUserRelation.Table(), "a").InnerJoin(dao.Notice.Table(), "b", "a.notice_id=b.id").Fields("a.*,b.remark,b.title,b.tag,b.content,b.sort").Where( 183 | "a.uid", uid) 184 | if req.Title != "" { 185 | model = model.WhereLike("b.title", req.Title) 186 | } 187 | if req.Content != "" { 188 | model = model.WhereLike("b.content", req.Content) 189 | } 190 | if req.Tag != "" { 191 | model = model.WhereLike("b.tag", req.Tag) 192 | } 193 | if req.Status != 0 { 194 | model = model.Where("a.status", req.Status) 195 | } 196 | 197 | model = model.OrderAsc("b.sort").OrderDesc("b.created_at").OrderAsc("a.status") 198 | if req.PageSize != 0 { 199 | resp.PageIndex = req.PageIndex 200 | resp.PageSize = req.PageSize 201 | model = model.Page(req.PageIndex, req.PageSize) 202 | } 203 | err = model.ScanAndCount(&resp.List, &resp.Total, false) 204 | if err != nil { 205 | return nil, err 206 | } 207 | return resp, nil 208 | } 209 | 210 | func DeleteNoticeForReceiver(ctx context.Context, req *vnotice.DeleteNoticeForReceiverReq) (res *vnotice.DeleteNoticeForReceiverRes, err error) { 211 | _, err = dao.NoticeUserRelation.Ctx(ctx).Where(noticeForReceiverCols.Id, req.Id).Delete() 212 | if err != nil { 213 | return nil, err 214 | } 215 | return 216 | } 217 | 218 | func UpdateNoticeStatusForReceiver(ctx context.Context, req *vnotice.UpdateNoticeForReceiverReq) (res *vnotice.UpdateNoticeForReceiverRes, err error) { 219 | _, err = dao.NoticeUserRelation.Ctx(ctx).Where(noticeForReceiverCols.Id, req.Id).Data(g.Map{ 220 | noticeForReceiverCols.Status: req.Status, 221 | }).Update() 222 | if err != nil { 223 | return nil, err 224 | } 225 | return 226 | } 227 | 228 | func GetNoticeUnreadCountForReceiver(ctx context.Context, req *vnotice.GetNoticeUnreadCountForReceiverReq) (res *vnotice.GetNoticeUnreadCountForReceiverRes, err error) { 229 | res = &vnotice.GetNoticeUnreadCountForReceiverRes{ 230 | Count: 0, 231 | } 232 | count, err := dao.NoticeUserRelation.Ctx(ctx).Where(noticeForReceiverCols.Uid, ctx.Value("uid")).Count(noticeForReceiverCols.Status, 1) 233 | if err != nil { 234 | return nil, err 235 | } 236 | res.Count = count 237 | return 238 | } 239 | --------------------------------------------------------------------------------