├── .dockerignore ├── config ├── db-end-mysql.sql ├── db-begin-mysql.sql ├── settings.demo.yml ├── extend.go ├── pg.sql └── settings.sqlite.yml ├── static ├── image │ ├── img.png │ ├── login.png │ ├── order.png │ ├── task.png │ ├── customflow.png │ ├── orderApply.png │ ├── statistics.png │ ├── tasktype.png │ ├── ordermanage.png │ ├── customtemplate.png │ └── orderApply-v2.png └── form-generator │ ├── css │ └── parser-example.69e16e51.css │ ├── img │ └── logo.e1bc3747.png │ ├── js │ └── tinymce-example.641995ab.js │ └── preview.html ├── common ├── actions │ ├── type.go │ ├── create.go │ ├── index.go │ ├── update.go │ ├── delete.go │ └── view.go ├── global │ ├── topic.go │ ├── adm.go │ ├── logo.go │ ├── casbin.go │ └── pagingquery.go ├── middleware │ ├── handler │ │ ├── ping.go │ │ ├── httpshandler.go │ │ ├── role.go │ │ ├── login.go │ │ └── user.go │ ├── db.go │ ├── trace.go │ ├── sentinel.go │ ├── request_id.go │ ├── init.go │ ├── demo.go │ ├── auth.go │ ├── customerror.go │ ├── header.go │ ├── permission.go │ └── settings.go ├── models │ ├── menu.go │ ├── type.go │ ├── migrate.go │ ├── response.go │ └── user.go ├── dto │ ├── order.go │ ├── pagination.go │ ├── type.go │ └── search.go ├── file_store │ ├── obs_test.go │ ├── oss_test.go │ ├── kodo_test.go │ ├── interface.go │ ├── initialize.go │ ├── oss.go │ └── obs.go ├── database │ ├── open.go │ ├── open_sqlite3.go │ └── initialize.go ├── service │ └── service.go ├── ip.go ├── storage │ └── initialize.go └── utils │ ├── encrypt.go │ ├── tasklog.go │ └── machinehealth.go ├── app ├── smart │ ├── service │ │ ├── .DS_Store │ │ └── dto │ │ │ ├── user_favorite.go │ │ │ ├── order_rating.go │ │ │ ├── order_comment.go │ │ │ ├── order_category.go │ │ │ └── order_statistics.go │ ├── models │ │ ├── order_rating.go │ │ ├── user_favorite.go │ │ ├── order_comment.go │ │ ├── order_category.go │ │ ├── order_items.go │ │ ├── flow_templates.go │ │ ├── exec_machine.go │ │ └── flow_manage.go │ └── router │ │ ├── user_favorite.go │ │ ├── flow_templates.go │ │ ├── order_category.go │ │ ├── order_items.go │ │ ├── init_router.go │ │ ├── flow_manage.go │ │ ├── order_statistics.go │ │ ├── order_comment.go │ │ ├── order_rating.go │ │ ├── exec_machine.go │ │ ├── router.go │ │ ├── order_task.go │ │ └── order_works.go ├── system │ ├── service │ │ ├── dto │ │ │ ├── sys_notify.go │ │ │ └── sys_login_log.go │ │ ├── sys_login_log.go │ │ └── sys_opera_log.go │ ├── models │ │ ├── model.go │ │ ├── casbin_rule.go │ │ ├── sys_dict_type.go │ │ ├── sys_config.go │ │ ├── sys_post.go │ │ ├── sys_dept.go │ │ ├── sys_dict_data.go │ │ ├── initdb.go │ │ ├── sys_role.go │ │ ├── sys_menu.go │ │ └── sys_login_log.go │ ├── router │ │ ├── sys_notify.go │ │ ├── sys_opera_log.go │ │ ├── sys_login_log.go │ │ ├── sys_api.go │ │ ├── sys_post.go │ │ ├── sys_dept.go │ │ ├── sys_menu.go │ │ ├── sys_role.go │ │ ├── init_router.go │ │ ├── router.go │ │ ├── sys_config.go │ │ ├── sys_dict.go │ │ └── sys_user.go │ └── apis │ │ ├── sys_notify.go │ │ ├── go_admin.go │ │ └── captcha.go ├── other │ ├── service │ │ └── dto │ │ │ └── sys_tables.go │ ├── router │ │ ├── file.go │ │ ├── monitor.go │ │ ├── sys_server_monitor.go │ │ ├── init_router.go │ │ ├── router.go │ │ └── gen_router.go │ ├── apis │ │ └── tools │ │ │ ├── db_columns.go │ │ │ └── db_tables.go │ └── models │ │ └── tools │ │ └── db_tables.go └── jobs │ ├── type.go │ ├── router │ ├── int_router.go │ ├── router.go │ └── sys_job.go │ ├── examples.go │ ├── apis │ └── sys_job.go │ └── models │ └── sys_job.go ├── scripts ├── swag.sh ├── k8s │ └── install.sh └── migrate.sh ├── cmd ├── migrate │ └── migration │ │ ├── version-local │ │ └── doc.go │ │ ├── models │ │ ├── model.go │ │ ├── role_dept.go │ │ ├── tb_demo.go │ │ ├── sys_dict_type.go │ │ ├── order │ │ │ ├── user_favorite.go │ │ │ ├── order_rating.go │ │ │ ├── order_comment.go │ │ │ ├── order_category.go │ │ │ ├── flow_templates.go │ │ │ ├── order_items.go │ │ │ ├── flow_manage.go │ │ │ ├── order_works.go │ │ │ ├── exec_machine.go │ │ │ └── common.go │ │ ├── sys_api.go │ │ ├── sys_post.go │ │ ├── by.go │ │ ├── casbin_rule.go │ │ ├── sys_config.go │ │ ├── sys_dept.go │ │ ├── sys_role.go │ │ ├── sys_job.go │ │ ├── sys_dict_data.go │ │ ├── sys_login_log.go │ │ ├── sys_menu.go │ │ ├── sys_user.go │ │ ├── sys_opera_log.go │ │ ├── initdb.go │ │ └── sys_tables.go │ │ ├── version │ │ ├── 1653638869132_migrate.go │ │ ├── 1599190683659_tables.go │ │ └── 1730013300607_migrate.go │ │ └── init.go ├── api │ ├── jobs.go │ ├── other.go │ └── smart.go └── cobra.go ├── template ├── cmd_api.template ├── v4 │ ├── no_actions │ │ ├── router_no_check_role.go.template │ │ └── router_check_role.go.template │ ├── actions │ │ ├── router_no_check_role.go.template │ │ └── router_check_role.go.template │ ├── js.go.template │ └── model.go.template ├── migrate.template └── router.template ├── .gitignore ├── .github └── workflows │ ├── go.yml │ └── build.yml ├── main.go ├── LICENSE.md ├── test └── gen_test.go └── Makefile /.dockerignore: -------------------------------------------------------------------------------- 1 | config/settings.yml 2 | -------------------------------------------------------------------------------- /config/db-end-mysql.sql: -------------------------------------------------------------------------------- 1 | SET FOREIGN_KEY_CHECKS = 1; -------------------------------------------------------------------------------- /config/db-begin-mysql.sql: -------------------------------------------------------------------------------- 1 | SET NAMES utf8mb4; 2 | SET FOREIGN_KEY_CHECKS = 0; -------------------------------------------------------------------------------- /static/image/img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/img.png -------------------------------------------------------------------------------- /static/image/login.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/login.png -------------------------------------------------------------------------------- /static/image/order.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/order.png -------------------------------------------------------------------------------- /static/image/task.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/task.png -------------------------------------------------------------------------------- /common/actions/type.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | const ( 4 | PermissionKey = "dataPermission" 5 | ) 6 | -------------------------------------------------------------------------------- /app/smart/service/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/app/smart/service/.DS_Store -------------------------------------------------------------------------------- /static/image/customflow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/customflow.png -------------------------------------------------------------------------------- /static/image/orderApply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/orderApply.png -------------------------------------------------------------------------------- /static/image/statistics.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/statistics.png -------------------------------------------------------------------------------- /static/image/tasktype.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/tasktype.png -------------------------------------------------------------------------------- /static/image/ordermanage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/ordermanage.png -------------------------------------------------------------------------------- /static/image/customtemplate.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/customtemplate.png -------------------------------------------------------------------------------- /static/image/orderApply-v2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/image/orderApply-v2.png -------------------------------------------------------------------------------- /static/form-generator/css/parser-example.69e16e51.css: -------------------------------------------------------------------------------- 1 | .test-form[data-v-77b1aafa]{margin:15px auto;width:800px;padding:15px} -------------------------------------------------------------------------------- /static/form-generator/img/logo.e1bc3747.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sunwenbo/smart-api/HEAD/static/form-generator/img/logo.e1bc3747.png -------------------------------------------------------------------------------- /scripts/swag.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | swag i -g init_router.go -dir app/smart-api/router --instanceName admin --parseDependency -o docs/smart-api 4 | -------------------------------------------------------------------------------- /cmd/migrate/migration/version-local/doc.go: -------------------------------------------------------------------------------- 1 | package version_local 2 | 3 | func init() { 4 | } 5 | 6 | /** 7 | 开发者项目的迁移脚本放在这个目录里,init写法参考version目录里的migrate或者自动生成 8 | */ 9 | -------------------------------------------------------------------------------- /common/global/topic.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | const ( 4 | LoginLog = "login_log_queue" 5 | OperateLog = "operate_log_queue" 6 | ApiCheck = "api_check_queue" 7 | ) 8 | -------------------------------------------------------------------------------- /common/global/adm.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | const ( 4 | // Version go-admin version info 5 | Version = "1.1.1" 6 | ) 7 | 8 | var ( 9 | // Driver 数据库驱动 10 | Driver string 11 | ) 12 | -------------------------------------------------------------------------------- /cmd/api/jobs.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "smart-api/app/jobs/router" 4 | 5 | func init() { 6 | //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 7 | AppRouters = append(AppRouters, router.InitRouter) 8 | } 9 | -------------------------------------------------------------------------------- /cmd/api/other.go: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "smart-api/app/other/router" 4 | 5 | func init() { 6 | //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 7 | AppRouters = append(AppRouters, router.InitRouter) 8 | } 9 | -------------------------------------------------------------------------------- /common/middleware/handler/ping.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | func Ping(c *gin.Context) { 8 | c.JSON(200, gin.H{ 9 | "message": "ok", 10 | }) 11 | } 12 | -------------------------------------------------------------------------------- /template/cmd_api.template: -------------------------------------------------------------------------------- 1 | package api 2 | 3 | import "smart-api/app/{{.appName}}/router" 4 | 5 | func init() { 6 | //注册路由 fixme 其他应用的路由,在本目录新建文件放在init方法 7 | AppRouters = append(AppRouters, router.InitRouter) 8 | } 9 | -------------------------------------------------------------------------------- /common/global/logo.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import "github.com/common-nighthawk/go-figure" 4 | 5 | func SmartLogo() string { 6 | myFigure := figure.NewFigure("Hello, SMART", "", true) 7 | return myFigure.String() 8 | } 9 | -------------------------------------------------------------------------------- /app/system/service/dto/sys_notify.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type SysNotify struct { 4 | OrderName string `json:"orderName" binding:"required"` // 工单名称 5 | ReceiveName string `json:"receiveName" binding:"required"` // 接收者名称 6 | } 7 | -------------------------------------------------------------------------------- /common/models/menu.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // Menu 菜单中的类型枚举值 4 | const ( 5 | // Directory 目录 6 | Directory string = "M" 7 | // Menu 菜单 8 | Menu string = "C" 9 | // Button 按钮 10 | Button string = "F" 11 | ) 12 | -------------------------------------------------------------------------------- /app/system/models/model.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type BaseModel struct { 8 | CreatedAt time.Time `json:"createdAt"` 9 | UpdatedAt time.Time `json:"updatedAt"` 10 | DeletedAt *time.Time `json:"deletedAt"` 11 | } 12 | -------------------------------------------------------------------------------- /common/models/type.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "gorm.io/gorm/schema" 4 | 5 | type ActiveRecord interface { 6 | schema.Tabler 7 | SetCreateBy(createBy int) 8 | SetUpdateBy(updateBy int) 9 | Generate() ActiveRecord 10 | GetId() interface{} 11 | } 12 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/model.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type BaseModel struct { 8 | CreatedAt time.Time `json:"createdAt"` 9 | UpdatedAt time.Time `json:"updatedAt"` 10 | DeletedAt *time.Time `json:"deletedAt"` 11 | } 12 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/role_dept.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysRoleDept struct { 4 | RoleId int `gorm:"size:11;primaryKey"` 5 | DeptId int `gorm:"size:11;primaryKey"` 6 | } 7 | 8 | func (SysRoleDept) TableName() string { 9 | return "sys_role_dept" 10 | } 11 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/tb_demo.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type TbDemo struct { 4 | Model 5 | Name string `json:"name" gorm:"type:varchar(128);comment:名称"` 6 | ModelTime 7 | ControlBy 8 | } 9 | 10 | func (TbDemo) TableName() string { 11 | return "tb_demo" 12 | } 13 | -------------------------------------------------------------------------------- /common/models/migrate.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "time" 4 | 5 | type Migration struct { 6 | Version string `gorm:"primaryKey"` 7 | ApplyTime time.Time `gorm:"autoCreateTime"` 8 | } 9 | 10 | func (Migration) TableName() string { 11 | return "sys_migration" 12 | } 13 | -------------------------------------------------------------------------------- /common/middleware/db.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk" 6 | ) 7 | 8 | func WithContextDb(c *gin.Context) { 9 | c.Set("db", sdk.Runtime.GetDbByKey(c.Request.Host).WithContext(c)) 10 | c.Next() 11 | } 12 | -------------------------------------------------------------------------------- /app/other/service/dto/sys_tables.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type SysTableSearch struct { 4 | TBName string `form:"tableName" search:"type:exact;column:table_name;table:table_name"` 5 | TableComment string `form:"tableComment" search:"type:icontains;column:table_comment;table:table_comment"` 6 | } 7 | -------------------------------------------------------------------------------- /common/dto/order.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "gorm.io/gorm/clause" 6 | ) 7 | 8 | func OrderDest(sort string, bl bool) func(db *gorm.DB) *gorm.DB { 9 | return func(db *gorm.DB) *gorm.DB { 10 | return db.Order(clause.OrderByColumn{Column: clause.Column{Name: sort}, Desc: bl}) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /common/file_store/obs_test.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOBSUpload(t *testing.T) { 8 | e := OXS{"", "", "", ""} 9 | var oxs = e.Setup(HuaweiOBS) 10 | err := oxs.UpLoad("test.png", "./test.png") 11 | if err != nil { 12 | t.Error(err) 13 | } 14 | t.Log("ok") 15 | } 16 | -------------------------------------------------------------------------------- /app/jobs/type.go: -------------------------------------------------------------------------------- 1 | package jobs 2 | 3 | import "github.com/robfig/cron/v3" 4 | 5 | type Job interface { 6 | Run() 7 | addJob(*cron.Cron) (int, error) 8 | } 9 | 10 | type JobExec interface { 11 | Exec(arg interface{}) error 12 | } 13 | 14 | func CallExec(e JobExec, arg interface{}) error { 15 | return e.Exec(arg) 16 | } 17 | -------------------------------------------------------------------------------- /common/file_store/oss_test.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestOSSUpload(t *testing.T) { 8 | // 打括号内填写自己的测试信息即可 9 | e := OXS{} 10 | var oxs = e.Setup(AliYunOSS) 11 | err := oxs.UpLoad("test.png", "./test.png") 12 | if err != nil { 13 | t.Error(err) 14 | } 15 | t.Log("ok") 16 | } 17 | -------------------------------------------------------------------------------- /scripts/k8s/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 创建k8s sre 命名空间 3 | kubectl create ns sre 4 | 5 | # 拷贝配置文件 6 | cp ../../config/settings.full.yml settings.yml 7 | 8 | # 创建secret 9 | kubectl create secret generic smart-settings \ 10 | --from-file=settings.yml=./settings.yml \ 11 | -n sre 12 | 13 | # 部署服务,并挂载secret 14 | kubectl apply -f scripts/smart-api-deploy.yaml 15 | -------------------------------------------------------------------------------- /cmd/api/smart.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package api 4 | 5 | import ( 6 | "fmt" 7 | "smart-api/app/smart/router" 8 | ) 9 | 10 | func init() { 11 | fmt.Println("注册Smart api路由...") 12 | //注册Smart路由 fixme 其他应用的路由,自定义注册路由 13 | // AppRouters 在system.go 中定义,将自定义的路由追加到AppRouters切片实现路由注册 14 | AppRouters = append(AppRouters, router.InitRouter) 15 | } 16 | -------------------------------------------------------------------------------- /common/database/open.go: -------------------------------------------------------------------------------- 1 | //go:build !sqlite3 2 | 3 | package database 4 | 5 | import ( 6 | "gorm.io/driver/mysql" 7 | "gorm.io/driver/postgres" 8 | "gorm.io/driver/sqlserver" 9 | "gorm.io/gorm" 10 | ) 11 | 12 | var opens = map[string]func(string) gorm.Dialector{ 13 | "mysql": mysql.Open, 14 | "postgres": postgres.Open, 15 | "sqlserver": sqlserver.Open, 16 | } 17 | -------------------------------------------------------------------------------- /common/dto/pagination.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | type Pagination struct { 4 | PageIndex int `form:"pageIndex"` 5 | PageSize int `form:"pageSize"` 6 | } 7 | 8 | func (m *Pagination) GetPageIndex() int { 9 | if m.PageIndex <= 0 { 10 | m.PageIndex = 1 11 | } 12 | return m.PageIndex 13 | } 14 | 15 | func (m *Pagination) GetPageSize() int { 16 | if m.PageSize <= 0 { 17 | m.PageSize = 100 18 | } 19 | return m.PageSize 20 | } 21 | -------------------------------------------------------------------------------- /common/database/open_sqlite3.go: -------------------------------------------------------------------------------- 1 | //go:build sqlite3 2 | // +build sqlite3 3 | 4 | package database 5 | 6 | import ( 7 | "gorm.io/driver/mysql" 8 | "gorm.io/driver/postgres" 9 | "gorm.io/driver/sqlite" 10 | "gorm.io/driver/sqlserver" 11 | "gorm.io/gorm" 12 | ) 13 | 14 | var opens = map[string]func(string) gorm.Dialector{ 15 | "mysql": mysql.Open, 16 | "postgres": postgres.Open, 17 | "sqlite3": sqlite.Open, 18 | "sqlserver": sqlserver.Open, 19 | } 20 | -------------------------------------------------------------------------------- /common/dto/type.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "smart-api/common/models" 6 | ) 7 | 8 | type Index interface { 9 | Generate() Index 10 | Bind(ctx *gin.Context) error 11 | GetPageIndex() int 12 | GetPageSize() int 13 | GetNeedSearch() interface{} 14 | } 15 | 16 | type Control interface { 17 | Generate() Control 18 | Bind(ctx *gin.Context) error 19 | GenerateM() (models.ActiveRecord, error) 20 | GetId() interface{} 21 | } 22 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | .vscode 3 | config/settings.yml 4 | config/settings.dev.yml 5 | config/settings.dev.*.yml 6 | config/settings.dev.*.yml.log 7 | */.DS_Store 8 | static/uploadfile 9 | main.exe 10 | *.exe 11 | smart-api 12 | smart-api.exe 13 | temp/ 14 | logs/ 15 | 16 | 17 | !temp 18 | vendor 19 | 20 | temp/logs 21 | config/settings.dev.yml.log 22 | config/settings.b.dev.yml 23 | cmd/migrate/migration/version-local/* 24 | !cmd/migrate/migration/version-local/doc.go 25 | 26 | # go sum 27 | #go.sum 28 | -------------------------------------------------------------------------------- /common/service/service.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/go-admin-team/go-admin-core/logger" 7 | "gorm.io/gorm" 8 | ) 9 | 10 | type Service struct { 11 | Orm *gorm.DB 12 | Msg string 13 | MsgID string 14 | Log *logger.Helper 15 | Error error 16 | } 17 | 18 | func (db *Service) AddError(err error) error { 19 | if db.Error == nil { 20 | db.Error = err 21 | } else if err != nil { 22 | db.Error = fmt.Errorf("%v; %w", db.Error, err) 23 | } 24 | return db.Error 25 | } 26 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_dict_type.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type DictType struct { 4 | DictId int `gorm:"primaryKey;autoIncrement;" json:"dictId"` 5 | DictName string `gorm:"size:128;" json:"dictName"` //字典名称 6 | DictType string `gorm:"size:128;" json:"dictType"` //字典类型 7 | Status int `gorm:"size:4;" json:"status"` //状态 8 | Remark string `gorm:"size:255;" json:"remark"` //备注 9 | ControlBy 10 | ModelTime 11 | } 12 | 13 | func (DictType) TableName() string { 14 | return "sys_dict_type" 15 | } 16 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/user_favorite.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/13 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type UserFavorites struct { 10 | ID uint `gorm:"primaryKey" json:"id"` 11 | UserID int `gorm:"column:user_id" json:"userId"` 12 | OrderItemID uint `gorm:"column:order_item_id" json:"orderItemId"` // 确保类型一致 13 | models.ControlBy 14 | models.ModelTime 15 | } 16 | 17 | func (*UserFavorites) TableName() string { 18 | return "user_favorites" 19 | } 20 | -------------------------------------------------------------------------------- /app/other/router/file.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/other/apis" 7 | ) 8 | 9 | func init() { 10 | routerCheckRole = append(routerCheckRole, registerFileRouter) 11 | } 12 | 13 | // 需认证的路由代码 14 | func registerFileRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 15 | var api = apis.File{} 16 | r := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 17 | { 18 | r.POST("/public/uploadFile", api.UploadFile) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /common/middleware/handler/httpshandler.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/unrolled/secure" 6 | 7 | "github.com/go-admin-team/go-admin-core/sdk/config" 8 | ) 9 | 10 | func TlsHandler() gin.HandlerFunc { 11 | return func(c *gin.Context) { 12 | secureMiddleware := secure.New(secure.Options{ 13 | SSLRedirect: true, 14 | SSLHost: config.SslConfig.Domain, 15 | }) 16 | err := secureMiddleware.Process(c.Writer, c.Request) 17 | if err != nil { 18 | return 19 | } 20 | c.Next() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_api.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysApi struct { 4 | Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` 5 | Handle string `json:"handle" gorm:"size:128;comment:handle"` 6 | Title string `json:"title" gorm:"size:128;comment:标题"` 7 | Path string `json:"path" gorm:"size:128;comment:地址"` 8 | Type string `json:"type" gorm:"size:16;comment:接口类型"` 9 | Action string `json:"action" gorm:"size:16;comment:请求类型"` 10 | ModelTime 11 | ControlBy 12 | } 13 | 14 | func (SysApi) TableName() string { 15 | return "sys_api" 16 | } -------------------------------------------------------------------------------- /common/file_store/kodo_test.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "testing" 5 | ) 6 | 7 | func TestKODOUpload(t *testing.T) { 8 | e := OXS{"", "", "", ""} 9 | var oxs = e.Setup(QiNiuKodo, map[string]interface{}{"Zone": "华东"}) 10 | err := oxs.UpLoad("test.png", "./test.png") 11 | if err != nil { 12 | t.Error(err) 13 | } 14 | t.Log("ok") 15 | } 16 | 17 | func TestKODOGetTempToken(t *testing.T) { 18 | e := OXS{"", "", "", ""} 19 | var oxs = e.Setup(QiNiuKodo, map[string]interface{}{"Zone": "华东"}) 20 | token, _ := oxs.GetTempToken() 21 | t.Log(token) 22 | t.Log("ok") 23 | } 24 | -------------------------------------------------------------------------------- /app/other/router/monitor.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/go-admin-team/go-admin-core/tools/transfer" 8 | "github.com/prometheus/client_golang/prometheus/promhttp" 9 | ) 10 | 11 | func init() { 12 | routerNoCheckRole = append(routerNoCheckRole, registerMonitorRouter) 13 | } 14 | 15 | // 不需认证的路由代码 16 | func registerMonitorRouter(v1 *gin.RouterGroup) { 17 | v1.GET("/metrics", transfer.Handler(promhttp.Handler())) 18 | //健康检查 19 | v1.GET("/health", func(c *gin.Context) { 20 | c.Status(http.StatusOK) 21 | }) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /common/global/casbin.go: -------------------------------------------------------------------------------- 1 | package global 2 | 3 | import ( 4 | "github.com/casbin/casbin/v2" 5 | "github.com/gin-gonic/gin" 6 | "github.com/go-admin-team/go-admin-core/sdk" 7 | "github.com/go-admin-team/go-admin-core/sdk/api" 8 | ) 9 | 10 | func LoadPolicy(c *gin.Context) (*casbin.SyncedEnforcer, error) { 11 | log := api.GetRequestLogger(c) 12 | if err := sdk.Runtime.GetCasbinKey(c.Request.Host).LoadPolicy(); err == nil { 13 | return sdk.Runtime.GetCasbinKey(c.Request.Host), err 14 | } else { 15 | log.Errorf("casbin rbac_model or policy init error, %s ", err.Error()) 16 | return nil, err 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_post.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysPost struct { 4 | PostId int `gorm:"primaryKey;autoIncrement" json:"postId"` //岗位编号 5 | PostName string `gorm:"size:128;" json:"postName"` //岗位名称 6 | PostCode string `gorm:"size:128;" json:"postCode"` //岗位代码 7 | Sort int `gorm:"size:4;" json:"sort"` //岗位排序 8 | Status int `gorm:"size:4;" json:"status"` //状态 9 | Remark string `gorm:"size:255;" json:"remark"` //描述 10 | ControlBy 11 | ModelTime 12 | } 13 | 14 | func (SysPost) TableName() string { 15 | return "sys_post" 16 | } -------------------------------------------------------------------------------- /app/smart/models/order_rating.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/8/17 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type OrderRating struct { 10 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 11 | OrderID int `gorm:"column:order_id" json:"orderID"` // 与工单ID关联 12 | Ratings int `gorm:"column:rating;type:int" json:"ratings"` // 评分 13 | Taskhandler int `gorm:"column:task_handler;type:int" json:"taskHandler"` // 评分所有人 14 | models.ControlBy 15 | models.ModelTime 16 | } 17 | 18 | func (*OrderRating) TableName() string { 19 | return "order_rating" 20 | } 21 | -------------------------------------------------------------------------------- /app/system/router/sys_notify.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/system/apis" 7 | "smart-api/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysNotifyRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysNotifyRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysNotify{} 17 | 18 | r := v1.Group("/notify").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.POST("", api.NotifySend) 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/by.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "smart-api/common/models" 6 | ) 7 | 8 | type ControlBy struct { 9 | CreateBy int `json:"createBy" gorm:"index;comment:创建者"` 10 | UpdateBy int `json:"updateBy" gorm:"index;comment:更新者"` 11 | } 12 | 13 | type Model struct { 14 | Id int `json:"id" gorm:"primaryKey;autoIncrement;comment:主键编码"` 15 | } 16 | 17 | type ModelTime struct { 18 | CreatedAt models.JSONTime `json:"createdAt" gorm:"comment:创建时间"` 19 | UpdatedAt models.JSONTime `json:"updatedAt" gorm:"comment:最后更新时间"` 20 | DeletedAt gorm.DeletedAt `json:"-" gorm:"index;comment:删除时间"` 21 | } 22 | -------------------------------------------------------------------------------- /app/system/models/casbin_rule.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type CasbinRule struct { 4 | ID uint `gorm:"primaryKey;autoIncrement"` 5 | Ptype string `gorm:"size:512;uniqueIndex:unique_index"` 6 | V0 string `gorm:"size:512;uniqueIndex:unique_index"` 7 | V1 string `gorm:"size:512;uniqueIndex:unique_index"` 8 | V2 string `gorm:"size:512;uniqueIndex:unique_index"` 9 | V3 string `gorm:"size:512;uniqueIndex:unique_index"` 10 | V4 string `gorm:"size:512;uniqueIndex:unique_index"` 11 | V5 string `gorm:"size:512;uniqueIndex:unique_index"` 12 | } 13 | 14 | func (CasbinRule) TableName() string { 15 | return "sys_casbin_rule" 16 | } 17 | -------------------------------------------------------------------------------- /common/ip.go: -------------------------------------------------------------------------------- 1 | package common 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "strings" 6 | ) 7 | 8 | func GetClientIP(c *gin.Context) string { 9 | ClientIP := c.ClientIP() 10 | //fmt.Println("ClientIP:", ClientIP) 11 | RemoteIP := c.RemoteIP() 12 | //fmt.Println("RemoteIP:", RemoteIP) 13 | ip := c.Request.Header.Get("X-Forwarded-For") 14 | if strings.Contains(ip, "127.0.0.1") || ip == "" { 15 | ip = c.Request.Header.Get("X-real-ip") 16 | } 17 | if ip == "" { 18 | ip = "127.0.0.1" 19 | } 20 | if RemoteIP != "127.0.0.1" { 21 | ip = RemoteIP 22 | } 23 | if ClientIP != "127.0.0.1" { 24 | ip = ClientIP 25 | } 26 | return ip 27 | } 28 | -------------------------------------------------------------------------------- /.github/workflows/go.yml: -------------------------------------------------------------------------------- 1 | # This workflow will build a golang project 2 | # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-go 3 | 4 | name: Go 5 | 6 | on: 7 | push: 8 | branches: [ "main" ] 9 | pull_request: 10 | branches: [ "main" ] 11 | 12 | jobs: 13 | 14 | build: 15 | runs-on: ubuntu-latest 16 | steps: 17 | - uses: actions/checkout@v4 18 | 19 | - name: Set up Go 20 | uses: actions/setup-go@v4 21 | with: 22 | go-version: '1.24' 23 | 24 | - name: Build 25 | run: go build -v ./... 26 | 27 | - name: Test 28 | run: go test -v ./... 29 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/order_rating.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/8/17 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type OrderRating struct { 10 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 11 | OrderID int `gorm:"column:order_id" json:"orderID"` // 与工单ID关联 12 | Ratings int `gorm:"column:rating;type:int" json:"ratings"` // 评分 13 | Taskhandler int `gorm:"column:task_handler;type:int" json:"taskHandler"` // 评分所有人 14 | models.ControlBy 15 | models.ModelTime 16 | } 17 | 18 | func (*OrderRating) TableName() string { 19 | return "order_rating" 20 | } 21 | -------------------------------------------------------------------------------- /app/other/router/sys_server_monitor.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/other/apis" 7 | "smart-api/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysServerMonitorRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysServerMonitorRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.ServerMonitor{} 17 | r := v1.Group("/server-monitor").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 18 | { 19 | r.GET("", api.ServerInfo) 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "smart-api/cmd" 5 | ) 6 | 7 | //go:generate swag init --parseDependency --parseDepth=6 --instanceName smart -o ./docs/smart 8 | 9 | // @title smart-api API 10 | // @version 1.0.0 11 | // @description 基于Gin + Vue + Element UI的前后端分离运维工单系统的接口文档 12 | // @description 添加qq群: xxxx 进入技术交流群 请先star,谢谢! 13 | // @license.name MIT 14 | // @contact.email swb956721830@163.com 15 | 16 | // @license.name Apache 2.0 17 | // @license.url https://github.com/sunwenbo/smart-api/blob/master/LICENSE.md 18 | 19 | // @securityDefinitions.apikey Bearer 20 | // @in header 21 | // @name Authorization 22 | 23 | func main() { 24 | cmd.Execute() 25 | } 26 | -------------------------------------------------------------------------------- /static/form-generator/js/tinymce-example.641995ab.js: -------------------------------------------------------------------------------- 1 | (window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["tinymce-example"],{a5aa:function(e,t,n){"use strict";n.r(t);var a=function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",[n("Tinymce",{attrs:{height:300,placeholder:"在这里输入文字"},model:{value:e.defaultValue,callback:function(t){e.defaultValue=t},expression:"defaultValue"}})],1)},c=[],u=n("31c6"),l={components:{Tinymce:u["a"]},props:{},data:function(){return{defaultValue:"

配置文档参阅:http://tinymce.ax-z.cn

"}},computed:{},watch:{},created:function(){},mounted:function(){},methods:{}},o=l,i=n("2877"),p=Object(i["a"])(o,a,c,!1,null,null,null);t["default"]=p.exports}}]); -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/order_comment.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/8/17 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type OrderComment struct { 10 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 11 | OrderID int `gorm:"column:order_id" json:"orderID"` // 与工单ID关联 12 | ParentID *int `gorm:"column:parent_id" json:"parentID"` // 父留言ID,如果为空表示是顶级留言 13 | Comments string `gorm:"column:comment;type:varchar(255)" json:"comments"` // 留言内容 14 | models.ControlBy 15 | models.ModelTime 16 | } 17 | 18 | func (*OrderComment) TableName() string { 19 | return "order_comment" 20 | } 21 | -------------------------------------------------------------------------------- /common/global/pagingquery.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/16 12:05 3 | package global 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | "strconv" 8 | ) 9 | 10 | func PagingQuery(c *gin.Context) (pageNum, limit int) { 11 | // 从请求中获取分页参数 12 | page := c.Query("page") 13 | pageSize := c.Query("pageSize") 14 | 15 | // 默认分页参数,你也可以根据需求自定义默认值 16 | defaultPage := 1 17 | defaultPageSize := 9999 18 | 19 | // 将字符串参数转换为整数,处理可能的错误 20 | pageNum, err := strconv.Atoi(page) 21 | if err != nil || pageNum < 1 { 22 | pageNum = defaultPage 23 | } 24 | limit, err = strconv.Atoi(pageSize) 25 | if err != nil || limit < 1 { 26 | limit = defaultPageSize 27 | } 28 | return 29 | } 30 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/casbin_rule.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | // CasbinRule sys_casbin_rule 4 | type CasbinRule struct { 5 | ID uint `gorm:"primaryKey;autoIncrement"` 6 | Ptype string `gorm:"size:512;uniqueIndex:unique_index"` 7 | V0 string `gorm:"size:512;uniqueIndex:unique_index"` 8 | V1 string `gorm:"size:512;uniqueIndex:unique_index"` 9 | V2 string `gorm:"size:512;uniqueIndex:unique_index"` 10 | V3 string `gorm:"size:512;uniqueIndex:unique_index"` 11 | V4 string `gorm:"size:512;uniqueIndex:unique_index"` 12 | V5 string `gorm:"size:512;uniqueIndex:unique_index"` 13 | } 14 | 15 | func (CasbinRule) TableName() string { 16 | return "sys_casbin_rule" 17 | } 18 | -------------------------------------------------------------------------------- /app/smart/models/user_favorite.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/13 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type UserFavorites struct { 10 | ID uint `gorm:"primaryKey" json:"id"` 11 | UserID int `gorm:"column:user_id" json:"userId"` 12 | OrderItemID uint `gorm:"column:order_item_id" json:"orderItemId"` // 确保类型一致 13 | models.ControlBy 14 | models.ModelTime 15 | } 16 | 17 | func (*UserFavorites) TableName() string { 18 | return "user_favorites" 19 | } 20 | func (e *UserFavorites) Generate() models.ActiveRecord { 21 | o := *e 22 | return &o 23 | } 24 | 25 | func (e *UserFavorites) GetId() interface{} { 26 | return e.ID 27 | } 28 | -------------------------------------------------------------------------------- /app/system/router/sys_opera_log.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/system/apis" 7 | "smart-api/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysOperaLogRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysOperaLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysOperaLog{} 17 | r := v1.Group("/sys-opera-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 18 | { 19 | r.GET("", api.GetPage) 20 | r.GET("/:id", api.Get) 21 | r.DELETE("", api.Delete) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /app/system/router/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/system/apis" 7 | "smart-api/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysLoginLogRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysLoginLogRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysLoginLog{} 17 | 18 | r := v1.Group("/sys-login-log").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.DELETE("", api.Delete) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_config.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysConfig struct { 4 | Model 5 | ConfigName string `json:"configName" gorm:"type:varchar(128);comment:ConfigName"` 6 | ConfigKey string `json:"configKey" gorm:"type:varchar(128);comment:ConfigKey"` 7 | ConfigValue string `json:"configValue" gorm:"type:varchar(255);comment:ConfigValue"` 8 | ConfigType string `json:"configType" gorm:"type:varchar(64);comment:ConfigType"` 9 | IsFrontend int `json:"isFrontend" gorm:"type:varchar(64);comment:是否前台"` 10 | Remark string `json:"remark" gorm:"type:varchar(128);comment:Remark"` 11 | ControlBy 12 | ModelTime 13 | } 14 | 15 | func (SysConfig) TableName() string { 16 | return "sys_config" 17 | } 18 | -------------------------------------------------------------------------------- /common/models/response.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type Response struct { 4 | // 代码 5 | Code int `json:"code" example:"200"` 6 | // 数据集 7 | Data interface{} `json:"data"` 8 | // 消息 9 | Msg string `json:"msg"` 10 | RequestId string `json:"requestId"` 11 | } 12 | 13 | type Page struct { 14 | List interface{} `json:"list"` 15 | Count int `json:"count"` 16 | PageIndex int `json:"pageIndex"` 17 | PageSize int `json:"pageSize"` 18 | } 19 | 20 | // ReturnOK 正常返回 21 | func (res *Response) ReturnOK() *Response { 22 | res.Code = 200 23 | return res 24 | } 25 | 26 | // ReturnError 错误返回 27 | func (res *Response) ReturnError(code int) *Response { 28 | res.Code = code 29 | return res 30 | } 31 | -------------------------------------------------------------------------------- /app/system/router/sys_api.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "smart-api/app/system/apis" 8 | "smart-api/common/middleware" 9 | ) 10 | 11 | func init() { 12 | routerCheckRole = append(routerCheckRole, registerSysApiRouter) 13 | } 14 | 15 | // registerSysApiRouter 16 | func registerSysApiRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 17 | api := apis.SysApi{} 18 | r := v1.Group("/sys-api").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.PUT("/:id", api.Update) 23 | r.DELETE("", api.DeleteSysApi) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/system/router/sys_post.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/system/apis" 7 | "smart-api/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSyPostRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSyPostRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysPost{} 17 | r := v1.Group("/post").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 18 | { 19 | r.GET("", api.GetPage) 20 | r.GET("/:id", api.Get) 21 | r.POST("", api.Insert) 22 | r.PUT("/:id", api.Update) 23 | r.DELETE("", api.Delete) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /common/file_store/interface.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | // DriverType 驱动类型 4 | type DriverType string 5 | 6 | const ( 7 | // HuaweiOBS 华为云OBS 8 | HuaweiOBS DriverType = "HuaweiOBS" 9 | // AliYunOSS 阿里云OSS 10 | AliYunOSS DriverType = "AliYunOSS" 11 | // QiNiuKodo 七牛云kodo 12 | QiNiuKodo DriverType = "QiNiuKodo" 13 | ) 14 | 15 | type ClientOption map[string]interface{} 16 | 17 | // TODO: FileStoreType名称待定 18 | 19 | // FileStoreType OXS 20 | type FileStoreType interface { 21 | // Setup 装载 endpoint sss 22 | Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error 23 | // UpLoad 上传 24 | UpLoad(yourObjectName string, localFile interface{}) error 25 | // GetTempToken 获取临时Token 26 | GetTempToken() (string, error) 27 | } 28 | -------------------------------------------------------------------------------- /template/v4/no_actions/router_no_check_role.go.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "smart-api/app/{{.PackageName}}/apis" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) 12 | } 13 | 14 | // register{{.ClassName}}Router 15 | func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.{{.ClassName}}{} 17 | r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()) 18 | { 19 | r.GET("", api.GetPage) 20 | r.GET("/:id", api.Get) 21 | r.POST("", api.Insert) 22 | r.PUT("/:id", api.Update) 23 | r.DELETE("", api.Delete) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /scripts/migrate.sh: -------------------------------------------------------------------------------- 1 | ./smart migrate -a true -g true 2 | ./smart migrate -c config/settings.yml 3 | 4 | 生成迁移文件 5 | go run main.go migrate -g true -c config/settings.yml 6 | 7 | 修改完迁移文件后,执行下面命令开始变更 8 | go run main.go migrate -c config/settings.yml 9 | 10 | go run main.go migrate -h # 帮助 11 | go run main.go migrate -g true -a true -c config/settings.dev.yml # 生成 smart系统预置 迁移文件 12 | go run main.go migrate -g true -c config/settings.dev.yml # 生成 自定义功能 迁移文件 自己开发新功能用这个功能 13 | go run main.go migrate -c config/settings.dev.yml # 执行迁移命令 迁移 未迁移过的 文件 14 | 15 | 16 | 生成迁移文件 17 | go run main.go migrate -g true -c config/settings.yml 18 | 19 | 修改完迁移文件后,执行下面命令开始变更 20 | go run main.go migrate -c config/settings.yml 21 | 22 | 生成迁移文件--系统相关 23 | go run main.go migrate -g true -a true -c config/settings.yml 24 | -------------------------------------------------------------------------------- /app/smart/router/user_favorite.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerUserFavoriteAuthRouter) 14 | } 15 | 16 | // registerSysApiRouter 需要JWT认证 17 | func registerUserFavoriteAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | api := apis.UserFavorites{} 19 | r := v1.Group("/favorite").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | r.POST("", api.AddFavorite) 22 | r.DELETE("", api.RemoveFavorite) 23 | r.GET("", api.GetUserFavorites) 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /app/system/models/sys_dict_type.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "smart-api/common/models" 5 | ) 6 | 7 | type SysDictType struct { 8 | ID int `json:"id" gorm:"primaryKey;column:dict_id;autoIncrement;comment:主键编码"` 9 | DictName string `json:"dictName" gorm:"size:128;comment:DictName"` 10 | DictType string `json:"dictType" gorm:"size:128;comment:DictType"` 11 | Status int `json:"status" gorm:"size:4;comment:Status"` 12 | Remark string `json:"remark" gorm:"size:255;comment:Remark"` 13 | models.ControlBy 14 | models.ModelTime 15 | } 16 | 17 | func (*SysDictType) TableName() string { 18 | return "sys_dict_type" 19 | } 20 | 21 | func (e *SysDictType) Generate() models.ActiveRecord { 22 | o := *e 23 | return &o 24 | } 25 | 26 | func (e *SysDictType) GetId() interface{} { 27 | return e.ID 28 | } 29 | -------------------------------------------------------------------------------- /app/smart/router/flow_templates.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerFlowTemplatesAuthRouter) 14 | } 15 | 16 | // 注册工单模板路由 17 | func registerFlowTemplatesAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | api := apis.FlowTemplates{} 19 | r := v1.Group("/flow-templates").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | r.GET("", api.GetPage) 22 | r.GET("/:id", api.Get) 23 | r.POST("", api.Insert) 24 | r.PUT("", api.Update) 25 | r.DELETE("", api.Delete) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/smart/router/order_category.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerOrderCategoryAuthRouter) 14 | } 15 | 16 | // 注册工单类别路由 17 | func registerOrderCategoryAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | api := apis.OrderCategory{} 19 | r := v1.Group("/order-category").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | r.GET("", api.GetPage) 22 | r.GET("/:id", api.Get) 23 | r.POST("", api.Insert) 24 | r.PUT("", api.Update) 25 | r.DELETE("", api.Delete) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/smart/router/order_items.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerOrderItemsAuthRouter) 14 | } 15 | 16 | // registerSysApiRouter 需要JWT认证 17 | func registerOrderItemsAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | api := apis.OrderItems{} 19 | r := v1.Group("/order-items").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | r.GET("", api.GetPage) 22 | r.GET("/:id", api.Get) 23 | r.POST("", api.Insert) 24 | r.PUT("", api.Update) 25 | r.DELETE("", api.Delete) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/smart/models/order_comment.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/8/17 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type OrderComment struct { 10 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 11 | OrderID int `gorm:"column:order_id" json:"orderID"` // 与工单ID关联 12 | ParentID *int `gorm:"column:parent_id" json:"parentID"` // 父留言ID,如果为空表示是顶级留言 13 | Comments string `gorm:"column:comment;type:varchar(255)" json:"comments"` // 留言内容 14 | models.ControlBy 15 | models.ModelTime 16 | } 17 | 18 | func (*OrderComment) TableName() string { 19 | return "order_comment" 20 | } 21 | 22 | func (e *OrderComment) Generate() models.ActiveRecord { 23 | o := *e 24 | return &o 25 | } 26 | 27 | func (e *OrderComment) GetId() interface{} { 28 | return e.ID 29 | } 30 | -------------------------------------------------------------------------------- /common/middleware/trace.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/opentracing/opentracing-go" 6 | ) 7 | 8 | // Trace 链路追踪 9 | func Trace() gin.HandlerFunc { 10 | return func(ctx *gin.Context) { 11 | var sp opentracing.Span 12 | opName := ctx.Request.URL.Path 13 | // Attempt to join a trace by getting trace context from the headers. 14 | wireContext, err := opentracing.GlobalTracer().Extract( 15 | opentracing.TextMap, 16 | opentracing.HTTPHeadersCarrier(ctx.Request.Header)) 17 | if err != nil { 18 | // If for whatever reason we can't join, go ahead and start a new root span. 19 | sp = opentracing.StartSpan(opName) 20 | } else { 21 | sp = opentracing.StartSpan(opName, opentracing.ChildOf(wireContext)) 22 | } 23 | ctx.Set("traceSpan", sp) 24 | ctx.Next() 25 | sp.Finish() 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /common/middleware/sentinel.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/alibaba/sentinel-golang/core/system" 5 | sentinel "github.com/alibaba/sentinel-golang/pkg/adapters/gin" 6 | "github.com/gin-gonic/gin" 7 | 8 | log "github.com/go-admin-team/go-admin-core/logger" 9 | ) 10 | 11 | // Sentinel 限流 12 | func Sentinel() gin.HandlerFunc { 13 | if _, err := system.LoadRules([]*system.Rule{ 14 | { 15 | MetricType: system.InboundQPS, 16 | TriggerCount: 200, 17 | Strategy: system.BBR, 18 | }, 19 | }); err != nil { 20 | log.Fatalf("Unexpected error: %+v", err) 21 | } 22 | return sentinel.SentinelMiddleware( 23 | sentinel.WithBlockFallback(func(ctx *gin.Context) { 24 | ctx.AbortWithStatusJSON(200, map[string]interface{}{ 25 | "msg": "too many request; the quota used up!", 26 | "code": 500, 27 | }) 28 | }), 29 | ) 30 | } 31 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_dept.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysDept struct { 4 | DeptId int `json:"deptId" gorm:"primaryKey;autoIncrement;"` //部门编码 5 | ParentId int `json:"parentId" gorm:""` //上级部门 6 | DeptPath string `json:"deptPath" gorm:"size:255;"` // 7 | DeptName string `json:"deptName" gorm:"size:128;"` //部门名称 8 | Sort int `json:"sort" gorm:"size:4;"` //排序 9 | Leader string `json:"leader" gorm:"size:128;"` //负责人 10 | Phone string `json:"phone" gorm:"size:11;"` //手机 11 | Email string `json:"email" gorm:"size:64;"` //邮箱 12 | Status int `json:"status" gorm:"size:4;"` //状态 13 | ControlBy 14 | ModelTime 15 | } 16 | 17 | func (SysDept) TableName() string { 18 | return "sys_dept" 19 | } 20 | -------------------------------------------------------------------------------- /app/system/router/sys_dept.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/system/apis" 7 | "smart-api/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysDeptRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysDeptRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysDept{} 17 | 18 | r := v1.Group("/dept").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("/:id", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | 27 | r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 28 | { 29 | r1.GET("/deptTree", api.Get2Tree) 30 | } 31 | 32 | } 33 | -------------------------------------------------------------------------------- /app/jobs/router/int_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | //"github.com/go-admin-team/go-admin-core/sdk/pkg" 5 | "os" 6 | 7 | "github.com/gin-gonic/gin" 8 | log "github.com/go-admin-team/go-admin-core/logger" 9 | "github.com/go-admin-team/go-admin-core/sdk" 10 | common "smart-api/common/middleware" 11 | ) 12 | 13 | // InitRouter 路由初始化,不要怀疑,这里用到了 14 | func InitRouter() { 15 | var r *gin.Engine 16 | h := sdk.Runtime.GetEngine() 17 | if h == nil { 18 | log.Fatal("not found engine...") 19 | os.Exit(-1) 20 | } 21 | switch h.(type) { 22 | case *gin.Engine: 23 | r = h.(*gin.Engine) 24 | default: 25 | log.Fatal("not support other engine") 26 | os.Exit(-1) 27 | } 28 | 29 | authMiddleware, err := common.AuthInit() 30 | if err != nil { 31 | log.Fatalf("JWT Init Error, %s", err.Error()) 32 | } 33 | 34 | // 注册业务路由 35 | initRouter(r, authMiddleware) 36 | } 37 | -------------------------------------------------------------------------------- /app/smart/router/init_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | common "smart-api/common/middleware" 10 | ) 11 | 12 | // Smart Api自定义路由 13 | func InitRouter() { 14 | var r *gin.Engine 15 | h := sdk.Runtime.GetEngine() 16 | if h == nil { 17 | log.Fatal("not found engine...") 18 | os.Exit(-1) 19 | } 20 | switch h.(type) { 21 | case *gin.Engine: 22 | r = h.(*gin.Engine) 23 | default: 24 | log.Fatal("not support smart-api engine") 25 | os.Exit(-1) 26 | } 27 | // the jwt middleware 28 | authMiddleware, err := common.AuthInit() 29 | if err != nil { 30 | log.Fatalf("JWT Init Error, %s", err.Error()) 31 | } 32 | 33 | // 注册业务路由 34 | // TODO: 这里存放业务路由,当前目录下的router.go 35 | initRouter(r, authMiddleware) 36 | } 37 | -------------------------------------------------------------------------------- /app/other/router/init_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | common "smart-api/common/middleware" 10 | ) 11 | 12 | // InitRouter 路由初始化,不要怀疑,这里用到了 13 | func InitRouter() { 14 | var r *gin.Engine 15 | h := sdk.Runtime.GetEngine() 16 | if h == nil { 17 | log.Fatal("not found engine...") 18 | os.Exit(-1) 19 | } 20 | switch h.(type) { 21 | case *gin.Engine: 22 | r = h.(*gin.Engine) 23 | default: 24 | log.Fatal("not support other engine") 25 | os.Exit(-1) 26 | } 27 | // the jwt middleware 28 | authMiddleware, err := common.AuthInit() 29 | if err != nil { 30 | log.Fatalf("JWT Init Error, %s", err.Error()) 31 | } 32 | 33 | // 注册业务路由 34 | // TODO: 这里可存放业务路由,里边并无实际路由只有演示代码 35 | initRouter(r, authMiddleware) 36 | } 37 | -------------------------------------------------------------------------------- /config/settings.demo.yml: -------------------------------------------------------------------------------- 1 | settings: 2 | application: 3 | demomsg: "谢谢您的参与,但为了大家更好的体验,所以本次提交就算了吧!\U0001F600\U0001F600\U0001F600" 4 | enabledp: true 5 | host: 0.0.0.0 6 | mode: demo 7 | name: testApp 8 | port: 8000 9 | readtimeout: 10000 10 | writertimeout: 20000 11 | database: 12 | driver: sqlite3 13 | source: ./smart-api-db.db 14 | gen: 15 | dbname: testhhh 16 | frontpath: ../smart-api-ui/src 17 | jwt: 18 | secret: smart-api 19 | timeout: 3600 20 | logger: 21 | # 日志存放路径 22 | path: temp/logs 23 | # 日志输出,file:文件,default:命令行,其他:命令行 24 | stdout: '' #控制台日志,启用后,不输出到文件 25 | # 日志等级, trace, debug, info, warn, error, fatal 26 | level: trace 27 | # 数据库日志开关 28 | enableddb: true 29 | queue: 30 | memory: 31 | poolSize: 100 32 | extend: 33 | amap: 34 | key: de7a062c984bf828d5d1b3a631a517e4 35 | -------------------------------------------------------------------------------- /app/system/apis/sys_notify.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/gin-gonic/gin/binding" 6 | "github.com/go-admin-team/go-admin-core/sdk/api" 7 | _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 8 | "smart-api/app/system/service" 9 | "smart-api/app/system/service/dto" 10 | ) 11 | 12 | type SysNotify struct { 13 | api.Api 14 | } 15 | 16 | func (e SysNotify) NotifySend(c *gin.Context) { 17 | s := service.SysNotify{} 18 | req := dto.SysNotify{} 19 | err := e.MakeContext(c). 20 | MakeOrm(). 21 | Bind(&req, binding.JSON). 22 | MakeService(&s.Service). 23 | Errors 24 | if err != nil { 25 | e.Logger.Error(err) 26 | e.Error(500, err, err.Error()) 27 | return 28 | } 29 | 30 | // 设置创建 31 | err = s.SendMessage(&req) 32 | if err != nil { 33 | e.Error(500, err, "发送通知失败") 34 | return 35 | } 36 | e.OK(nil, "通知发送成功") 37 | } 38 | -------------------------------------------------------------------------------- /app/smart/router/flow_manage.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/actions" 10 | "smart-api/common/middleware" 11 | ) 12 | 13 | func init() { 14 | routerCheckRole = append(routerCheckRole, registerFlowManageAuthRouter) 15 | } 16 | 17 | // 注册工单模板路由 18 | func registerFlowManageAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 19 | api := apis.FlowManage{} 20 | r := v1.Group("/flow-manage").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction()) 21 | { 22 | r.POST("", api.Insert) 23 | r.POST("/:id", api.Clone) 24 | r.GET("", api.GetPage) 25 | r.GET("/:id", api.Get) 26 | r.PUT("", api.Update) 27 | r.DELETE("", api.Delete) 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /config/extend.go: -------------------------------------------------------------------------------- 1 | package config 2 | 3 | var ExtConfig *Extend 4 | 5 | // Extend 扩展配置 6 | // 7 | // extend: 8 | // demo: 9 | // name: demo-name 10 | // 11 | // 使用方法: config.ExtConfig......即可!! 12 | 13 | type Extend struct { 14 | Ldap *Ldap // 这里配置对应配置文件的结构即可 15 | Notify *Notify 16 | AesSecrets *AesSecrets // 对称加密 key 17 | } 18 | 19 | type Ldap struct { 20 | Host string `yaml:"host"` 21 | Tls bool `yaml:"tls"` 22 | Port int `yaml:"port"` 23 | BindDN string `yaml:"bindDN"` 24 | BindPassword string `yaml:"bindPassword"` 25 | SearchDomain string `yaml:"searchDomain"` 26 | } 27 | 28 | type Notify struct { 29 | BotCredit *BotCredit `yaml:"bot_credit"` 30 | } 31 | 32 | type BotCredit struct { 33 | AppID string `yaml:"appid" ` 34 | AppSecret string `yaml:"app_secret" ` 35 | } 36 | 37 | type AesSecrets struct { 38 | Key string `yaml:"key"` 39 | } 40 | -------------------------------------------------------------------------------- /app/system/apis/go_admin.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | ) 6 | 7 | const INDEX = ` 8 | 9 | 10 | 11 | 12 | Smart 欢迎您 13 | 20 | 21 | 29 | 30 | 31 | 32 | 33 | 34 | ` 35 | 36 | func GoAdmin(c *gin.Context) { 37 | c.Header("Content-Type", "text/html; charset=utf-8") 38 | c.String(200, INDEX) 39 | } 40 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/order_category.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/16 21:14 3 | package models 4 | 5 | import ( 6 | models2 "smart-api/cmd/migrate/migration/models" 7 | ) 8 | 9 | type OrderCategory struct { 10 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 11 | Name string `gorm:"column:name;type:varchar(50)" json:"name"` 12 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 13 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 14 | ChineseName string `gorm:"column:chineseName;type:varchar(50)" json:"chineseName"` 15 | FlowTemplates []FlowTemplates `gorm:"foreignKey:CategoryID" json:"flowTemplates"` 16 | models2.ControlBy 17 | models2.ModelTime 18 | } 19 | 20 | func (OrderCategory) TableName() string { 21 | return "order_category" 22 | } 23 | -------------------------------------------------------------------------------- /app/smart/router/order_statistics.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/9/25 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerOrderStatisticsAuthRouter) 14 | } 15 | 16 | // registerSysApiRouter 需要JWT认证 17 | func registerOrderStatisticsAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | api := apis.OrderStatistics{} 19 | r := v1.Group("/statistics").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | r.GET("/orders", api.GetOrderStatistics) // 获取工单统计 22 | r.GET("/orders/count", api.GetOrderCountByPeriod) // 根据周或月统计工单数量,以及个人提交排行榜 23 | 24 | r.GET("/ratings", api.GetOrderRatingsByPeriod) // 根据周或月统计获取评分统计 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /app/system/router/sys_menu.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/system/apis" 7 | "smart-api/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerSysMenuRouter) 12 | } 13 | 14 | // 需认证的路由代码 15 | func registerSysMenuRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 16 | api := apis.SysMenu{} 17 | 18 | r := v1.Group("/menu").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("/:id", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | 27 | r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 28 | { 29 | r1.GET("/menurole", api.GetMenuRole) 30 | //r1.GET("/menuids", api.GetMenuIDS) 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /app/system/router/sys_role.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "smart-api/app/system/apis" 8 | "smart-api/common/middleware" 9 | ) 10 | 11 | func init() { 12 | routerCheckRole = append(routerCheckRole, registerSysRoleRouter) 13 | } 14 | 15 | // 需认证的路由代码 16 | func registerSysRoleRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 17 | api := apis.SysRole{} 18 | r := v1.Group("/role").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("/:id", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | r1 := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 27 | { 28 | r1.PUT("/role-status", api.Update2Status) 29 | r1.PUT("/roledatascope", api.Update2DataScope) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/system/models/sys_config.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "smart-api/common/models" 5 | ) 6 | 7 | type SysConfig struct { 8 | models.Model 9 | ConfigName string `json:"configName" gorm:"size:128;comment:ConfigName"` // 10 | ConfigKey string `json:"configKey" gorm:"size:128;comment:ConfigKey"` // 11 | ConfigValue string `json:"configValue" gorm:"size:255;comment:ConfigValue"` // 12 | ConfigType string `json:"configType" gorm:"size:64;comment:ConfigType"` 13 | IsFrontend string `json:"isFrontend" gorm:"size:64;comment:是否前台"` // 14 | Remark string `json:"remark" gorm:"size:128;comment:Remark"` // 15 | models.ControlBy 16 | models.ModelTime 17 | } 18 | 19 | func (*SysConfig) TableName() string { 20 | return "sys_config" 21 | } 22 | 23 | func (e *SysConfig) Generate() models.ActiveRecord { 24 | o := *e 25 | return &o 26 | } 27 | 28 | func (e *SysConfig) GetId() interface{} { 29 | return e.Id 30 | } 31 | -------------------------------------------------------------------------------- /template/v4/no_actions/router_check_role.go.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "smart-api/app/{{.PackageName}}/apis" 8 | "smart-api/common/middleware" 9 | "smart-api/common/actions" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) 14 | } 15 | 16 | // register{{.ClassName}}Router 17 | func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | api := apis.{{.ClassName}}{} 19 | r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | r.GET("", actions.PermissionAction(), api.GetPage) 22 | r.GET("/:id", actions.PermissionAction(), api.Get) 23 | r.POST("", api.Insert) 24 | r.PUT("/:id", actions.PermissionAction(), api.Update) 25 | r.DELETE("", api.Delete) 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /app/smart/router/order_comment.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerOrderCommentAuthRouter) 14 | } 15 | 16 | // 注册工单评论路由 17 | func registerOrderCommentAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | commentApi := apis.OrderCommentAPI{} 19 | 20 | r := v1.Group("/order-comments").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 21 | { 22 | // 根据ID获取评论 23 | r.GET("/:orderID", commentApi.Get) // 根据工单ID获取所有留言 24 | // 添加留言 25 | r.POST("", commentApi.Insert) // 添加留言的路由 26 | // 更新留言 27 | r.PUT("", commentApi.Update) // 更新留言的路由 28 | // 删除留言 29 | r.DELETE("", commentApi.Delete) // 删除留言的路由 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/smart/service/dto/user_favorite.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "smart-api/app/smart/models" 5 | common "smart-api/common/models" 6 | ) 7 | 8 | type UserFavoriteInsertReq struct { 9 | OrderItemID uint `json:"orderItemId" binding:"required"` // 工单项ID 10 | UserID int `json:"userID"` // 用户id 11 | common.ControlBy 12 | } 13 | 14 | // Generate 生成 OrderRating 模型实例 15 | func (s *UserFavoriteInsertReq) Generate(userID int, model *models.UserFavorites) { 16 | model.OrderItemID = s.OrderItemID 17 | model.UserID = userID 18 | model.ControlBy = s.ControlBy 19 | } 20 | 21 | // GetId 获取数据对应的 ID 22 | func (s *UserFavoriteInsertReq) GetId() interface{} { 23 | return s.OrderItemID 24 | } 25 | 26 | type UserFavoriteDeleteReq struct { 27 | OrderItemID uint `json:"orderItemId" binding:"required"` // 工单项ID 28 | } 29 | 30 | // GetId 删除数据对应的 ID 31 | func (s *UserFavoriteDeleteReq) GetId() interface{} { 32 | return s.OrderItemID 33 | } 34 | -------------------------------------------------------------------------------- /app/system/models/sys_post.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "smart-api/common/models" 4 | 5 | type SysPost struct { 6 | PostId int `gorm:"primaryKey;autoIncrement" json:"postId"` //岗位编号 7 | PostName string `gorm:"size:128;" json:"postName"` //岗位名称 8 | PostCode string `gorm:"size:128;" json:"postCode"` //岗位代码 9 | Sort int `gorm:"size:4;" json:"sort"` //岗位排序 10 | Status int `gorm:"size:4;" json:"status"` //状态 11 | Remark string `gorm:"size:255;" json:"remark"` //描述 12 | models.ControlBy 13 | models.ModelTime 14 | 15 | DataScope string `gorm:"-" json:"dataScope"` 16 | Params string `gorm:"-" json:"params"` 17 | } 18 | 19 | func (*SysPost) TableName() string { 20 | return "sys_post" 21 | } 22 | 23 | func (e *SysPost) Generate() models.ActiveRecord { 24 | o := *e 25 | return &o 26 | } 27 | 28 | func (e *SysPost) GetId() interface{} { 29 | return e.PostId 30 | } 31 | -------------------------------------------------------------------------------- /config/pg.sql: -------------------------------------------------------------------------------- 1 | -- 开始初始化数据 ; 2 | create sequence if not exists sys_role_role_id_seq; 3 | create sequence if not exists sys_user_user_id_seq; 4 | create sequence if not exists sys_post_post_id_seq; 5 | create sequence if not exists sys_menu_menu_id_seq; 6 | create sequence if not exists sys_dict_type_dict_id_seq; 7 | create sequence if not exists sys_dict_data_dict_code_seq; 8 | create sequence if not exists sys_dept_dept_id_seq; 9 | create sequence if not exists sys_config_config_id_seq; 10 | create sequence if not exists sys_job_id_seq; 11 | 12 | select setval('sys_role_role_id_seq',4); 13 | select setval('sys_user_user_id_seq',5); 14 | select setval('sys_post_post_id_seq',4); 15 | select setval('sys_menu_menu_id_seq',543); 16 | select setval('sys_dict_type_dict_id_seq',12); 17 | select setval('sys_dict_data_dict_code_seq',34); 18 | select setval('sys_dept_dept_id_seq',11); 19 | select setval('sys_config_config_id_seq',6); 20 | select setval('sys_job_id_seq',3); 21 | -- 数据完成 ; 22 | -------------------------------------------------------------------------------- /app/smart/router/order_rating.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerOrderRatingAuthRouter) 14 | } 15 | 16 | // 注册工单评论路由 17 | func registerOrderRatingAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | ratingApi := apis.OrderRatingAPI{} // 假设你有一个处理评分的 API 19 | 20 | rating := v1.Group("/order-ratings").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 21 | { 22 | // 获取工单评分 23 | rating.GET("/:orderID", ratingApi.Get) // 添加评分的路由 24 | // 添加评分 25 | rating.POST("", ratingApi.Insert) // 添加评分的路由 26 | // 更新评分 27 | rating.PUT("", ratingApi.Update) // 更新评分的路由 28 | // 删除评分 29 | rating.DELETE("", ratingApi.Delete) // 删除评分的路由 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /app/smart/router/exec_machine.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerExecMachineAuthRouter) 14 | } 15 | 16 | // 执行节点管理 17 | func registerExecMachineAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 18 | api := apis.ExecMachine{} 19 | r := v1.Group("/exec-machine").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | // 查询所有节点 22 | r.GET("", api.GetPage) 23 | // 根据ID 查询 24 | r.GET("/:id", api.Get) 25 | // 创建节点 26 | r.POST("", api.Insert) 27 | // 更新节点信息 28 | r.PUT("", api.Update) 29 | // 删除节点 30 | r.DELETE("", api.Delete) 31 | // 新增连接测试接口 32 | r.POST("/testConnection", api.TestConnection) // 添加连接测试接口 33 | 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /app/system/router/init_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "os" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | common "smart-api/common/middleware" 10 | ) 11 | 12 | // InitRouter 路由初始化,不要怀疑,这里用到了 13 | func InitRouter() { 14 | var r *gin.Engine 15 | h := sdk.Runtime.GetEngine() 16 | if h == nil { 17 | log.Fatal("not found engine...") 18 | os.Exit(-1) 19 | } 20 | switch h.(type) { 21 | case *gin.Engine: 22 | r = h.(*gin.Engine) 23 | default: 24 | log.Fatal("not support other engine") 25 | os.Exit(-1) 26 | } 27 | 28 | // the jwt middleware 29 | authMiddleware, err := common.AuthInit() 30 | if err != nil { 31 | log.Fatalf("JWT Init Error, %s", err.Error()) 32 | } 33 | 34 | // 注册系统路由 35 | InitSysRouter(r, authMiddleware) 36 | 37 | // 注册业务路由 38 | InitSmartApiRouter(r, authMiddleware) 39 | 40 | // 注册LDAP路由 41 | InitLDAPRouter(r, authMiddleware) 42 | } 43 | -------------------------------------------------------------------------------- /common/middleware/request_id.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/go-admin-team/go-admin-core/logger" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 6 | "net/http" 7 | "strings" 8 | 9 | "github.com/gin-gonic/gin" 10 | "github.com/google/uuid" 11 | ) 12 | 13 | // RequestId 自动增加requestId 14 | func RequestId(trafficKey string) gin.HandlerFunc { 15 | return func(c *gin.Context) { 16 | if c.Request.Method == http.MethodOptions { 17 | c.Next() 18 | return 19 | } 20 | requestId := c.GetHeader(trafficKey) 21 | if requestId == "" { 22 | requestId = c.GetHeader(strings.ToLower(trafficKey)) 23 | } 24 | if requestId == "" { 25 | requestId = uuid.New().String() 26 | } 27 | c.Request.Header.Set(trafficKey, requestId) 28 | c.Set(trafficKey, requestId) 29 | c.Set(pkg.LoggerKey, 30 | logger.NewHelper(logger.DefaultLogger). 31 | WithFields(map[string]interface{}{ 32 | trafficKey: requestId, 33 | })) 34 | c.Next() 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /config/settings.sqlite.yml: -------------------------------------------------------------------------------- 1 | settings: 2 | application: 3 | # dev开发环境 test测试环境 prod线上环境 4 | mode: dev 5 | # 服务器ip,默认使用 0.0.0.0 6 | host: 0.0.0.0 7 | # 服务名称 8 | name: testApp 9 | # 端口号 10 | port: 8000 # 服务端口号 11 | readtimeout: 3000 12 | writertimeout: 2000 13 | # 数据权限功能开关 14 | enabledp: false 15 | logger: 16 | # 日志存放路径 17 | path: temp/logs 18 | # 日志输出,file:文件,default:命令行,其他:命令行 19 | stdout: '' #控制台日志,启用后,不输出到文件 20 | # 日志等级, trace, debug, info, warn, error, fatal 21 | level: trace 22 | # 数据库日志开关 23 | enableddb: false 24 | jwt: 25 | # token 密钥,生产环境时及的修改 26 | secret: smart-api 27 | # token 过期时间 单位:秒 28 | timeout: 3600 29 | database: 30 | # 数据库类型 mysql,sqlite3, postgres 31 | driver: sqlite3 32 | # 数据库连接sqlite3数据文件的路径 33 | source: smart-api-db.db 34 | gen: 35 | # 代码生成读取的数据库名称 36 | dbname: dbname 37 | # 代码生成是使用前端代码存放位置,需要指定到src文件夹,相对路径 38 | frontpath: ../smart-api-ui/src 39 | -------------------------------------------------------------------------------- /app/system/apis/captcha.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk/api" 6 | "github.com/go-admin-team/go-admin-core/sdk/pkg/captcha" 7 | ) 8 | 9 | type System struct { 10 | api.Api 11 | } 12 | 13 | // GenerateCaptchaHandler 获取验证码 14 | // @Summary 获取验证码 15 | // @Description 获取验证码 16 | // @Tags 登陆 17 | // @Success 200 {object} response.Response{data=string,id=string,msg=string} "{"code": 200, "data": [...]}" 18 | // @Router /api/v1/captcha [get] 19 | func (e System) GenerateCaptchaHandler(c *gin.Context) { 20 | err := e.MakeContext(c).Errors 21 | if err != nil { 22 | e.Error(500, err, "服务初始化失败!") 23 | return 24 | } 25 | id, b64s, err := captcha.DriverDigitFunc() 26 | if err != nil { 27 | e.Logger.Errorf("DriverDigitFunc error, %s", err.Error()) 28 | e.Error(500, err, "验证码获取失败") 29 | return 30 | } 31 | e.Custom(gin.H{ 32 | "code": 200, 33 | "data": b64s, 34 | "id": id, 35 | "msg": "success", 36 | }) 37 | } 38 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_role.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysRole struct { 4 | RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 5 | RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 6 | Status string `json:"status" gorm:"size:4;"` // 7 | RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 8 | RoleSort int `json:"roleSort" gorm:""` //角色排序 9 | Flag string `json:"flag" gorm:"size:128;"` // 10 | Remark string `json:"remark" gorm:"size:255;"` //备注 11 | Admin bool `json:"admin" gorm:"size:4;"` 12 | DataScope string `json:"dataScope" gorm:"size:128;"` 13 | SysMenu []SysMenu `json:"sysMenu" gorm:"many2many:sys_role_menu;foreignKey:RoleId;joinForeignKey:role_id;references:MenuId;joinReferences:menu_id;"` 14 | ControlBy 15 | ModelTime 16 | } 17 | 18 | func (SysRole) TableName() string { 19 | return "sys_role" 20 | } -------------------------------------------------------------------------------- /common/middleware/handler/role.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import "smart-api/common/models" 4 | 5 | type SysRole struct { 6 | RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 7 | RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 8 | Status string `json:"status" gorm:"size:4;"` // 9 | RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 10 | RoleSort int `json:"roleSort" gorm:""` //角色排序 11 | Flag string `json:"flag" gorm:"size:128;"` // 12 | Remark string `json:"remark" gorm:"size:255;"` //备注 13 | Admin bool `json:"admin" gorm:"size:4;"` 14 | DataScope string `json:"dataScope" gorm:"size:128;"` 15 | Params string `json:"params" gorm:"-"` 16 | MenuIds []int `json:"menuIds" gorm:"-"` 17 | DeptIds []int `json:"deptIds" gorm:"-"` 18 | models.ControlBy 19 | models.ModelTime 20 | } 21 | 22 | func (SysRole) TableName() string { 23 | return "sys_role" 24 | } 25 | -------------------------------------------------------------------------------- /template/migrate.template: -------------------------------------------------------------------------------- 1 | package {{.Package}} 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "runtime" 6 | 7 | "smart-api/cmd/migrate/migration" 8 | common "smart-api/common/models" 9 | ) 10 | 11 | func init() { 12 | _, fileName, _, _ := runtime.Caller(0) 13 | migration.Migrate.SetVersion(migration.GetFilename(fileName), _{{.GenerateTime}}Test) 14 | } 15 | 16 | func _{{.GenerateTime}}Test(db *gorm.DB, version string) error { 17 | return db.Transaction(func(tx *gorm.DB) error { 18 | 19 | // TODO: 这里开始写入要变更的内容 20 | 21 | // TODO: 例如 修改表字段 使用过程中请删除此段代码 22 | //err := tx.Migrator().RenameColumn(&models.SysConfig{}, "config_id", "id") 23 | //if err != nil { 24 | // return err 25 | //} 26 | 27 | // TODO: 例如 新增表结构 使用过程中请删除此段代码 28 | //err = tx.Debug().Migrator().AutoMigrate( 29 | // new(models.CasbinRule), 30 | // ) 31 | //if err != nil { 32 | // return err 33 | //} 34 | 35 | 36 | return tx.Create(&common.Migration{ 37 | Version: version, 38 | }).Error 39 | }) 40 | } 41 | -------------------------------------------------------------------------------- /app/smart/models/order_category.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/13 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type OrderCategory struct { 10 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 11 | Name string `gorm:"column:name;type:varchar(50)" json:"name"` 12 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 13 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 14 | ChineseName string `gorm:"column:chineseName;type:varchar(50)" json:"chineseName"` 15 | FlowTemplates []FlowTemplates `gorm:"foreignKey:CategoryID" json:"flowTemplates"` 16 | models.ControlBy 17 | models.ModelTime 18 | } 19 | 20 | func (*OrderCategory) TableName() string { 21 | return "order_category" 22 | } 23 | 24 | func (e *OrderCategory) Generate() models.ActiveRecord { 25 | o := *e 26 | return &o 27 | } 28 | 29 | func (e *OrderCategory) GetId() interface{} { 30 | return e.ID 31 | } 32 | -------------------------------------------------------------------------------- /app/jobs/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | ) 7 | 8 | var ( 9 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 10 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 11 | ) 12 | 13 | // initRouter 路由示例 14 | func initRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 15 | 16 | // 无需认证的路由 17 | noCheckRoleRouter(r) 18 | // 需要认证的路由 19 | checkRoleRouter(r, authMiddleware) 20 | 21 | return r 22 | } 23 | 24 | // noCheckRoleRouter 无需认证的路由示例 25 | func noCheckRoleRouter(r *gin.Engine) { 26 | // 可根据业务需求来设置接口版本 27 | v1 := r.Group("/api/v1") 28 | 29 | for _, f := range routerNoCheckRole { 30 | f(v1) 31 | } 32 | } 33 | 34 | // checkRoleRouter 需要认证的路由示例 35 | func checkRoleRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) { 36 | // 可根据业务需求来设置接口版本 37 | v1 := r.Group("/api/v1") 38 | 39 | for _, f := range routerCheckRole { 40 | f(v1, authMiddleware) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /app/other/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | ) 7 | 8 | var ( 9 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 10 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 11 | ) 12 | 13 | // initRouter 路由示例 14 | func initRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 15 | 16 | // 无需认证的路由 17 | noCheckRoleRouter(r) 18 | // 需要认证的路由 19 | checkRoleRouter(r, authMiddleware) 20 | 21 | return r 22 | } 23 | 24 | // noCheckRoleRouter 无需认证的路由示例 25 | func noCheckRoleRouter(r *gin.Engine) { 26 | // 可根据业务需求来设置接口版本 27 | v1 := r.Group("/api/v1") 28 | 29 | for _, f := range routerNoCheckRole { 30 | f(v1) 31 | } 32 | } 33 | 34 | // checkRoleRouter 需要认证的路由示例 35 | func checkRoleRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) { 36 | // 可根据业务需求来设置接口版本 37 | v1 := r.Group("/api/v1") 38 | 39 | for _, f := range routerCheckRole { 40 | f(v1, authMiddleware) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /common/middleware/init.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk" 6 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 7 | "smart-api/common/actions" 8 | ) 9 | 10 | const ( 11 | JwtTokenCheck string = "JwtToken" 12 | RoleCheck string = "AuthCheckRole" 13 | PermissionCheck string = "PermissionAction" 14 | ) 15 | 16 | func InitMiddleware(r *gin.Engine) { 17 | r.Use(DemoEvn()) 18 | // 数据库链接 19 | r.Use(WithContextDb) 20 | // 日志处理 21 | r.Use(LoggerToFile()) 22 | // 自定义错误处理 23 | r.Use(CustomError) 24 | // NoCache is a middleware function that appends headers 25 | r.Use(NoCache) 26 | // 跨域处理 27 | r.Use(Options) 28 | // Secure is a middleware function that appends security 29 | r.Use(Secure) 30 | // 链路追踪 31 | //r.Use(middleware.Trace()) 32 | sdk.Runtime.SetMiddleware(JwtTokenCheck, (*jwt.GinJWTMiddleware).MiddlewareFunc) 33 | sdk.Runtime.SetMiddleware(RoleCheck, AuthCheckRole()) 34 | sdk.Runtime.SetMiddleware(PermissionCheck, actions.PermissionAction()) 35 | } 36 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright © 2024 sunwenbo smart swb956721830@163.com 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /common/middleware/demo.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk/config" 6 | "net/http" 7 | ) 8 | 9 | func DemoEvn() gin.HandlerFunc { 10 | return func(c *gin.Context) { 11 | method := c.Request.Method 12 | if config.ApplicationConfig.Mode == "demo" { 13 | if method == "GET" || 14 | method == "OPTIONS" || 15 | c.Request.RequestURI == "/api/v1/login" || 16 | c.Request.RequestURI == "/api/v1/logout" { 17 | c.Next() 18 | } else { 19 | // 添加跨域头部 20 | c.Header("Access-Control-Allow-Origin", "*") 21 | c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS") 22 | c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept, user-agent") 23 | c.Header("Access-Control-Allow-Credentials", "true") 24 | c.JSON(http.StatusOK, gin.H{ 25 | "code": 500, 26 | "msg": "谢谢您的参与,但为了大家更好的体验,所以本次提交就算了吧!\U0001F600\U0001F600\U0001F600", 27 | }) 28 | c.Abort() 29 | return 30 | } 31 | } 32 | c.Next() 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_job.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysJob struct { 4 | JobId int `json:"jobId" gorm:"primaryKey;autoIncrement"` // 编码 5 | JobName string `json:"jobName" gorm:"size:255;"` // 名称 6 | JobGroup string `json:"jobGroup" gorm:"size:255;"` // 任务分组 7 | JobType int `json:"jobType" gorm:"size:1;"` // 任务类型 8 | CronExpression string `json:"cronExpression" gorm:"size:255;"` // cron表达式 9 | InvokeTarget string `json:"invokeTarget" gorm:"size:255;"` // 调用目标 10 | Args string `json:"args" gorm:"size:255;"` // 目标参数 11 | MisfirePolicy int `json:"misfirePolicy" gorm:"size:255;"` // 执行策略 12 | Concurrent int `json:"concurrent" gorm:"size:1;"` // 是否并发 13 | Status int `json:"status" gorm:"size:1;"` // 状态 14 | EntryId int `json:"entry_id" gorm:"size:11;"` // job启动时返回的id 15 | ModelTime 16 | ControlBy 17 | } 18 | 19 | func (SysJob) TableName() string { 20 | return "sys_job" 21 | } 22 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/flow_templates.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/16 21:14 3 | package models 4 | 5 | import ( 6 | models2 "smart-api/cmd/migrate/migration/models" 7 | ) 8 | 9 | type FormData map[string]interface{} 10 | 11 | type FlowTemplates struct { 12 | ID uint `gorm:"primaryKey;autoIncrement"` 13 | Name string `gorm:"column:name;type:varchar(100)" json:"name"` 14 | Description string `gorm:"column:description;type:varchar(200)" json:"description"` 15 | BindCount int `gorm:"column:bindCount" json:"bindCount"` 16 | FormData FormData `gorm:"type:json" json:"formData"` 17 | CategoryID uint `gorm:"column:categoryId" json:"categoryId"` 18 | BindFlow uint `gorm:"column:bindFlow" json:"bindFlow"` 19 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 20 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 21 | models2.ControlBy 22 | models2.ModelTime 23 | } 24 | 25 | func (FlowTemplates) TableName() string { 26 | return "flow_templates" 27 | } 28 | -------------------------------------------------------------------------------- /app/smart/router/router.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:42 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | ) 9 | 10 | var ( 11 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 12 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 13 | ) 14 | 15 | // initRouter 路由示例 16 | func initRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 17 | 18 | // 无需认证的路由 19 | noCheckRoleRouter(r) 20 | // 需要认证的路由 21 | checkRoleRouter(r, authMiddleware) 22 | 23 | return r 24 | } 25 | 26 | // noCheckRoleRouter 无需认证的路由示例 27 | func noCheckRoleRouter(r *gin.Engine) { 28 | // 可根据业务需求来设置接口版本 29 | v1 := r.Group("/api/v1") 30 | 31 | for _, f := range routerNoCheckRole { 32 | f(v1) 33 | } 34 | } 35 | 36 | // checkRoleRouter 需要认证的路由示例 37 | func checkRoleRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) { 38 | // 可根据业务需求来设置接口版本 39 | v1 := r.Group("/api/v1/") 40 | 41 | for _, f := range routerCheckRole { 42 | f(v1, authMiddleware) 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /app/system/router/router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | _ "github.com/gin-gonic/gin" 6 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | ) 9 | 10 | var ( 11 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 12 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 13 | ) 14 | 15 | func InitSmartApiRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 16 | // 无需认证的路由 17 | smartApiNoCheckRoleRouter(r) 18 | // 需要认证的路由 19 | smartApiCheckRoleRouter(r, authMiddleware) 20 | return r 21 | } 22 | 23 | // 无需认证的路由示例 24 | func smartApiNoCheckRoleRouter(r *gin.Engine) { 25 | // 可根据业务需求来设置接口版本 26 | v1 := r.Group("/api/v1") 27 | for _, f := range routerNoCheckRole { 28 | f(v1) 29 | } 30 | } 31 | 32 | // 需要认证的路由示例 33 | func smartApiCheckRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) { 34 | // 可根据业务需求来设置接口版本 35 | v1 := r.Group("/api/v1") 36 | for _, f := range routerCheckRole { 37 | f(v1, authMiddleware) 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/order_items.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/13 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type OrderItems struct { 10 | ID uint `gorm:"primaryKey" json:"id"` 11 | Title string `gorm:"column:title;type:varchar(50)" json:"title"` // 订单项标题 12 | BindTempLate string `gorm:"column:bindTempLate;type:varchar(50)" json:"bindTempLate"` // 绑定模板 13 | Description string `gorm:"column:description;type:varchar(256)" json:"description"` // 订单项描述 14 | Icon string `gorm:"column:icon;type:varchar(50)" json:"icon"` // 订单项图标 15 | CategoryID uint `gorm:"column:categoryId" json:"categoryId"` 16 | Link string `gorm:"column:link;type:varchar(256)" json:"link"` // 连接到网页 17 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 18 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 19 | models.ControlBy 20 | models.ModelTime 21 | } 22 | 23 | func (*OrderItems) TableName() string { 24 | return "order_items" 25 | } 26 | -------------------------------------------------------------------------------- /test/gen_test.go: -------------------------------------------------------------------------------- 1 | package test 2 | 3 | import ( 4 | //"smart-api/models/tools" 5 | //"os" 6 | "testing" 7 | //"text/template" 8 | ) 9 | 10 | func TestGoModelTemplate(t *testing.T) { 11 | //t1, err := template.ParseFiles("model.go.template") 12 | //if err != nil { 13 | // t.Error(err) 14 | //} 15 | //table := tools.SysTables{} 16 | //table.TBName = "sys_tables" 17 | //tab, err := table.Get() 18 | //if err != nil { 19 | // t.Error(err) 20 | //} 21 | //file, err := os.Create("models/" + table.PackageName + ".go") 22 | //if err != nil { 23 | // t.Error(err) 24 | //} 25 | //defer file.Close() 26 | // 27 | //_ = t1.Execute(file, tab) 28 | t.Log("") 29 | } 30 | 31 | func TestGoApiTemplate(t *testing.T) { 32 | //t1, err := template.ParseFiles("api.go.template") 33 | //if err != nil { 34 | // t.Error(err) 35 | //} 36 | //table := tools.SysTables{} 37 | //table.TBName = "sys_tables" 38 | //tab, _ := table.Get() 39 | //file, err := os.Create("apis/" + table.PackageName + ".go") 40 | //if err != nil { 41 | // t.Error(err) 42 | //} 43 | //defer file.Close() 44 | // 45 | //_ = t1.Execute(file, tab) 46 | t.Log("") 47 | } 48 | -------------------------------------------------------------------------------- /app/system/router/sys_config.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "smart-api/app/system/apis" 5 | "smart-api/common/middleware" 6 | 7 | "github.com/gin-gonic/gin" 8 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 9 | ) 10 | 11 | func init() { 12 | routerCheckRole = append(routerCheckRole, registerSysConfigRouter) 13 | } 14 | 15 | // 需认证的路由代码 16 | func registerSysConfigRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 17 | api := apis.SysConfig{} 18 | r := v1.Group("/config").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/:id", api.Get) 22 | r.POST("", api.Insert) 23 | r.PUT("/:id", api.Update) 24 | r.DELETE("", api.Delete) 25 | } 26 | 27 | r1 := v1.Group("/configKey").Use(authMiddleware.MiddlewareFunc()) 28 | { 29 | r1.GET("/:configKey", api.GetSysConfigByKEYForService) 30 | } 31 | 32 | r2 := v1.Group("/app-config") 33 | { 34 | r2.GET("", api.Get2SysApp) 35 | } 36 | 37 | r3 := v1.Group("/set-config").Use(authMiddleware.MiddlewareFunc()) 38 | { 39 | r3.PUT("", api.Update2Set) 40 | r3.GET("", api.Get2Set) 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /app/smart/router/order_task.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | ) 11 | 12 | func init() { 13 | routerCheckRole = append(routerCheckRole, registerOrderTaskAuthRouter) 14 | //routerNoCheckRole = append(routerNoCheckRole, registerOrderRouter) 15 | } 16 | 17 | // 注册工单类别路由 18 | func registerOrderTaskAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 19 | api := apis.OrderTask{} 20 | 21 | r := v1.Group("/order-task").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 22 | { 23 | // 查询所有的任务 24 | r.GET("", api.GetPage) 25 | // 根据ID 查询 26 | r.GET("/:id", api.Get) 27 | // 创建任务 28 | r.POST("", api.Insert) 29 | // 更新任务信息 30 | r.PUT("", api.Update) 31 | // 删除任务 32 | r.DELETE("", api.Delete) 33 | 34 | // 查询历史任务 35 | r.GET("/history", api.GetHistoryTaskPage) 36 | // 删除历史执行后的任务 37 | r.DELETE("/history", api.DeleteHistoryTask) 38 | 39 | // 查询历史任务日志 40 | r.GET("/history/:id/logs", api.GetTaskLogsByID) 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /template/v4/actions/router_no_check_role.go.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | 6 | "smart-api/app/{{.PackageName}}/middleware" 7 | "smart-api/app/{{.PackageName}}/models" 8 | "smart-api/app/{{.PackageName}}/service/dto" 9 | "smart-api/common/actions" 10 | ) 11 | 12 | func init() { 13 | routerNoCheckRole = append(routerNoCheckRole, register{{.ClassName}}Router) 14 | } 15 | 16 | // 无需认证的路由代码 17 | func register{{.ClassName}}Router(v1 *gin.RouterGroup) { 18 | r := v1.Group("/{{.ModuleName}}") 19 | { 20 | model := &models.{{.ClassName}}{} 21 | r.GET("", actions.IndexAction(model, new(dto.{{.ClassName}}Search), func() interface{} { 22 | list := make([]models.{{.ClassName}}, 0) 23 | return &list 24 | })) 25 | r.GET("/:id", actions.ViewAction(new(dto.{{.ClassName}}ById), nil)) 26 | r.POST("", actions.CreateAction(new(dto.{{.ClassName}}Control))) 27 | r.PUT("/:id", actions.UpdateAction(new(dto.{{.ClassName}}Control))) 28 | r.DELETE("", actions.DeleteAction(new(dto.{{.ClassName}}ById))) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_dict_data.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type DictData struct { 4 | DictCode int `gorm:"primaryKey;autoIncrement;" json:"dictCode" example:"1"` //字典编码 5 | DictSort int `gorm:"" json:"dictSort"` //显示顺序 6 | DictLabel string `gorm:"size:128;" json:"dictLabel"` //数据标签 7 | DictValue string `gorm:"size:255;" json:"dictValue"` //数据键值 8 | DictType string `gorm:"size:64;" json:"dictType"` //字典类型 9 | CssClass string `gorm:"size:128;" json:"cssClass"` // 10 | ListClass string `gorm:"size:128;" json:"listClass"` // 11 | IsDefault string `gorm:"size:8;" json:"isDefault"` // 12 | Status int `gorm:"size:4;" json:"status"` //状态 13 | Default string `gorm:"size:8;" json:"default"` // 14 | Remark string `gorm:"size:255;" json:"remark"` //备注 15 | ControlBy 16 | ModelTime 17 | } 18 | 19 | func (DictData) TableName() string { 20 | return "sys_dict_data" 21 | } 22 | -------------------------------------------------------------------------------- /common/middleware/auth.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "time" 5 | 6 | "github.com/go-admin-team/go-admin-core/sdk/config" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/common/middleware/handler" 9 | ) 10 | 11 | // AuthInit jwt验证new 12 | func AuthInit() (*jwt.GinJWTMiddleware, error) { 13 | timeout := time.Hour 14 | if config.ApplicationConfig.Mode == "dev" { 15 | timeout = time.Duration(876010) * time.Hour 16 | } else { 17 | if config.JwtConfig.Timeout != 0 { 18 | timeout = time.Duration(config.JwtConfig.Timeout) * time.Second 19 | } 20 | } 21 | return jwt.New(&jwt.GinJWTMiddleware{ 22 | Realm: "test zone", 23 | Key: []byte(config.JwtConfig.Secret), 24 | Timeout: timeout, 25 | MaxRefresh: time.Hour, 26 | PayloadFunc: handler.PayloadFunc, 27 | IdentityHandler: handler.IdentityHandler, 28 | Authenticator: handler.Authenticator, 29 | Authorizator: handler.Authorizator, 30 | Unauthorized: handler.Unauthorized, 31 | TokenLookup: "header: Authorization, query: token, cookie: jwt", 32 | TokenHeadName: "Bearer", 33 | TimeFunc: time.Now, 34 | }) 35 | 36 | } 37 | -------------------------------------------------------------------------------- /template/v4/js.go.template: -------------------------------------------------------------------------------- 1 | import request from '@/utils/request' 2 | 3 | // 查询{{.ClassName}}列表 4 | export function list{{.ClassName}}(query) { 5 | return request({ 6 | url: '/api/v1/{{.ModuleName}}', 7 | method: 'get', 8 | params: query 9 | }) 10 | } 11 | 12 | // 查询{{.ClassName}}详细 13 | export function get{{.ClassName}} ({{.PkJsonField}}) { 14 | return request({ 15 | url: '/api/v1/{{.ModuleName}}/' + {{.PkJsonField}}, 16 | method: 'get' 17 | }) 18 | } 19 | 20 | 21 | // 新增{{.ClassName}} 22 | export function add{{.ClassName}}(data) { 23 | return request({ 24 | url: '/api/v1/{{.ModuleName}}', 25 | method: 'post', 26 | data: data 27 | }) 28 | } 29 | 30 | // 修改{{.ClassName}} 31 | export function update{{.ClassName}}(data) { 32 | return request({ 33 | url: '/api/v1/{{.ModuleName}}/'+data.{{.PkJsonField}}, 34 | method: 'put', 35 | data: data 36 | }) 37 | } 38 | 39 | // 删除{{.ClassName}} 40 | export function del{{.ClassName}}(data) { 41 | return request({ 42 | url: '/api/v1/{{.ModuleName}}', 43 | method: 'delete', 44 | data: data 45 | }) 46 | } 47 | 48 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type SysLoginLog struct { 8 | Model 9 | Username string `json:"username" gorm:"type:varchar(128);comment:用户名"` 10 | Status string `json:"status" gorm:"type:varchar(4);comment:状态"` 11 | Ipaddr string `json:"ipaddr" gorm:"type:varchar(255);comment:ip地址"` 12 | LoginLocation string `json:"loginLocation" gorm:"type:varchar(255);comment:归属地"` 13 | Browser string `json:"browser" gorm:"type:varchar(255);comment:浏览器"` 14 | Os string `json:"os" gorm:"type:varchar(255);comment:系统"` 15 | Platform string `json:"platform" gorm:"type:varchar(255);comment:固件"` 16 | LoginTime time.Time `json:"loginTime" gorm:"type:timestamp;comment:登录时间"` 17 | Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` 18 | Msg string `json:"msg" gorm:"type:varchar(255);comment:信息"` 19 | CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` 20 | UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` 21 | ControlBy 22 | } 23 | 24 | func (SysLoginLog) TableName() string { 25 | return "sys_login_log" 26 | } 27 | -------------------------------------------------------------------------------- /common/file_store/initialize.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import "fmt" 4 | 5 | type OXS struct { 6 | // Endpoint 访问域名 7 | Endpoint string 8 | // AccessKeyID AK 9 | AccessKeyID string 10 | // AccessKeySecret AKS 11 | AccessKeySecret string 12 | // BucketName 桶名称 13 | BucketName string 14 | } 15 | 16 | // Setup 配置文件存储driver 17 | func (e *OXS) Setup(driver DriverType, options ...ClientOption) FileStoreType { 18 | fileStoreType := driver 19 | var fileStore FileStoreType 20 | switch fileStoreType { 21 | case AliYunOSS: 22 | fileStore = new(ALiYunOSS) 23 | err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) 24 | if err != nil { 25 | fmt.Println(err) 26 | } 27 | return fileStore 28 | case HuaweiOBS: 29 | fileStore = new(HuaWeiOBS) 30 | err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) 31 | if err != nil { 32 | fmt.Println(err) 33 | } 34 | return fileStore 35 | case QiNiuKodo: 36 | fileStore = new(QiNiuKODO) 37 | err := fileStore.Setup(e.Endpoint, e.AccessKeyID, e.AccessKeySecret, e.BucketName) 38 | if err != nil { 39 | fmt.Println(err) 40 | } 41 | return fileStore 42 | } 43 | 44 | return nil 45 | } 46 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_menu.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysMenu struct { 4 | MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"` 5 | MenuName string `json:"menuName" gorm:"size:128;"` 6 | Title string `json:"title" gorm:"size:128;"` 7 | Icon string `json:"icon" gorm:"size:128;"` 8 | Path string `json:"path" gorm:"size:128;"` 9 | Paths string `json:"paths" gorm:"size:128;"` 10 | MenuType string `json:"menuType" gorm:"size:1;"` 11 | Action string `json:"action" gorm:"size:16;"` 12 | Permission string `json:"permission" gorm:"size:255;"` 13 | ParentId int `json:"parentId" gorm:"size:11;"` 14 | NoCache bool `json:"noCache" gorm:"size:8;"` 15 | Breadcrumb string `json:"breadcrumb" gorm:"size:255;"` 16 | Component string `json:"component" gorm:"size:255;"` 17 | Sort int `json:"sort" gorm:"size:4;"` 18 | Visible string `json:"visible" gorm:"size:1;"` 19 | IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"` 20 | SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"` 21 | ControlBy 22 | ModelTime 23 | } 24 | 25 | func (SysMenu) TableName() string { 26 | return "sys_menu" 27 | } -------------------------------------------------------------------------------- /common/models/user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | 6 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 7 | ) 8 | 9 | // BaseUser 密码登录基础用户 10 | type BaseUser struct { 11 | Username string `json:"username" gorm:"type:varchar(100);comment:用户名"` 12 | Salt string `json:"-" gorm:"type:varchar(255);comment:加盐;<-"` 13 | PasswordHash string `json:"-" gorm:"type:varchar(128);comment:密码hash;<-"` 14 | Password string `json:"password" gorm:"-"` 15 | } 16 | 17 | // SetPassword 设置密码 18 | func (u *BaseUser) SetPassword(value string) { 19 | u.Password = value 20 | u.generateSalt() 21 | u.PasswordHash = u.GetPasswordHash() 22 | } 23 | 24 | // GetPasswordHash 获取密码hash 25 | func (u *BaseUser) GetPasswordHash() string { 26 | passwordHash, err := pkg.SetPassword(u.Password, u.Salt) 27 | if err != nil { 28 | return "" 29 | } 30 | return passwordHash 31 | } 32 | 33 | // generateSalt 生成加盐值 34 | func (u *BaseUser) generateSalt() { 35 | u.Salt = pkg.GenerateRandomKey16() 36 | } 37 | 38 | // Verify 验证密码 39 | func (u *BaseUser) Verify(db *gorm.DB, tableName string) bool { 40 | db.Table(tableName).Where("username = ?", u.Username).First(u) 41 | return u.GetPasswordHash() == u.PasswordHash 42 | } 43 | -------------------------------------------------------------------------------- /common/middleware/handler/login.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | log "github.com/go-admin-team/go-admin-core/logger" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 6 | "gorm.io/gorm" 7 | ) 8 | 9 | type Login struct { 10 | Username string `form:"UserName" json:"username" binding:"required"` 11 | Password string `form:"Password" json:"password" binding:"required"` 12 | Source string `json:"source" comment:"用户来源" vd:"len($)>0" default:"1"` 13 | Code string `form:"Code" json:"code" binding:"required"` 14 | UUID string `form:"UUID" json:"uuid" binding:"required"` 15 | } 16 | 17 | func (u *Login) GetUser(tx *gorm.DB) (user SysUser, role SysRole, err error) { 18 | err = tx.Table("sys_user").Where("username = ? and status = '2'", u.Username).First(&user).Error 19 | if err != nil { 20 | log.Errorf("get user error, %s", err.Error()) 21 | return 22 | } 23 | _, err = pkg.CompareHashAndPassword(user.Password, u.Password) 24 | if err != nil { 25 | log.Errorf("user login error, %s", err.Error()) 26 | return 27 | } 28 | err = tx.Table("sys_role").Where("role_id = ? ", user.RoleId).First(&role).Error 29 | if err != nil { 30 | log.Errorf("get role error, %s", err.Error()) 31 | return 32 | } 33 | return 34 | } 35 | -------------------------------------------------------------------------------- /app/system/models/sys_dept.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "smart-api/common/models" 4 | 5 | type SysDept struct { 6 | DeptId int `json:"deptId" gorm:"primaryKey;autoIncrement;"` //部门编码 7 | ParentId int `json:"parentId" gorm:""` //上级部门 8 | DeptPath string `json:"deptPath" gorm:"size:255;"` // 9 | DeptName string `json:"deptName" gorm:"size:128;"` //部门名称 10 | Sort int `json:"sort" gorm:"size:4;"` //排序 11 | Leader string `json:"leader" gorm:"size:128;"` //负责人 12 | Phone string `json:"phone" gorm:"size:11;"` //手机 13 | Email string `json:"email" gorm:"size:64;"` //邮箱 14 | Status int `json:"status" gorm:"size:4;"` //状态 15 | models.ControlBy 16 | models.ModelTime 17 | DataScope string `json:"dataScope" gorm:"-"` 18 | Params string `json:"params" gorm:"-"` 19 | Children []SysDept `json:"children" gorm:"-"` 20 | } 21 | 22 | func (*SysDept) TableName() string { 23 | return "sys_dept" 24 | } 25 | 26 | func (e *SysDept) Generate() models.ActiveRecord { 27 | o := *e 28 | return &o 29 | } 30 | 31 | func (e *SysDept) GetId() interface{} { 32 | return e.DeptId 33 | } 34 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/flow_manage.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/16 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type StrucTure map[string]interface{} 10 | type FlowSliceInt []int 11 | 12 | type FlowManage struct { 13 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 14 | Name string `gorm:"column:name;type:varchar(100)" json:"name"` // 流程名称 15 | CategoryID uint `gorm:"column:categoryId" json:"categoryId"` 16 | Notice FlowSliceInt `gorm:"column:notice;type:json" json:"notice"` // 变为json切片 17 | Comments bool `gorm:"column:comments;default:false" json:"comments"` 18 | Ratings bool `gorm:"column:ratings;default:false" json:"ratings"` 19 | Description string `gorm:"description:des;type:varchar(512)" json:"description"` 20 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 21 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 22 | StrucTure StrucTure `gorm:"column:structure;type:json" json:"structure"` 23 | models.ControlBy 24 | models.ModelTime 25 | } 26 | 27 | func (*FlowManage) TableName() string { 28 | return "flow_manage" 29 | } 30 | -------------------------------------------------------------------------------- /app/system/models/sys_dict_data.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "smart-api/common/models" 5 | ) 6 | 7 | type SysDictData struct { 8 | DictCode int `json:"dictCode" gorm:"primaryKey;column:dict_code;autoIncrement;comment:主键编码"` 9 | DictSort int `json:"dictSort" gorm:"size:20;comment:DictSort"` 10 | DictLabel string `json:"dictLabel" gorm:"size:128;comment:DictLabel"` 11 | DictValue string `json:"dictValue" gorm:"size:255;comment:DictValue"` 12 | DictType string `json:"dictType" gorm:"size:64;comment:DictType"` 13 | CssClass string `json:"cssClass" gorm:"size:128;comment:CssClass"` 14 | ListClass string `json:"listClass" gorm:"size:128;comment:ListClass"` 15 | IsDefault string `json:"isDefault" gorm:"size:8;comment:IsDefault"` 16 | Status int `json:"status" gorm:"size:4;comment:Status"` 17 | Default string `json:"default" gorm:"size:8;comment:Default"` 18 | Remark string `json:"remark" gorm:"size:255;comment:Remark"` 19 | models.ControlBy 20 | models.ModelTime 21 | } 22 | 23 | func (*SysDictData) TableName() string { 24 | return "sys_dict_data" 25 | } 26 | 27 | func (e *SysDictData) Generate() models.ActiveRecord { 28 | o := *e 29 | return &o 30 | } 31 | 32 | func (e *SysDictData) GetId() interface{} { 33 | return e.DictCode 34 | } 35 | -------------------------------------------------------------------------------- /app/smart/models/order_items.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/13 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type OrderItems struct { 10 | ID uint `gorm:"primaryKey" json:"id"` 11 | Title string `gorm:"column:title;type:varchar(50)" json:"title"` // 订单项标题 12 | BindTempLate string `gorm:"column:bindTempLate;type:varchar(50)" json:"bindTempLate"` // 绑定模板 13 | Description string `gorm:"column:description;type:varchar(256)" json:"description"` // 订单项描述 14 | Icon string `gorm:"column:icon;type:varchar(50)" json:"icon"` // 订单项图标 15 | CategoryID uint `gorm:"column:categoryId" json:"categoryId"` 16 | Link string `gorm:"column:link;type:varchar(256)" json:"link"` // 连接到网页 17 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 18 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 19 | models.ControlBy 20 | models.ModelTime 21 | } 22 | 23 | func (*OrderItems) TableName() string { 24 | return "order_items" 25 | } 26 | 27 | func (e *OrderItems) Generate() models.ActiveRecord { 28 | o := *e 29 | return &o 30 | } 31 | 32 | func (e *OrderItems) GetId() interface{} { 33 | return e.ID 34 | } 35 | -------------------------------------------------------------------------------- /cmd/cobra.go: -------------------------------------------------------------------------------- 1 | package cmd 2 | 3 | import ( 4 | "errors" 5 | "fmt" 6 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 7 | "os" 8 | "smart-api/cmd/api" 9 | "smart-api/cmd/migrate" 10 | "smart-api/common/global" 11 | 12 | "github.com/spf13/cobra" 13 | ) 14 | 15 | var rootCmd = &cobra.Command{ 16 | Use: "smart", 17 | Short: "smart", 18 | SilenceUsage: true, 19 | Long: `smart`, 20 | Args: func(cmd *cobra.Command, args []string) error { 21 | if len(args) < 1 { 22 | tip() 23 | return errors.New(pkg.Red("requires at least one arg")) 24 | } 25 | return nil 26 | }, 27 | PersistentPreRunE: func(*cobra.Command, []string) error { return nil }, 28 | Run: func(cmd *cobra.Command, args []string) { 29 | tip() 30 | }, 31 | } 32 | 33 | func tip() { 34 | usageStr := `欢迎使用 ` + pkg.Green(`smart `+global.Version) + ` 可以使用 ` + pkg.Red(`-h`) + ` 查看命令` 35 | usageStr1 := `https://blog.csdn.net/weixin_43798031?spm=1000.2115.3001.5343` 36 | fmt.Printf("%s\n", usageStr) 37 | fmt.Printf("%s\n", usageStr1) 38 | } 39 | 40 | func init() { 41 | rootCmd.AddCommand(api.StartCmd) 42 | rootCmd.AddCommand(migrate.StartCmd) 43 | } 44 | 45 | // Execute : apply commands 46 | func Execute() { 47 | if err := rootCmd.Execute(); err != nil { 48 | os.Exit(-1) 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /app/system/router/sys_dict.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/system/apis" 7 | "smart-api/common/middleware" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, registerDictRouter) 12 | } 13 | 14 | func registerDictRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 15 | dictApi := apis.SysDictType{} 16 | dataApi := apis.SysDictData{} 17 | dicts := v1.Group("/dict").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 18 | { 19 | 20 | dicts.GET("/data", dataApi.GetPage) 21 | dicts.GET("/data/:dictCode", dataApi.Get) 22 | dicts.POST("/data", dataApi.Insert) 23 | dicts.PUT("/data/:dictCode", dataApi.Update) 24 | dicts.DELETE("/data", dataApi.Delete) 25 | 26 | dicts.GET("/type-option-select", dictApi.GetAll) 27 | dicts.GET("/type", dictApi.GetPage) 28 | dicts.GET("/type/:id", dictApi.Get) 29 | dicts.POST("/type", dictApi.Insert) 30 | dicts.PUT("/type/:id", dictApi.Update) 31 | dicts.DELETE("/type", dictApi.Delete) 32 | } 33 | opSelect := v1.Group("/dict-data").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 34 | { 35 | opSelect.GET("/option-select", dataApi.GetAll) 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /app/system/router/sys_user.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/system/apis" 7 | "smart-api/common/actions" 8 | "smart-api/common/middleware" 9 | ) 10 | 11 | func init() { 12 | routerCheckRole = append(routerCheckRole, registerSysUserRouter) 13 | } 14 | 15 | // 需认证的路由代码 16 | func registerSysUserRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 17 | api := apis.SysUser{} 18 | r := v1.Group("/sys-user").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction()) 19 | { 20 | r.GET("", api.GetPage) 21 | r.GET("/specify-user", api.GetSpecify) 22 | r.GET("/:id", api.Get) 23 | r.POST("", api.Insert) 24 | r.PUT("", api.Update) 25 | r.DELETE("", api.Delete) 26 | } 27 | 28 | user := v1.Group("/user").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()).Use(actions.PermissionAction()) 29 | { 30 | user.GET("/profile", api.GetProfile) 31 | user.POST("/avatar", api.InsetAvatar) 32 | user.PUT("/pwd/set", api.UpdatePwd) 33 | user.PUT("/pwd/reset", api.ResetPwd) 34 | user.PUT("/status", api.UpdateStatus) 35 | } 36 | v1auth := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 37 | { 38 | v1auth.GET("/getinfo", api.GetInfo) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /common/actions/create.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/go-admin-team/go-admin-core/sdk/api" 8 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 11 | 12 | "smart-api/common/dto" 13 | "smart-api/common/models" 14 | ) 15 | 16 | // CreateAction 通用新增动作 17 | func CreateAction(control dto.Control) gin.HandlerFunc { 18 | return func(c *gin.Context) { 19 | log := api.GetRequestLogger(c) 20 | db, err := pkg.GetOrm(c) 21 | if err != nil { 22 | log.Error(err) 23 | return 24 | } 25 | 26 | //新增操作 27 | req := control.Generate() 28 | err = req.Bind(c) 29 | if err != nil { 30 | response.Error(c, http.StatusUnprocessableEntity, err, err.Error()) 31 | return 32 | } 33 | var object models.ActiveRecord 34 | object, err = req.GenerateM() 35 | if err != nil { 36 | response.Error(c, 500, err, "模型生成失败") 37 | return 38 | } 39 | object.SetCreateBy(user.GetUserId(c)) 40 | err = db.WithContext(c).Create(object).Error 41 | if err != nil { 42 | log.Errorf("Create error: %s", err) 43 | response.Error(c, 500, err, "创建失败") 44 | return 45 | } 46 | response.OK(c, object.GetId(), "创建成功") 47 | c.Next() 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /common/middleware/customerror.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "runtime" 7 | "strconv" 8 | "strings" 9 | "time" 10 | 11 | "github.com/gin-gonic/gin" 12 | ) 13 | 14 | func CustomError(c *gin.Context) { 15 | defer func() { 16 | if err := recover(); err != nil { 17 | 18 | if c.IsAborted() { 19 | c.Status(200) 20 | } 21 | switch errStr := err.(type) { 22 | case string: 23 | p := strings.Split(errStr, "#") 24 | if len(p) == 3 && p[0] == "CustomError" { 25 | statusCode, e := strconv.Atoi(p[1]) 26 | if e != nil { 27 | break 28 | } 29 | c.Status(statusCode) 30 | fmt.Println( 31 | time.Now().Format("2006-01-02 15:04:05"), 32 | "[ERROR]", 33 | c.Request.Method, 34 | c.Request.URL, 35 | statusCode, 36 | c.Request.RequestURI, 37 | c.ClientIP(), 38 | p[2], 39 | ) 40 | c.JSON(http.StatusOK, gin.H{ 41 | "code": statusCode, 42 | "msg": p[2], 43 | }) 44 | } else { 45 | c.JSON(http.StatusOK, gin.H{ 46 | "code": 500, 47 | "msg": errStr, 48 | }) 49 | } 50 | case runtime.Error: 51 | c.JSON(http.StatusOK, gin.H{ 52 | "code": 500, 53 | "msg": errStr.Error(), 54 | }) 55 | default: 56 | panic(err) 57 | } 58 | } 59 | }() 60 | c.Next() 61 | } 62 | -------------------------------------------------------------------------------- /common/file_store/oss.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "github.com/aliyun/aliyun-oss-go-sdk/oss" 5 | "log" 6 | ) 7 | 8 | type ALiYunOSS struct { 9 | Client interface{} 10 | BucketName string 11 | } 12 | 13 | //Setup 装载 14 | //endpoint sss 15 | func (e *ALiYunOSS) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error { 16 | client, err := oss.New(endpoint, accessKeyID, accessKeySecret) 17 | if err != nil { 18 | log.Println("Error:", err) 19 | return err 20 | } 21 | e.Client = client 22 | e.BucketName = BucketName 23 | 24 | return nil 25 | } 26 | 27 | // UpLoad 文件上传 28 | func (e *ALiYunOSS) UpLoad(yourObjectName string, localFile interface{}) error { 29 | // 获取存储空间。 30 | bucket, err := e.Client.(*oss.Client).Bucket(e.BucketName) 31 | if err != nil { 32 | log.Println("Error:", err) 33 | return err 34 | } 35 | // 设置分片大小为100 KB,指定分片上传并发数为3,并开启断点续传上传。 36 | // 其中与objectKey是同一概念,表示断点续传上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg。 37 | // "LocalFile"为filePath,100*1024为partSize。 38 | err = bucket.UploadFile(yourObjectName, localFile.(string), 100*1024, oss.Routines(3), oss.Checkpoint(true, "")) 39 | if err != nil { 40 | log.Println("Error:", err) 41 | return err 42 | } 43 | return nil 44 | } 45 | 46 | func (e *ALiYunOSS) GetTempToken() (string, error) { 47 | return "", nil 48 | } 49 | -------------------------------------------------------------------------------- /cmd/migrate/migration/version/1653638869132_migrate.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "runtime" 6 | "smart-api/cmd/migrate/migration/models" 7 | common "smart-api/common/models" 8 | "strconv" 9 | 10 | "smart-api/cmd/migrate/migration" 11 | ) 12 | 13 | func init() { 14 | _, fileName, _, _ := runtime.Caller(0) 15 | migration.Migrate.SetVersion(migration.GetFilename(fileName), _1653638869132Test) 16 | } 17 | 18 | func _1653638869132Test(db *gorm.DB, version string) error { 19 | return db.Transaction(func(tx *gorm.DB) error { 20 | var list []models.SysMenu 21 | err := tx.Model(&models.SysMenu{}).Order("parent_id,menu_id").Find(&list).Error 22 | if err != nil { 23 | return err 24 | } 25 | for _, v := range list { 26 | if v.ParentId == 0 { 27 | v.Paths = "/0/" + strconv.Itoa(v.MenuId) 28 | } else { 29 | var e models.SysMenu 30 | err = tx.Model(&models.SysMenu{}).Where("menu_id=?", v.ParentId).First(&e).Error 31 | if err != nil { 32 | if err == gorm.ErrRecordNotFound { 33 | continue 34 | } 35 | return err 36 | } 37 | v.Paths = e.Paths + "/" + strconv.Itoa(v.MenuId) 38 | } 39 | err = tx.Model(&v).Update("paths", v.Paths).Error 40 | if err != nil { 41 | return err 42 | } 43 | } 44 | return tx.Create(&common.Migration{ 45 | Version: version, 46 | }).Error 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /template/v4/actions/router_check_role.go.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | 7 | "smart-api/app/{{.PackageName}}/models" 8 | "smart-api/app/{{.PackageName}}/service/dto" 9 | "smart-api/common/actions" 10 | "smart-api/common/middleware" 11 | ) 12 | 13 | func init() { 14 | routerCheckRole = append(routerCheckRole, register{{.ClassName}}Router) 15 | } 16 | 17 | // 需认证的路由代码 18 | func register{{.ClassName}}Router(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 19 | r := v1.Group("/{{.ModuleName}}").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 20 | { 21 | model := &models.{{.ClassName}}{} 22 | r.GET("", actions.PermissionAction(), actions.IndexAction(model, new(dto.{{.ClassName}}Search), func() interface{} { 23 | list := make([]models.{{.ClassName}}, 0) 24 | return &list 25 | })) 26 | r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto.{{.ClassName}}ById), nil)) 27 | r.POST("", actions.CreateAction(new(dto.{{.ClassName}}Control))) 28 | r.PUT("/:id", actions.PermissionAction(), actions.UpdateAction(new(dto.{{.ClassName}}Control))) 29 | r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto.{{.ClassName}}ById))) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /common/storage/initialize.go: -------------------------------------------------------------------------------- 1 | /* 2 | * @Author: lwnmengjing 3 | * @Date: 2021/6/10 3:39 下午 4 | * @Last Modified by: lwnmengjing 5 | * @Last Modified time: 2021/6/10 3:39 下午 6 | */ 7 | 8 | package storage 9 | 10 | import ( 11 | "log" 12 | 13 | "github.com/go-admin-team/go-admin-core/sdk" 14 | "github.com/go-admin-team/go-admin-core/sdk/config" 15 | "github.com/go-admin-team/go-admin-core/sdk/pkg/captcha" 16 | ) 17 | 18 | // Setup 配置storage组件 19 | func Setup() { 20 | //4. 设置缓存 21 | cacheAdapter, err := config.CacheConfig.Setup() 22 | if err != nil { 23 | log.Fatalf("cache setup error, %s\n", err.Error()) 24 | } 25 | sdk.Runtime.SetCacheAdapter(cacheAdapter) 26 | //5. 设置验证码store 27 | captcha.SetStore(captcha.NewCacheStore(cacheAdapter, 600)) 28 | 29 | //6. 设置队列 30 | if !config.QueueConfig.Empty() { 31 | if q := sdk.Runtime.GetQueueAdapter(); q != nil { 32 | q.Shutdown() 33 | } 34 | queueAdapter, err := config.QueueConfig.Setup() 35 | if err != nil { 36 | log.Fatalf("queue setup error, %s\n", err.Error()) 37 | } 38 | sdk.Runtime.SetQueueAdapter(queueAdapter) 39 | defer func() { 40 | go queueAdapter.Run() 41 | }() 42 | } 43 | 44 | //7. 设置分布式锁 45 | if !config.LockerConfig.Empty() { 46 | lockerAdapter, err := config.LockerConfig.Setup() 47 | if err != nil { 48 | log.Fatalf("locker setup error, %s\n", err.Error()) 49 | } 50 | sdk.Runtime.SetLockerAdapter(lockerAdapter) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /common/utils/encrypt.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/8/30 19:19 3 | package utils 4 | 5 | import ( 6 | "crypto/aes" 7 | "crypto/cipher" 8 | "crypto/rand" 9 | "encoding/base64" 10 | "errors" 11 | "io" 12 | ) 13 | 14 | // Encrypt encrypts plain text string into base64 encoded string 15 | func Encrypt(plainText, key string) (string, error) { 16 | block, err := aes.NewCipher([]byte(key)) 17 | if err != nil { 18 | return "", err 19 | } 20 | ciphertext := make([]byte, aes.BlockSize+len(plainText)) 21 | iv := ciphertext[:aes.BlockSize] 22 | if _, err := io.ReadFull(rand.Reader, iv); err != nil { 23 | return "", err 24 | } 25 | stream := cipher.NewCFBEncrypter(block, iv) 26 | stream.XORKeyStream(ciphertext[aes.BlockSize:], []byte(plainText)) 27 | return base64.URLEncoding.EncodeToString(ciphertext), nil 28 | } 29 | 30 | // Decrypt decrypts base64 encoded string into plain text string 31 | func Decrypt(cipherText, key string) (string, error) { 32 | ciphertext, _ := base64.URLEncoding.DecodeString(cipherText) 33 | block, err := aes.NewCipher([]byte(key)) 34 | if err != nil { 35 | return "", err 36 | } 37 | if len(ciphertext) < aes.BlockSize { 38 | return "", errors.New("ciphertext too short") 39 | } 40 | iv := ciphertext[:aes.BlockSize] 41 | ciphertext = ciphertext[aes.BlockSize:] 42 | stream := cipher.NewCFBDecrypter(block, iv) 43 | stream.XORKeyStream(ciphertext, ciphertext) 44 | return string(ciphertext), nil 45 | } 46 | -------------------------------------------------------------------------------- /app/jobs/router/sys_job.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/jobs/apis" 7 | models2 "smart-api/app/jobs/models" 8 | dto2 "smart-api/app/jobs/service/dto" 9 | "smart-api/common/actions" 10 | "smart-api/common/middleware" 11 | ) 12 | 13 | func init() { 14 | routerCheckRole = append(routerCheckRole, registerSysJobRouter) 15 | } 16 | 17 | // 需认证的路由代码 18 | func registerSysJobRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 19 | 20 | r := v1.Group("/sysjob").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 21 | { 22 | sysJob := &models2.SysJob{} 23 | r.GET("", actions.PermissionAction(), actions.IndexAction(sysJob, new(dto2.SysJobSearch), func() interface{} { 24 | list := make([]models2.SysJob, 0) 25 | return &list 26 | })) 27 | r.GET("/:id", actions.PermissionAction(), actions.ViewAction(new(dto2.SysJobById), func() interface{} { 28 | return &dto2.SysJobItem{} 29 | })) 30 | r.POST("", actions.CreateAction(new(dto2.SysJobControl))) 31 | r.PUT("", actions.PermissionAction(), actions.UpdateAction(new(dto2.SysJobControl))) 32 | r.DELETE("", actions.PermissionAction(), actions.DeleteAction(new(dto2.SysJobById))) 33 | } 34 | sysJob := apis.SysJob{} 35 | 36 | v1.GET("/job/remove/:id", sysJob.RemoveJobForService) 37 | v1.GET("/job/start/:id", sysJob.StartJobForService) 38 | } 39 | -------------------------------------------------------------------------------- /static/form-generator/preview.html: -------------------------------------------------------------------------------- 1 | form-generator-preview
-------------------------------------------------------------------------------- /cmd/migrate/migration/version/1599190683659_tables.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "github.com/go-admin-team/go-admin-core/sdk/config" 5 | "runtime" 6 | 7 | "smart-api/cmd/migrate/migration" 8 | "smart-api/cmd/migrate/migration/models" 9 | common "smart-api/common/models" 10 | 11 | "gorm.io/gorm" 12 | ) 13 | 14 | func init() { 15 | _, fileName, _, _ := runtime.Caller(0) 16 | migration.Migrate.SetVersion(migration.GetFilename(fileName), _1599190683659Tables) 17 | } 18 | 19 | func _1599190683659Tables(db *gorm.DB, version string) error { 20 | return db.Transaction(func(tx *gorm.DB) error { 21 | if config.DatabaseConfig.Driver == "mysql" { 22 | tx = tx.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4") 23 | } 24 | err := tx.Migrator().AutoMigrate( 25 | new(models.SysDept), 26 | new(models.SysConfig), 27 | new(models.SysTables), 28 | new(models.SysColumns), 29 | new(models.SysMenu), 30 | new(models.SysLoginLog), 31 | new(models.SysOperaLog), 32 | new(models.SysRoleDept), 33 | new(models.SysUser), 34 | new(models.SysRole), 35 | new(models.SysPost), 36 | new(models.DictData), 37 | new(models.DictType), 38 | new(models.SysJob), 39 | new(models.SysConfig), 40 | new(models.SysApi), 41 | new(models.TbDemo), 42 | ) 43 | if err != nil { 44 | return err 45 | } 46 | 47 | return tx.Create(&common.Migration{ 48 | Version: version, 49 | }).Error 50 | }) 51 | } 52 | -------------------------------------------------------------------------------- /cmd/migrate/migration/init.go: -------------------------------------------------------------------------------- 1 | package migration 2 | 3 | import ( 4 | "log" 5 | "path/filepath" 6 | "sort" 7 | "sync" 8 | 9 | "gorm.io/gorm" 10 | ) 11 | 12 | var Migrate = &Migration{ 13 | version: make(map[string]func(db *gorm.DB, version string) error), 14 | } 15 | 16 | type Migration struct { 17 | db *gorm.DB 18 | version map[string]func(db *gorm.DB, version string) error 19 | mutex sync.Mutex 20 | } 21 | 22 | func (e *Migration) GetDb() *gorm.DB { 23 | return e.db 24 | } 25 | 26 | func (e *Migration) SetDb(db *gorm.DB) { 27 | e.db = db 28 | } 29 | 30 | func (e *Migration) SetVersion(k string, f func(db *gorm.DB, version string) error) { 31 | e.mutex.Lock() 32 | defer e.mutex.Unlock() 33 | e.version[k] = f 34 | } 35 | 36 | func (e *Migration) Migrate() { 37 | versions := make([]string, 0) 38 | for k := range e.version { 39 | versions = append(versions, k) 40 | } 41 | if !sort.StringsAreSorted(versions) { 42 | sort.Strings(versions) 43 | } 44 | var err error 45 | var count int64 46 | for _, v := range versions { 47 | err = e.db.Table("sys_migration").Where("version = ?", v).Count(&count).Error 48 | if err != nil { 49 | log.Fatalln(err) 50 | } 51 | if count > 0 { 52 | log.Println(count) 53 | count = 0 54 | continue 55 | } 56 | err = (e.version[v])(e.db.Debug(), v) 57 | if err != nil { 58 | log.Fatalln(err) 59 | } 60 | } 61 | } 62 | 63 | func GetFilename(s string) string { 64 | s = filepath.Base(s) 65 | return s[:13] 66 | } 67 | -------------------------------------------------------------------------------- /app/jobs/examples.go: -------------------------------------------------------------------------------- 1 | package jobs 2 | 3 | import ( 4 | "fmt" 5 | "github.com/go-admin-team/go-admin-core/sdk" 6 | "smart-api/common/utils" 7 | "time" 8 | ) 9 | 10 | // InitJob 11 | // 需要将定义的struct 添加到字典中; 12 | // 字典 key 可以配置到 自动任务 调用目标 中; 13 | func InitJob() { 14 | host := "" 15 | db := sdk.Runtime.GetDbByKey(host) 16 | 17 | jobList = map[string]JobExec{ 18 | "ExamplesOne": ExamplesOne{}, 19 | "CheckAllMachines": CheckAllMachinesJob{ 20 | MachineService: &utils.MachineService{ 21 | Orm: db, // 使用指定的 DB 实例 22 | }, 23 | }, 24 | } 25 | } 26 | 27 | // ExamplesOne 28 | // 新添加的job 必须按照以下格式定义,并实现Exec函数 29 | type ExamplesOne struct { 30 | } 31 | 32 | // CheckAllMachinesJob 用于检查所有机器状态的定时任务 33 | type CheckAllMachinesJob struct { 34 | MachineService *utils.MachineService // 传入你定义的服务 35 | } 36 | 37 | func (t CheckAllMachinesJob) Exec(arg interface{}) error { 38 | // 调用 CheckAllMachines 方法 39 | t.MachineService.CheckAllMachines() 40 | return nil 41 | } 42 | 43 | func (t ExamplesOne) Exec(arg interface{}) error { 44 | str := time.Now().Format(timeFormat) + " [INFO] JobCore ExamplesOne exec success" 45 | // TODO: 这里需要注意 Examples 传入参数是 string 所以 arg.(string);请根据对应的类型进行转化; 46 | switch arg.(type) { 47 | 48 | case string: 49 | if arg.(string) != "" { 50 | fmt.Println("string", arg.(string)) 51 | fmt.Println(str, arg.(string)) 52 | } else { 53 | fmt.Println("arg is nil") 54 | fmt.Println(str, "arg is nil") 55 | } 56 | break 57 | } 58 | 59 | return nil 60 | } 61 | -------------------------------------------------------------------------------- /common/file_store/obs.go: -------------------------------------------------------------------------------- 1 | package file_store 2 | 3 | import ( 4 | "fmt" 5 | "github.com/huaweicloud/huaweicloud-sdk-go-obs/obs" 6 | "log" 7 | ) 8 | 9 | type HuaWeiOBS struct { 10 | Client interface{} 11 | BucketName string 12 | } 13 | 14 | func (e *HuaWeiOBS) Setup(endpoint, accessKeyID, accessKeySecret, BucketName string, options ...ClientOption) error { 15 | // 创建ObsClient结构体 16 | client, err := obs.New(accessKeyID, accessKeySecret, endpoint) 17 | if err != nil { 18 | log.Println("Error:", err) 19 | return err 20 | } 21 | e.Client = client 22 | e.BucketName = BucketName 23 | return nil 24 | } 25 | 26 | // UpLoad 文件上传 27 | // yourObjectName 文件路径名称,与objectKey是同一概念,表示断点续传上传文件到OSS时需要指定包含文件后缀在内的完整路径,例如abc/efg/123.jpg 28 | func (e *HuaWeiOBS) UpLoad(yourObjectName string, localFile interface{}) error { 29 | // 获取存储空间。 30 | input := &obs.PutFileInput{} 31 | input.Bucket = e.BucketName 32 | input.Key = yourObjectName 33 | input.SourceFile = localFile.(string) 34 | output, err := e.Client.(*obs.ObsClient).PutFile(input) 35 | 36 | if err == nil { 37 | fmt.Printf("RequestId:%s\n", output.RequestId) 38 | fmt.Printf("ETag:%s, StorageClass:%s\n", output.ETag, output.StorageClass) 39 | } else { 40 | if obsError, ok := err.(obs.ObsError); ok { 41 | fmt.Println(obsError.Code) 42 | fmt.Println(obsError.Message) 43 | } else { 44 | fmt.Println(err) 45 | } 46 | } 47 | return nil 48 | } 49 | 50 | func (e *HuaWeiOBS) GetTempToken() (string, error) { 51 | return "", nil 52 | } 53 | -------------------------------------------------------------------------------- /app/system/models/initdb.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "gorm.io/gorm" 6 | "io/ioutil" 7 | "log" 8 | "smart-api/common/global" 9 | "strings" 10 | ) 11 | 12 | func InitDb(db *gorm.DB) (err error) { 13 | filePath := "config/db.sql" 14 | err = ExecSql(db, filePath) 15 | if global.Driver == "postgres" { 16 | filePath = "config/pg.sql" 17 | err = ExecSql(db, filePath) 18 | } 19 | return err 20 | } 21 | 22 | func ExecSql(db *gorm.DB, filePath string) error { 23 | sql, err := Ioutil(filePath) 24 | if err != nil { 25 | fmt.Println("数据库基础数据初始化脚本读取失败!原因:", err.Error()) 26 | return err 27 | } 28 | sqlList := strings.Split(sql, ";") 29 | for i := 0; i < len(sqlList)-1; i++ { 30 | if strings.Contains(sqlList[i], "--") { 31 | fmt.Println(sqlList[i]) 32 | continue 33 | } 34 | sql := strings.Replace(sqlList[i]+";", "\n", "", -1) 35 | sql = strings.TrimSpace(sql) 36 | if err = db.Exec(sql).Error; err != nil { 37 | log.Printf("error sql: %s", sql) 38 | if !strings.Contains(err.Error(), "Query was empty") { 39 | return err 40 | } 41 | } 42 | } 43 | return nil 44 | } 45 | 46 | func Ioutil(filePath string) (string, error) { 47 | if contents, err := ioutil.ReadFile(filePath); err == nil { 48 | //因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符 49 | result := strings.Replace(string(contents), "\n", "", 1) 50 | fmt.Println("Use ioutil.ReadFile to read a file:", result) 51 | return result, nil 52 | } else { 53 | return "", err 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /common/middleware/handler/user.go: -------------------------------------------------------------------------------- 1 | package handler 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "smart-api/common/models" 6 | ) 7 | 8 | type SysUser struct { 9 | UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"` 10 | Username string `json:"username" gorm:"size:64;comment:用户名"` 11 | Password string `json:"-" gorm:"size:128;comment:密码"` 12 | NickName string `json:"nickName" gorm:"size:128;comment:昵称"` 13 | Phone string `json:"phone" gorm:"size:11;comment:手机号"` 14 | RoleId int `json:"roleId" gorm:"size:20;comment:角色ID"` 15 | Salt string `json:"-" gorm:"size:255;comment:加盐"` 16 | Avatar string `json:"avatar" gorm:"size:255;comment:头像"` 17 | Sex string `json:"sex" gorm:"size:255;comment:性别"` 18 | Email string `json:"email" gorm:"size:128;comment:邮箱"` 19 | DeptId int `json:"deptId" gorm:"size:20;comment:部门"` 20 | PostId int `json:"postId" gorm:"size:20;comment:岗位"` 21 | Remark string `json:"remark" gorm:"size:255;comment:备注"` 22 | Status string `json:"status" gorm:"size:4;comment:状态"` 23 | DeptIds []int `json:"deptIds" gorm:"-"` 24 | PostIds []int `json:"postIds" gorm:"-"` 25 | RoleIds []int `json:"roleIds" gorm:"-"` 26 | //Dept *SysDept `json:"dept"` 27 | models.ControlBy 28 | models.ModelTime 29 | } 30 | 31 | func (*SysUser) TableName() string { 32 | return "sys_user" 33 | } 34 | 35 | func (e *SysUser) AfterFind(_ *gorm.DB) error { 36 | e.DeptIds = []int{e.DeptId} 37 | e.PostIds = []int{e.PostId} 38 | e.RoleIds = []int{e.RoleId} 39 | return nil 40 | } 41 | -------------------------------------------------------------------------------- /common/utils/tasklog.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/10/22 16:41 3 | package utils 4 | 5 | import ( 6 | "fmt" 7 | "os" 8 | "time" 9 | ) 10 | 11 | // TaskLogger 用于记录任务执行的日志 12 | type TaskLogger struct { 13 | logFile *os.File 14 | } 15 | 16 | // NewTaskLogger 创建一个新的 TaskLogger 实例 17 | func NewTaskLogger(orderTitle string, hisTaskUUId string) (*TaskLogger, error) { 18 | // 指定日志文件路径 19 | logDir := "./logs/task-log" 20 | 21 | // 获取当前日期并格式化为字符串 22 | currentDateTime := time.Now().Format("200601021504") // YYYYMMDDHHMM 格式 23 | 24 | logFilePath := fmt.Sprintf("%s/%s-%s_%s.log", logDir, orderTitle, currentDateTime, hisTaskUUId) 25 | 26 | // 确保日志目录存在,如果不存在则创建 27 | if err := os.MkdirAll(logDir, 0755); err != nil { 28 | return nil, fmt.Errorf("failed to create log directory: %v", err) 29 | } 30 | 31 | // 打开日志文件,确保以追加模式打开 32 | logFile, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) 33 | if err != nil { 34 | return nil, fmt.Errorf("failed to open log file: %v", err) 35 | } 36 | 37 | return &TaskLogger{logFile: logFile}, nil 38 | } 39 | 40 | // Log 写入日志信息 41 | func (t *TaskLogger) Log(message string) { 42 | // 使用更高精度的时间戳 43 | _, err := t.logFile.WriteString(fmt.Sprintf("%s: %s\n", time.Now().Format("2006-01-02 15:04:05.000000"), message)) 44 | if err != nil { 45 | fmt.Printf("Failed to write log: %v\n", err) 46 | } 47 | } 48 | 49 | // Close 关闭日志文件 50 | func (t *TaskLogger) Close() { 51 | if err := t.logFile.Close(); err != nil { 52 | fmt.Printf("Failed to close log file: %v\n", err) 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /cmd/migrate/migration/version/1730013300607_migrate.go: -------------------------------------------------------------------------------- 1 | package version 2 | 3 | import ( 4 | "github.com/go-admin-team/go-admin-core/sdk/config" 5 | "gorm.io/gorm" 6 | "runtime" 7 | "smart-api/app/smart/models" 8 | "smart-api/cmd/migrate/migration" 9 | models2 "smart-api/cmd/migrate/migration/models" 10 | common "smart-api/common/models" 11 | ) 12 | 13 | func init() { 14 | _, fileName, _, _ := runtime.Caller(0) 15 | migration.Migrate.SetVersion(migration.GetFilename(fileName), _1730013300607Test) 16 | } 17 | 18 | // 添加自定义的表,为系统表 19 | func _1730013300607Test(db *gorm.DB, version string) error { 20 | return db.Transaction(func(tx *gorm.DB) error { 21 | if config.DatabaseConfig.Driver == "mysql" { 22 | tx = tx.Set("gorm:table_options", "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4") 23 | } 24 | // 先进行自动迁移,创建表 25 | err := tx.Migrator().AutoMigrate( 26 | new(models.OrderCategory), 27 | new(models.OrderItems), 28 | new(models.ExecMachine), 29 | new(models.ExecutionHistoryTask), 30 | new(models.FlowManage), 31 | new(models.FlowTemplates), 32 | new(models.OperationHistory), 33 | new(models.OrderComment), 34 | new(models.OrderRating), 35 | new(models.OrderTask), 36 | new(models.OrderWorks), 37 | new(models.UserFavorites), 38 | new(models.WorksNotify), 39 | ) 40 | if err != nil { 41 | return err 42 | } 43 | // 确保初始化数据库模型 44 | if err := models2.InitDb(tx); err != nil { 45 | return err 46 | } 47 | 48 | return tx.Create(&common.Migration{ 49 | Version: version, 50 | }).Error 51 | 52 | }) 53 | } 54 | -------------------------------------------------------------------------------- /app/system/models/sys_role.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "smart-api/common/models" 4 | 5 | type SysRole struct { 6 | RoleId int `json:"roleId" gorm:"primaryKey;autoIncrement"` // 角色编码 7 | RoleName string `json:"roleName" gorm:"size:128;"` // 角色名称 8 | Status string `json:"status" gorm:"size:4;"` // 状态 1禁用 2正常 9 | RoleKey string `json:"roleKey" gorm:"size:128;"` //角色代码 10 | RoleSort int `json:"roleSort" gorm:""` //角色排序 11 | Flag string `json:"flag" gorm:"size:128;"` // 12 | Remark string `json:"remark" gorm:"size:255;"` //备注 13 | Admin bool `json:"admin" gorm:"size:4;"` 14 | DataScope string `json:"dataScope" gorm:"size:128;"` 15 | Params string `json:"params" gorm:"-"` 16 | MenuIds []int `json:"menuIds" gorm:"-"` 17 | DeptIds []int `json:"deptIds" gorm:"-"` 18 | SysDept []SysDept `json:"sysDept" gorm:"many2many:sys_role_dept;foreignKey:RoleId;joinForeignKey:role_id;references:DeptId;joinReferences:dept_id;"` 19 | SysMenu *[]SysMenu `json:"sysMenu" gorm:"many2many:sys_role_menu;foreignKey:RoleId;joinForeignKey:role_id;references:MenuId;joinReferences:menu_id;"` 20 | models.ControlBy 21 | models.ModelTime 22 | } 23 | 24 | func (*SysRole) TableName() string { 25 | return "sys_role" 26 | } 27 | 28 | func (e *SysRole) Generate() models.ActiveRecord { 29 | o := *e 30 | return &o 31 | } 32 | 33 | func (e *SysRole) GetId() interface{} { 34 | return e.RoleId 35 | } 36 | -------------------------------------------------------------------------------- /common/actions/index.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | log "github.com/go-admin-team/go-admin-core/logger" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 11 | "gorm.io/gorm" 12 | 13 | "smart-api/common/dto" 14 | "smart-api/common/models" 15 | ) 16 | 17 | // IndexAction 通用查询动作 18 | func IndexAction(m models.ActiveRecord, d dto.Index, f func() interface{}) gin.HandlerFunc { 19 | return func(c *gin.Context) { 20 | db, err := pkg.GetOrm(c) 21 | if err != nil { 22 | log.Error(err) 23 | return 24 | } 25 | 26 | msgID := pkg.GenerateMsgIDFromContext(c) 27 | list := f() 28 | object := m.Generate() 29 | req := d.Generate() 30 | var count int64 31 | 32 | //查询列表 33 | err = req.Bind(c) 34 | if err != nil { 35 | response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") 36 | return 37 | } 38 | 39 | //数据权限检查 40 | p := GetPermissionFromContext(c) 41 | 42 | err = db.WithContext(c).Model(object). 43 | Scopes( 44 | dto.MakeCondition(req.GetNeedSearch()), 45 | dto.Paginate(req.GetPageSize(), req.GetPageIndex()), 46 | Permission(object.TableName(), p), 47 | ). 48 | Find(list).Limit(-1).Offset(-1). 49 | Count(&count).Error 50 | if err != nil && !errors.Is(err, gorm.ErrRecordNotFound) { 51 | log.Errorf("MsgID[%s] Index error: %s", msgID, err) 52 | response.Error(c, 500, err, "查询失败") 53 | return 54 | } 55 | response.PageOK(c, list, int(count), req.GetPageIndex(), req.GetPageSize(), "查询成功") 56 | c.Next() 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /common/actions/update.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 11 | 12 | "smart-api/common/dto" 13 | "smart-api/common/models" 14 | ) 15 | 16 | // UpdateAction 通用更新动作 17 | func UpdateAction(control dto.Control) gin.HandlerFunc { 18 | return func(c *gin.Context) { 19 | db, err := pkg.GetOrm(c) 20 | if err != nil { 21 | log.Error(err) 22 | return 23 | } 24 | 25 | msgID := pkg.GenerateMsgIDFromContext(c) 26 | req := control.Generate() 27 | //更新操作 28 | err = req.Bind(c) 29 | if err != nil { 30 | response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") 31 | return 32 | } 33 | var object models.ActiveRecord 34 | object, err = req.GenerateM() 35 | if err != nil { 36 | response.Error(c, 500, err, "模型生成失败") 37 | return 38 | } 39 | object.SetUpdateBy(user.GetUserId(c)) 40 | 41 | //数据权限检查 42 | p := GetPermissionFromContext(c) 43 | 44 | db = db.WithContext(c).Scopes( 45 | Permission(object.TableName(), p), 46 | ).Where(req.GetId()).Updates(object) 47 | if err = db.Error; err != nil { 48 | log.Errorf("MsgID[%s] Update error: %s", msgID, err) 49 | response.Error(c, 500, err, "更新失败") 50 | return 51 | } 52 | if db.RowsAffected == 0 { 53 | response.Error(c, http.StatusForbidden, nil, "无权更新该数据") 54 | return 55 | } 56 | response.OK(c, object.GetId(), "更新成功") 57 | c.Next() 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /template/v4/model.go.template: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | {{- $bb := false -}} 5 | {{- range .Columns -}} 6 | {{- $z := .IsQuery -}} 7 | {{- if ($z) -}} 8 | {{- if eq .GoType "time.Time" -}}{{- $bb = true -}}{{- end -}} 9 | {{- end -}} 10 | {{- end -}} 11 | {{- range .Columns -}} 12 | {{- if eq .GoField "CreatedAt" -}} 13 | {{- else if eq .GoField "UpdatedAt" -}} 14 | {{- else if eq .GoField "DeletedAt" -}} 15 | {{- else -}} 16 | {{- if eq .GoType "time.Time" -}}{{- $bb = true -}}{{- end -}} 17 | {{- end -}} 18 | {{- end -}} 19 | {{- if eq $bb true }} 20 | "time" 21 | {{- end }} 22 | 23 | "smart-api/common/models" 24 | 25 | ) 26 | 27 | type {{.ClassName}} struct { 28 | models.Model 29 | {{ range .Columns -}} 30 | {{$x := .Pk}} 31 | {{- if ($x) }} 32 | {{- else if eq .GoField "CreatedAt" -}} 33 | {{- else if eq .GoField "UpdatedAt" -}} 34 | {{- else if eq .GoField "DeletedAt" -}} 35 | {{- else if eq .GoField "CreateBy" -}} 36 | {{- else if eq .GoField "UpdateBy" -}} 37 | {{- else }} 38 | {{.GoField}} {{.GoType}} `json:"{{.JsonField}}" gorm:"type:{{.ColumnType}};comment:{{- if eq .ColumnComment "" -}}{{.GoField}}{{- else -}}{{.ColumnComment}}{{end -}}"` {{end -}} 39 | {{- end }} 40 | models.ModelTime 41 | models.ControlBy 42 | } 43 | 44 | func ({{.ClassName}}) TableName() string { 45 | return "{{.TBName}}" 46 | } 47 | 48 | func (e *{{.ClassName}}) Generate() models.ActiveRecord { 49 | o := *e 50 | return &o 51 | } 52 | 53 | func (e *{{.ClassName}}) GetId() interface{} { 54 | return e.{{.PkGoField}} 55 | } 56 | -------------------------------------------------------------------------------- /app/jobs/apis/sys_job.go: -------------------------------------------------------------------------------- 1 | package apis 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | "github.com/go-admin-team/go-admin-core/sdk" 8 | "github.com/go-admin-team/go-admin-core/sdk/api" 9 | 10 | "smart-api/app/jobs/service" 11 | "smart-api/common/dto" 12 | ) 13 | 14 | type SysJob struct { 15 | api.Api 16 | } 17 | 18 | // RemoveJobForService 调用service实现 19 | func (e SysJob) RemoveJobForService(c *gin.Context) { 20 | v := dto.GeneralDelDto{} 21 | s := service.SysJob{} 22 | err := e.MakeContext(c). 23 | MakeOrm(). 24 | Bind(&v). 25 | MakeService(&s.Service). 26 | Errors 27 | if err != nil { 28 | e.Logger.Error(err) 29 | return 30 | } 31 | 32 | s.Cron = sdk.Runtime.GetCrontabKey(c.Request.Host) 33 | err = s.RemoveJob(&v) 34 | if err != nil { 35 | e.Logger.Errorf("RemoveJob error, %s", err.Error()) 36 | e.Error(500, err, "") 37 | return 38 | } 39 | e.OK(nil, s.Msg) 40 | } 41 | 42 | // StartJobForService 启动job service实现 43 | func (e SysJob) StartJobForService(c *gin.Context) { 44 | e.MakeContext(c) 45 | log := e.GetLogger() 46 | db, err := e.GetOrm() 47 | if err != nil { 48 | log.Error(err) 49 | return 50 | } 51 | var v dto.GeneralGetDto 52 | err = c.BindUri(&v) 53 | if err != nil { 54 | log.Warnf("参数验证错误, error: %s", err) 55 | e.Error(http.StatusUnprocessableEntity, err, "参数验证失败") 56 | return 57 | } 58 | s := service.SysJob{} 59 | s.Orm = db 60 | s.Log = log 61 | s.Cron = sdk.Runtime.GetCrontabKey(c.Request.Host) 62 | err = s.StartJob(&v) 63 | if err != nil { 64 | log.Errorf("GetCrontabKey error, %s", err.Error()) 65 | e.Error(500, err, err.Error()) 66 | return 67 | } 68 | e.OK(nil, s.Msg) 69 | } 70 | -------------------------------------------------------------------------------- /app/smart/service/dto/order_rating.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "smart-api/app/smart/models" 5 | common "smart-api/common/models" 6 | ) 7 | 8 | type OrderRatingInsertReq struct { 9 | OrderID int `json:"orderID" comment:"工单ID"` // 工单ID 10 | Ratings int `json:"ratings" comment:"评分"` // 评分 11 | common.ControlBy 12 | } 13 | 14 | // Generate 生成 OrderRating 模型实例 15 | func (s *OrderRatingInsertReq) Generate(model *models.OrderRating) { 16 | model.OrderID = s.OrderID 17 | model.Ratings = s.Ratings 18 | model.ControlBy = s.ControlBy 19 | } 20 | 21 | // GetId 获取数据对应的 ID 22 | func (s *OrderRatingInsertReq) GetId() interface{} { 23 | return s.OrderID 24 | } 25 | 26 | type OrderRatingUpdateReq struct { 27 | ID int `uri:"id" comment:"ID"` // 评分ID 28 | OrderID int `json:"orderID" comment:"工单ID"` // 工单ID 29 | Ratings int `json:"ratings" comment:"评分"` // 评分 30 | common.ControlBy 31 | common.ModelTime 32 | } 33 | 34 | // Generate 生成 OrderRating 模型实例 35 | func (s *OrderRatingUpdateReq) Generate(model *models.OrderRating) { 36 | model.ID = s.ID 37 | model.OrderID = s.OrderID 38 | model.Ratings = s.Ratings 39 | model.ControlBy = s.ControlBy 40 | } 41 | 42 | // GetId 获取数据对应的 ID 43 | func (s *OrderRatingUpdateReq) GetId() interface{} { 44 | return s.ID 45 | } 46 | 47 | type OrderRatingGetReq struct { 48 | OrderId int `uri:"orderID" comment:"工单ID"` // 评分ID 49 | } 50 | 51 | // GetId 获取数据对应的 ID 52 | func (s *OrderRatingGetReq) GetId() interface{} { 53 | return s.OrderId 54 | } 55 | 56 | type OrderRatingDeleteReq struct { 57 | ID int `json:"id" comment:"ID"` // 评分ID 58 | } 59 | 60 | // GetId 获取数据对应的 ID 61 | func (s *OrderRatingDeleteReq) GetId() interface{} { 62 | return s.ID 63 | } 64 | -------------------------------------------------------------------------------- /common/actions/delete.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "net/http" 5 | 6 | "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth/user" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 11 | 12 | "smart-api/common/dto" 13 | "smart-api/common/models" 14 | ) 15 | 16 | // DeleteAction 通用删除动作 17 | func DeleteAction(control dto.Control) gin.HandlerFunc { 18 | return func(c *gin.Context) { 19 | db, err := pkg.GetOrm(c) 20 | if err != nil { 21 | log.Error(err) 22 | return 23 | } 24 | 25 | msgID := pkg.GenerateMsgIDFromContext(c) 26 | //删除操作 27 | req := control.Generate() 28 | err = req.Bind(c) 29 | if err != nil { 30 | log.Errorf("MsgID[%s] Bind error: %s", msgID, err) 31 | response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") 32 | return 33 | } 34 | var object models.ActiveRecord 35 | object, err = req.GenerateM() 36 | if err != nil { 37 | response.Error(c, 500, err, "模型生成失败") 38 | return 39 | } 40 | 41 | object.SetUpdateBy(user.GetUserId(c)) 42 | 43 | //数据权限检查 44 | p := GetPermissionFromContext(c) 45 | 46 | db = db.WithContext(c).Scopes( 47 | Permission(object.TableName(), p), 48 | ).Where(req.GetId()).Delete(object) 49 | if err = db.Error; err != nil { 50 | log.Errorf("MsgID[%s] Delete error: %s", msgID, err) 51 | response.Error(c, 500, err, "删除失败") 52 | return 53 | } 54 | if db.RowsAffected == 0 { 55 | response.Error(c, http.StatusForbidden, nil, "无权删除该数据") 56 | return 57 | } 58 | response.OK(c, object.GetId(), "删除成功") 59 | c.Next() 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /app/other/apis/tools/db_columns.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 6 | _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 7 | 8 | "smart-api/app/other/models/tools" 9 | ) 10 | 11 | // GetDBColumnList 分页列表数据 12 | // @Summary 分页列表数据 / page list data 13 | // @Description 数据库表列分页列表 / database table column page list 14 | // @Tags 工具 / 生成工具 15 | // @Param tableName query string false "tableName / 数据表名称" 16 | // @Param pageSize query int false "pageSize / 页条数" 17 | // @Param pageIndex query int false "pageIndex / 页码" 18 | // @Success 200 {object} response.Response "{"code": 200, "data": [...]}" 19 | // @Router /api/v1/db/columns/page [get] 20 | func (e Gen) GetDBColumnList(c *gin.Context) { 21 | e.Context = c 22 | log := e.GetLogger() 23 | var data tools.DBColumns 24 | var err error 25 | var pageSize = 10 26 | var pageIndex = 1 27 | 28 | if size := c.Request.FormValue("pageSize"); size != "" { 29 | pageSize, err = pkg.StringToInt(size) 30 | } 31 | 32 | if index := c.Request.FormValue("pageIndex"); index != "" { 33 | pageIndex, err = pkg.StringToInt(index) 34 | } 35 | 36 | db, err := pkg.GetOrm(c) 37 | if err != nil { 38 | log.Errorf("get db connection error, %s", err.Error()) 39 | e.Error(500, err, "数据库连接获取失败") 40 | return 41 | } 42 | 43 | data.TableName = c.Request.FormValue("tableName") 44 | pkg.Assert(data.TableName == "", "table name cannot be empty!", 500) 45 | result, count, err := data.GetPage(db, pageSize, pageIndex) 46 | if err != nil { 47 | log.Errorf("GetPage error, %s", err.Error()) 48 | e.Error(500, err, "") 49 | return 50 | } 51 | e.PageOK(result, count, pageIndex, pageSize, "查询成功") 52 | } 53 | -------------------------------------------------------------------------------- /common/actions/view.go: -------------------------------------------------------------------------------- 1 | package actions 2 | 3 | import ( 4 | "errors" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 6 | "net/http" 7 | 8 | "github.com/gin-gonic/gin" 9 | log "github.com/go-admin-team/go-admin-core/logger" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 11 | "gorm.io/gorm" 12 | 13 | "smart-api/common/dto" 14 | "smart-api/common/models" 15 | ) 16 | 17 | // ViewAction 通用详情动作 18 | func ViewAction(control dto.Control, f func() interface{}) gin.HandlerFunc { 19 | return func(c *gin.Context) { 20 | db, err := pkg.GetOrm(c) 21 | if err != nil { 22 | log.Error(err) 23 | return 24 | } 25 | 26 | msgID := pkg.GenerateMsgIDFromContext(c) 27 | //查看详情 28 | req := control.Generate() 29 | err = req.Bind(c) 30 | if err != nil { 31 | response.Error(c, http.StatusUnprocessableEntity, err, "参数验证失败") 32 | return 33 | } 34 | var object models.ActiveRecord 35 | object, err = req.GenerateM() 36 | if err != nil { 37 | response.Error(c, 500, err, "模型生成失败") 38 | return 39 | } 40 | 41 | var rsp interface{} 42 | if f != nil { 43 | rsp = f() 44 | } else { 45 | rsp, _ = req.GenerateM() 46 | } 47 | 48 | //数据权限检查 49 | p := GetPermissionFromContext(c) 50 | 51 | err = db.Model(object).WithContext(c).Scopes( 52 | Permission(object.TableName(), p), 53 | ).Where(req.GetId()).First(rsp).Error 54 | 55 | if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { 56 | response.Error(c, http.StatusNotFound, nil, "查看对象不存在或无权查看") 57 | return 58 | } 59 | if err != nil { 60 | log.Errorf("MsgID[%s] View error: %s", msgID, err) 61 | response.Error(c, 500, err, "查看失败") 62 | return 63 | } 64 | response.OK(c, rsp, "查询成功") 65 | c.Next() 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /app/smart/models/flow_templates.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/13 21:14 3 | package models 4 | 5 | import ( 6 | "database/sql/driver" 7 | "encoding/json" 8 | "errors" 9 | "smart-api/common/models" 10 | ) 11 | 12 | type FormData map[string]interface{} 13 | 14 | // vform模板管理表 15 | type FlowTemplates struct { 16 | ID uint `gorm:"primaryKey;autoIncrement" json:"id"` 17 | Name string `gorm:"column:name;type:varchar(100)" json:"name"` 18 | Description string `gorm:"column:description;type:varchar(200)" json:"description"` 19 | BindCount int `gorm:"column:bindCount" json:"bindCount"` 20 | FormData FormData `gorm:"type:json" json:"formData"` 21 | CategoryID uint `gorm:"column:categoryId" json:"categoryId"` 22 | BindFlow uint `gorm:"column:bindFlow" json:"bindFlow"` 23 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 24 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 25 | models.ControlBy 26 | models.ModelTime 27 | } 28 | 29 | func (*FlowTemplates) TableName() string { 30 | return "flow_templates" 31 | } 32 | 33 | func (e *FlowTemplates) Generate() models.ActiveRecord { 34 | o := *e 35 | return &o 36 | } 37 | 38 | func (e *FlowTemplates) GetId() interface{} { 39 | return e.ID 40 | } 41 | 42 | // FormData 的 Scan 和 Value 方法 43 | func (e *FormData) Scan(value interface{}) error { 44 | bytes, ok := value.([]byte) 45 | if !ok { 46 | return errors.New("Scan source is not []byte") 47 | } 48 | return json.Unmarshal(bytes, &e) 49 | } 50 | 51 | func (e FormData) Value() (driver.Value, error) { 52 | bytes, err := json.Marshal(e) 53 | if err != nil { 54 | return nil, err 55 | } 56 | return string(bytes), nil 57 | } 58 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_user.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "golang.org/x/crypto/bcrypt" 5 | "gorm.io/gorm" 6 | ) 7 | 8 | type SysUser struct { 9 | UserId int `gorm:"primaryKey;autoIncrement;comment:编码" json:"userId"` 10 | Username string `json:"username" gorm:"type:varchar(64);comment:用户名"` 11 | Password string `json:"-" gorm:"type:varchar(128);comment:密码"` 12 | NickName string `json:"nickName" gorm:"type:varchar(128);comment:昵称"` 13 | Phone string `json:"phone" gorm:"type:varchar(11);comment:手机号"` 14 | RoleId int `json:"roleId" gorm:"type:bigint;comment:角色ID"` 15 | Salt string `json:"-" gorm:"type:varchar(255);comment:加盐"` 16 | Avatar string `json:"avatar" gorm:"type:varchar(255);comment:头像"` 17 | Sex string `json:"sex" gorm:"type:varchar(255);comment:性别"` 18 | Email string `json:"email" gorm:"type:varchar(128);comment:邮箱"` 19 | DeptId int `json:"deptId" gorm:"type:bigint;comment:部门"` 20 | PostId int `json:"postId" gorm:"type:bigint;comment:岗位"` 21 | Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` 22 | Status string `json:"status" gorm:"type:varchar(4);comment:状态"` 23 | Source string `json:"source" gorm:"size:255;comment:用户来源"` 24 | ControlBy 25 | ModelTime 26 | } 27 | 28 | func (*SysUser) TableName() string { 29 | return "sys_user" 30 | } 31 | 32 | // Encrypt 加密 33 | func (e *SysUser) Encrypt() (err error) { 34 | if e.Password == "" { 35 | return 36 | } 37 | 38 | var hash []byte 39 | if hash, err = bcrypt.GenerateFromPassword([]byte(e.Password), bcrypt.DefaultCost); err != nil { 40 | return 41 | } else { 42 | e.Password = string(hash) 43 | return 44 | } 45 | } 46 | 47 | func (e *SysUser) BeforeCreate(_ *gorm.DB) error { 48 | return e.Encrypt() 49 | } 50 | -------------------------------------------------------------------------------- /app/smart/router/order_works.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/12 20:28 3 | package router 4 | 5 | import ( 6 | "github.com/gin-gonic/gin" 7 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 8 | "smart-api/app/smart/apis" 9 | "smart-api/common/middleware" 10 | "smart-api/common/utils" 11 | ) 12 | 13 | func init() { 14 | routerCheckRole = append(routerCheckRole, registerOrderWorksAuthRouter) 15 | } 16 | 17 | // 注册工单类别路由 18 | func registerOrderWorksAuthRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 19 | api := apis.OrderWorksAPI{} 20 | hisApi := apis.OperationHistory{} 21 | notifyApi := apis.WorksNotify{} 22 | 23 | r := v1.Group("/order-works").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 24 | 25 | ws := v1.Group("").Use(authMiddleware.MiddlewareFunc()).Use(middleware.AuthCheckRole()) 26 | 27 | { 28 | // 查询所有的工单 29 | r.GET("", api.GetPage) 30 | // 根据ID 查询 31 | r.GET("/:id", api.Get) 32 | // 我的待办 33 | r.GET("/myBacklog", api.MyBacklogGet) 34 | // 我创建的 35 | r.GET("/createdByMe", api.CreatedByMe) 36 | // 与我相关的 37 | r.GET("/relatedToMe", api.RelatedToMe) 38 | // 创建工单 39 | r.POST("", api.Insert) 40 | // 更新工单信息、生成更新记录 41 | r.PUT("", api.Update) 42 | // 工单处理,更新工单当前节点、当前处理人 43 | r.PUT("/handle", api.Handle) 44 | // 删除工单 45 | r.DELETE("", api.Delete) 46 | } 47 | { 48 | // 获取历史变更信息 49 | r.GET("/history", hisApi.GetOperationHistory) 50 | } 51 | { 52 | // 获取通知消息 53 | r.GET("/notify", notifyApi.GetNotify) 54 | 55 | // 发送通知消息 56 | r.POST("/notify", notifyApi.CreateNotify) 57 | 58 | // 处理通知消息 59 | r.PUT("/notify", notifyApi.UpdateNotify) 60 | 61 | } 62 | 63 | { 64 | // 自定义WebSocket处理程序 65 | ws.GET("/ws/task/:id", utils.WsHandler) 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PROJECT:=smart-api 2 | 3 | .PHONY: build 4 | build: 5 | CGO_ENABLED=0 go build -ldflags="-w -s" -a -installsuffix "" -o smart-api . 6 | 7 | # make build-linux 8 | build-linux: 9 | @docker build -t smart-api:latest . 10 | @echo "build successful" 11 | 12 | build-sqlite: 13 | go build -tags sqlite3 -ldflags="-w -s" -a -installsuffix -o smart-api . 14 | 15 | # make run 16 | run: 17 | # delete smart-api-api container 18 | @if [ $(shell docker ps -aq --filter name=smart-api --filter publish=8000) ]; then docker rm -f smart-api; fi 19 | 20 | # 启动方法一 run smart-api-api container docker-compose 启动方式 21 | # 进入到项目根目录 执行 make run 命令 22 | @docker-compose up -d 23 | 24 | # 启动方式二 docker run 这里注意-v挂载的宿主机的地址改为部署时的实际决对路径 25 | #@docker run --name=smart-api -p 8000:8000 -v /home/code/go/src/smart-api/smart-api/config:/smart-api-api/config -v /home/code/go/src/smart-api/smart-api-api/static:/smart-api/static -v /home/code/go/src/smart-api/smart-api/temp:/smart-api-api/temp -d --restart=always smart-api:latest 26 | 27 | @echo "smart-api service is running..." 28 | 29 | # delete Tag= 的镜像 30 | @docker image prune -f 31 | @docker ps -a | grep "smart-api" 32 | 33 | stop: 34 | # delete smart-api-api container 35 | @if [ $(shell docker ps -aq --filter name=smart-api --filter publish=8000) ]; then docker-compose down; fi 36 | #@if [ $(shell docker ps -aq --filter name=smart-api --filter publish=8000) ]; then docker rm -f smart-api; fi 37 | #@echo "smart-api stop success" 38 | 39 | 40 | #.PHONY: test 41 | #test: 42 | # go test -v ./... -cover 43 | 44 | #.PHONY: docker 45 | #docker: 46 | # docker build . -t smart-api:latest 47 | 48 | # make deploy 49 | deploy: 50 | 51 | #@git checkout master 52 | #@git pull origin master 53 | make build-linux 54 | make run 55 | -------------------------------------------------------------------------------- /app/smart/service/dto/order_comment.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "smart-api/app/smart/models" 5 | common "smart-api/common/models" 6 | ) 7 | 8 | type OrderCommentInsertReq struct { 9 | OrderID int `json:"orderID" comment:"工单ID"` // 工单ID 10 | ParentID *int `json:"parentID" comment:"父留言ID"` // 父留言ID 11 | Comments string `json:"comments" comment:"留言"` // 留言 12 | common.ControlBy 13 | } 14 | 15 | func (s *OrderCommentInsertReq) Generate(model *models.OrderComment) { 16 | model.OrderID = s.OrderID 17 | model.ParentID = s.ParentID 18 | model.Comments = s.Comments 19 | model.ControlBy = s.ControlBy 20 | } 21 | 22 | func (s *OrderCommentInsertReq) GetId() interface{} { 23 | return s.OrderID 24 | } 25 | 26 | type OrderCommentUpdateReq struct { 27 | ID int `uri:"id" comment:"ID"` // 留言ID 28 | OrderID int `json:"orderID" comment:"工单ID"` // 工单ID 29 | ParentID *int `json:"parentID" comment:"父留言ID"` 30 | Comments string `json:"comments" comment:"留言"` // 留言内容 31 | common.ControlBy 32 | common.ModelTime 33 | } 34 | 35 | func (s *OrderCommentUpdateReq) Generate(model *models.OrderComment) { 36 | model.ID = s.ID 37 | model.OrderID = s.OrderID 38 | model.ParentID = s.ParentID 39 | model.Comments = s.Comments 40 | model.ControlBy = s.ControlBy 41 | } 42 | 43 | func (s *OrderCommentUpdateReq) GetId() interface{} { 44 | return s.ID 45 | } 46 | 47 | type OrderCommentGetReq struct { 48 | OrderID int `uri:"orderID" comment:"工单ID"` // 工单ID 49 | } 50 | 51 | // GetId 获取留言的 ID 52 | func (s *OrderCommentGetReq) GetId() interface{} { 53 | return s.OrderID 54 | } 55 | 56 | type OrderCommentDeleteReq struct { 57 | ID int `json:"id" comment:"留言ID"` // 留言ID 58 | } 59 | 60 | // GetId 获取留言的 ID 61 | func (s *OrderCommentDeleteReq) GetId() interface{} { 62 | return s.ID 63 | } 64 | -------------------------------------------------------------------------------- /app/system/service/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "errors" 5 | 6 | "github.com/go-admin-team/go-admin-core/sdk/service" 7 | "gorm.io/gorm" 8 | 9 | "smart-api/app/system/models" 10 | "smart-api/app/system/service/dto" 11 | cDto "smart-api/common/dto" 12 | ) 13 | 14 | type SysLoginLog struct { 15 | service.Service 16 | } 17 | 18 | // GetPage 获取SysLoginLog列表 19 | func (e *SysLoginLog) GetPage(c *dto.SysLoginLogGetPageReq, list *[]models.SysLoginLog, count *int64) error { 20 | var err error 21 | var data models.SysLoginLog 22 | 23 | err = e.Orm.Model(&data). 24 | Scopes( 25 | cDto.MakeCondition(c.GetNeedSearch()), 26 | cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), 27 | ). 28 | Find(list).Limit(-1).Offset(-1). 29 | Count(count).Error 30 | if err != nil { 31 | e.Log.Errorf("db error:%s", err) 32 | return err 33 | } 34 | return nil 35 | } 36 | 37 | // Get 获取SysLoginLog对象 38 | func (e *SysLoginLog) Get(d *dto.SysLoginLogGetReq, model *models.SysLoginLog) error { 39 | var err error 40 | db := e.Orm.First(model, d.GetId()) 41 | err = db.Error 42 | if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { 43 | err = errors.New("查看对象不存在或无权查看") 44 | e.Log.Errorf("db error:%s", err) 45 | return err 46 | } 47 | if err = db.Error; err != nil { 48 | e.Log.Errorf("db error:%s", err) 49 | return err 50 | } 51 | return nil 52 | } 53 | 54 | // Remove 删除SysLoginLog 55 | func (e *SysLoginLog) Remove(c *dto.SysLoginLogDeleteReq) error { 56 | var err error 57 | var data models.SysLoginLog 58 | 59 | db := e.Orm.Delete(&data, c.GetId()) 60 | if err = db.Error; err != nil { 61 | err = db.Error 62 | e.Log.Errorf("Delete error: %s", err) 63 | return err 64 | } 65 | if db.RowsAffected == 0 { 66 | err = errors.New("无权删除该数据") 67 | return err 68 | } 69 | return nil 70 | } 71 | -------------------------------------------------------------------------------- /common/middleware/header.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "net/http" 5 | "time" 6 | 7 | "github.com/gin-gonic/gin" 8 | ) 9 | 10 | // NoCache is a middleware function that appends headers 11 | // to prevent the client from caching the HTTP response. 12 | func NoCache(c *gin.Context) { 13 | c.Header("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate, value") 14 | c.Header("Expires", "Thu, 01 Jan 1970 00:00:00 GMT") 15 | c.Header("Last-Modified", time.Now().UTC().Format(http.TimeFormat)) 16 | c.Next() 17 | } 18 | 19 | // Options is a middleware function that appends headers 20 | // for options requests and aborts then exits the middleware 21 | // chain and ends the request. 22 | func Options(c *gin.Context) { 23 | if c.Request.Method != "OPTIONS" { 24 | c.Next() 25 | } else { 26 | c.Header("Access-Control-Allow-Origin", "*") 27 | c.Header("Access-Control-Allow-Methods", "GET,POST,PUT,PATCH,DELETE,OPTIONS") 28 | c.Header("Access-Control-Allow-Headers", "authorization, origin, content-type, accept, user-agent") 29 | c.Header("Access-Control-Allow-Credentials", "true") 30 | c.Header("Allow", "HEAD,GET,POST,PUT,PATCH,DELETE,OPTIONS") 31 | c.Header("Content-Type", "application/json") 32 | c.AbortWithStatus(200) 33 | } 34 | } 35 | 36 | // Secure is a middleware function that appends security 37 | // and resource access headers. 38 | func Secure(c *gin.Context) { 39 | c.Header("Access-Control-Allow-Origin", "*") 40 | //c.Header("X-Frame-Options", "DENY") 41 | c.Header("X-Content-Type-Options", "nosniff") 42 | c.Header("X-XSS-Protection", "1; mode=block") 43 | if c.Request.TLS != nil { 44 | c.Header("Strict-Transport-Security", "max-age=31536000") 45 | } 46 | 47 | // Also consider adding Content-Security-Policy headers 48 | // c.Header("Content-Security-Policy", "script-src 'self' https://cdnjs.cloudflare.com") 49 | } 50 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/order_works.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/17 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type BindFlowData map[string]interface{} 10 | 11 | type OrderWorks struct { 12 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 13 | Title string `gorm:"column:title;type:varchar(100)" json:"title"` // 工单标题 14 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 15 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 16 | CurrentNode string `gorm:"column:currentNode;type:varchar(50)" json:"currentNode"` // 当前节点 17 | CurrentHandler string `gorm:"column:currentHandler;type:varchar(50)" json:"currentHandler"` // 当前处理人 18 | CurrentHandlerID int `gorm:"column:currentHandlerId" json:"currentHandlerID"` // 当前处理人ID 19 | Process string `gorm:"column:process;type:varchar(50)" json:"process"` // 流程 20 | Priority string `gorm:"column:priority;type:varchar(20)" json:"priority"` // 优先级 21 | Status string `gorm:"column:status;type:varchar(20)" json:"status"` // 状态 22 | Department string `gorm:"column:department;type:varchar(50)" json:"department"` // 部门 23 | Description string `gorm:"description:des;type:varchar(512)" json:"description"` 24 | Template string `gorm:"column:template;type:varchar(50)" json:"template"` // 模板 25 | FormData FormData `gorm:"type:json" json:"formData"` 26 | BindFlowData BindFlowData `gorm:"column:bindFlowData;type:json" json:"bindFlowData"` 27 | models.ControlBy 28 | models.ModelTime 29 | } 30 | 31 | func (OrderWorks) TableName() string { 32 | return "order_works" 33 | } 34 | -------------------------------------------------------------------------------- /app/other/router/gen_router.go: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | import ( 4 | "github.com/gin-gonic/gin" 5 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 6 | "smart-api/app/other/apis/tools" 7 | "smart-api/app/system/apis" 8 | ) 9 | 10 | func init() { 11 | routerCheckRole = append(routerCheckRole, sysNoCheckRoleRouter, registerDBRouter, registerSysTableRouter) 12 | } 13 | 14 | func sysNoCheckRoleRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 15 | r1 := v1.Group("") 16 | { 17 | sys := apis.System{} 18 | r1.GET("/captcha", sys.GenerateCaptchaHandler) 19 | } 20 | 21 | r := v1.Group("").Use(authMiddleware.MiddlewareFunc()) 22 | { 23 | gen := tools.Gen{} 24 | r.GET("/gen/preview/:tableId", gen.Preview) 25 | r.GET("/gen/toproject/:tableId", gen.GenCode) 26 | r.GET("/gen/apitofile/:tableId", gen.GenApiToFile) 27 | r.GET("/gen/todb/:tableId", gen.GenMenuAndApi) 28 | sysTable := tools.SysTable{} 29 | r.GET("/gen/tabletree", sysTable.GetSysTablesTree) 30 | } 31 | } 32 | 33 | func registerDBRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 34 | db := v1.Group("/db").Use(authMiddleware.MiddlewareFunc()) 35 | { 36 | gen := tools.Gen{} 37 | db.GET("/tables/page", gen.GetDBTableList) 38 | db.GET("/columns/page", gen.GetDBColumnList) 39 | } 40 | } 41 | 42 | func registerSysTableRouter(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) { 43 | tables := v1.Group("/sys/tables") 44 | { 45 | sysTable := tools.SysTable{} 46 | tables.Group("").Use(authMiddleware.MiddlewareFunc()).GET("/page", sysTable.GetPage) 47 | tablesInfo := tables.Group("/info").Use(authMiddleware.MiddlewareFunc()) 48 | { 49 | tablesInfo.POST("", sysTable.Insert) 50 | tablesInfo.PUT("", sysTable.Update) 51 | tablesInfo.DELETE("/:tableId", sysTable.Delete) 52 | tablesInfo.GET("/:tableId", sysTable.Get) 53 | tablesInfo.GET("", sysTable.GetSysTablesInfo) 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_opera_log.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "time" 5 | ) 6 | 7 | type SysOperaLog struct { 8 | Model 9 | Title string `json:"title" gorm:"type:varchar(255);comment:操作模块"` 10 | BusinessType string `json:"businessType" gorm:"type:varchar(128);comment:操作类型"` 11 | BusinessTypes string `json:"businessTypes" gorm:"type:varchar(128);comment:BusinessTypes"` 12 | Method string `json:"method" gorm:"type:varchar(128);comment:函数"` 13 | RequestMethod string `json:"requestMethod" gorm:"type:varchar(128);comment:请求方式: GET POST PUT DELETE"` 14 | OperatorType string `json:"operatorType" gorm:"type:varchar(128);comment:操作类型"` 15 | OperName string `json:"operName" gorm:"type:varchar(128);comment:操作者"` 16 | DeptName string `json:"deptName" gorm:"type:varchar(128);comment:部门名称"` 17 | OperUrl string `json:"operUrl" gorm:"type:varchar(255);comment:访问地址"` 18 | OperIp string `json:"operIp" gorm:"type:varchar(128);comment:客户端ip"` 19 | OperLocation string `json:"operLocation" gorm:"type:varchar(128);comment:访问位置"` 20 | OperParam string `json:"operParam" gorm:"type:text;comment:请求参数"` 21 | Status string `json:"status" gorm:"type:varchar(4);comment:操作状态 1:正常 2:关闭"` 22 | OperTime time.Time `json:"operTime" gorm:"type:timestamp;comment:操作时间"` 23 | JsonResult string `json:"jsonResult" gorm:"type:varchar(255);comment:返回数据"` 24 | Remark string `json:"remark" gorm:"type:varchar(255);comment:备注"` 25 | LatencyTime string `json:"latencyTime" gorm:"type:varchar(128);comment:耗时"` 26 | UserAgent string `json:"userAgent" gorm:"type:varchar(255);comment:ua"` 27 | CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` 28 | UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` 29 | ControlBy 30 | } 31 | 32 | func (SysOperaLog) TableName() string { 33 | return "sys_opera_log" 34 | } 35 | -------------------------------------------------------------------------------- /template/router.template: -------------------------------------------------------------------------------- 1 | package router 2 | 3 | 4 | import ( 5 | "github.com/gin-gonic/gin" 6 | _ "github.com/gin-gonic/gin" 7 | log "github.com/go-admin-team/go-admin-core/logger" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | // "github.com/go-admin-team/go-admin-core/sdk/pkg" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 11 | jwt "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 12 | common "smart-api/common/middleware" 13 | "os" 14 | ) 15 | 16 | var ( 17 | routerNoCheckRole = make([]func(*gin.RouterGroup), 0) 18 | routerCheckRole = make([]func(v1 *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware), 0) 19 | ) 20 | 21 | // InitRouter 路由初始化 22 | func InitRouter() { 23 | var r *gin.Engine 24 | h := sdk.Runtime.GetEngine() 25 | if h == nil { 26 | h = gin.New() 27 | sdk.Runtime.SetEngine(h) 28 | } 29 | switch h.(type) { 30 | case *gin.Engine: 31 | r = h.(*gin.Engine) 32 | default: 33 | log.Fatal("not support other engine") 34 | os.Exit(-1) 35 | } 36 | 37 | // the jwt middleware 38 | authMiddleware, err := common.AuthInit() 39 | if err != nil { 40 | log.Fatalf("JWT Init Error, %s", err.Error()) 41 | } 42 | 43 | // 注册业务路由 44 | InitBusinessRouter(r, authMiddleware) 45 | } 46 | 47 | func InitBusinessRouter(r *gin.Engine, authMiddleware *jwt.GinJWTMiddleware) *gin.Engine { 48 | 49 | // 无需认证的路由 50 | noCheckRoleRouter(r) 51 | // 需要认证的路由 52 | checkRoleRouter(r, authMiddleware) 53 | 54 | return r 55 | } 56 | 57 | // noCheckRoleRouter 无需认证的路由 58 | func noCheckRoleRouter(r *gin.Engine) { 59 | // 可根据业务需求来设置接口版本 60 | v := r.Group("/api/v1") 61 | 62 | for _, f := range routerNoCheckRole { 63 | f(v) 64 | } 65 | } 66 | 67 | // checkRoleRouter 需要认证的路由 68 | func checkRoleRouter(r *gin.Engine, authMiddleware *jwtauth.GinJWTMiddleware) { 69 | // 可根据业务需求来设置接口版本 70 | v := r.Group("/api/v1") 71 | 72 | for _, f := range routerCheckRole { 73 | f(v, authMiddleware) 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /app/other/apis/tools/db_tables.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "errors" 5 | "github.com/gin-gonic/gin" 6 | "github.com/go-admin-team/go-admin-core/sdk/config" 7 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 8 | _ "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 9 | 10 | "smart-api/app/other/models/tools" 11 | ) 12 | 13 | // GetDBTableList 分页列表数据 14 | // @Summary 分页列表数据 / page list data 15 | // @Description 数据库表分页列表 / database table page list 16 | // @Tags 工具 / 生成工具 17 | // @Param tableName query string false "tableName / 数据表名称" 18 | // @Param pageSize query int false "pageSize / 页条数" 19 | // @Param pageIndex query int false "pageIndex / 页码" 20 | // @Success 200 {object} response.Response "{"code": 200, "data": [...]}" 21 | // @Router /api/v1/db/tables/page [get] 22 | func (e Gen) GetDBTableList(c *gin.Context) { 23 | //var res response.Response 24 | var data tools.DBTables 25 | var err error 26 | var pageSize = 10 27 | var pageIndex = 1 28 | e.Context = c 29 | log := e.GetLogger() 30 | if config.DatabaseConfig.Driver == "sqlite3" || config.DatabaseConfig.Driver == "postgres" { 31 | err = errors.New("对不起,sqlite3 或 postgres 不支持代码生成!") 32 | log.Warn(err) 33 | e.Error(403, err, "") 34 | return 35 | } 36 | 37 | if size := c.Request.FormValue("pageSize"); size != "" { 38 | pageSize, err = pkg.StringToInt(size) 39 | } 40 | 41 | if index := c.Request.FormValue("pageIndex"); index != "" { 42 | pageIndex, err = pkg.StringToInt(index) 43 | } 44 | 45 | db, err := pkg.GetOrm(c) 46 | if err != nil { 47 | log.Errorf("get db connection error, %s", err.Error()) 48 | e.Error(500, err, "数据库连接获取失败") 49 | return 50 | } 51 | 52 | data.TableName = c.Request.FormValue("tableName") 53 | result, count, err := data.GetPage(db, pageSize, pageIndex) 54 | if err != nil { 55 | log.Errorf("GetPage error, %s", err.Error()) 56 | e.Error(500, err, "") 57 | return 58 | } 59 | e.PageOK(result, count, pageIndex, pageSize, "查询成功") 60 | } 61 | -------------------------------------------------------------------------------- /app/smart/service/dto/order_category.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "smart-api/app/smart/models" 5 | common "smart-api/common/models" 6 | ) 7 | 8 | type OrderCategoryInsertReq struct { 9 | ID int `uri:"id" comment:"编码"` // 编码 10 | Name string `json:"name" comment:"标题"` // 标题 11 | Creator string `json:"creator" comment:"创建人"` // 创建人 12 | ChineseName string `json:"chineseName" comment:"中文名称"` //中文名称 13 | common.ControlBy 14 | } 15 | 16 | func (s *OrderCategoryInsertReq) Generate(model *models.OrderCategory) { 17 | if s.ID != 0 { 18 | model.ID = s.ID 19 | } 20 | model.Name = s.Name 21 | model.Creator = s.Creator 22 | model.ChineseName = s.ChineseName 23 | model.ControlBy = s.ControlBy 24 | } 25 | 26 | // GetId 获取数据对应的ID 27 | func (s *OrderCategoryInsertReq) GetId() interface{} { 28 | return s.ID 29 | } 30 | 31 | type OrderCategoryUpdateReq struct { 32 | ID int `uri:"id" comment:"编码"` // 编码 33 | Name string `json:"name" comment:"标题"` // 标题 34 | Regenerator string `json:"regenerator" comment:"更新人"` // 更新人 35 | ChineseName string `json:"chineseName" comment:"中文名称"` //中文名称 36 | common.ControlBy 37 | } 38 | 39 | // Generate 结构体数据转化 从 SysDeptControl 至 SysDept 对应的模型 40 | func (s *OrderCategoryUpdateReq) Generate(model *models.OrderCategory) { 41 | if s.ID != 0 { 42 | model.ID = s.ID 43 | } 44 | model.Name = s.Name 45 | model.Regenerator = s.Regenerator 46 | model.ChineseName = s.ChineseName 47 | model.ControlBy = s.ControlBy 48 | } 49 | 50 | // GetId 获取数据对应的ID 51 | func (s *OrderCategoryUpdateReq) GetId() interface{} { 52 | return s.ID 53 | } 54 | 55 | type OrderCategoryGetReq struct { 56 | Id int `uri:"id"` 57 | } 58 | 59 | func (s *OrderCategoryGetReq) GetId() interface{} { 60 | return s.Id 61 | } 62 | 63 | type OrderCategoryDeleteReq struct { 64 | Id int `json:"id"` 65 | } 66 | 67 | func (s *OrderCategoryDeleteReq) GetId() interface{} { 68 | return s.Id 69 | } 70 | -------------------------------------------------------------------------------- /common/utils/machinehealth.go: -------------------------------------------------------------------------------- 1 | package utils 2 | 3 | import ( 4 | "fmt" 5 | "gorm.io/gorm" 6 | "gorm.io/gorm/logger" 7 | "smart-api/app/smart/models" 8 | "time" 9 | ) 10 | 11 | type MachineService struct { 12 | Orm *gorm.DB 13 | } 14 | 15 | // 测试机器连接并更新心跳字段 16 | func (s *MachineService) TestMachine(machine *models.ExecMachine) error { 17 | var err error 18 | 19 | // 使用 TCP 端口探测 20 | connTest := MachineConn{} 21 | err = connTest.testTCPPort(machine.Ip, machine.Port) 22 | if err != nil { 23 | // 连接失败,更新机器状态为 2 24 | updateErr := s.Orm.Model(machine).UpdateColumns(map[string]interface{}{ 25 | "status": 2, // 2 表示连接失败 26 | }).Error 27 | if updateErr != nil { 28 | return fmt.Errorf("failed to update status for machine ID '%v' after connection failure: %v", machine.ID, updateErr) 29 | } 30 | // 返回连接失败错误 31 | return fmt.Errorf("TCP connection test failed: %v", err) 32 | } 33 | 34 | // 连接成功,更新心跳时间和状态为正常 35 | err = s.Orm.Model(machine).UpdateColumns(map[string]interface{}{ 36 | "heartbeat": time.Now(), // 更新心跳时间 37 | "status": 1, // 1 表示连接正常 38 | }).Error 39 | if err != nil { 40 | return fmt.Errorf("failed to update heartbeat for machine ID '%v': %v", machine.ID, err) 41 | } 42 | 43 | return nil 44 | } 45 | 46 | // 检测所有机器状态 47 | func (s *MachineService) CheckAllMachines() { 48 | // 暂时禁用日志 49 | s.Orm = s.Orm.Session(&gorm.Session{ 50 | Logger: logger.Default.LogMode(logger.Silent), 51 | }) 52 | 53 | var machines []models.ExecMachine 54 | // 从数据库中获取所有机器 55 | err := s.Orm.Find(&machines).Error 56 | if err != nil { 57 | fmt.Printf("failed to retrieve machines: %v\n", err) 58 | return 59 | } 60 | 61 | // 逐台机器进行状态检查 62 | for _, machine := range machines { 63 | err = s.TestMachine(&machine) 64 | if err != nil { 65 | fmt.Printf("failed to test connection for machine ID '%v': %v\n", machine.ID, err) 66 | } 67 | } 68 | // 如果需要恢复日志输出,可重新设置 69 | // s.Orm = s.Orm.Session(&gorm.Session{Logger: logger.Default.LogMode(logger.Info)}) 70 | 71 | } 72 | -------------------------------------------------------------------------------- /common/middleware/permission.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | import ( 4 | "github.com/casbin/casbin/v2/util" 5 | "net/http" 6 | 7 | "github.com/gin-gonic/gin" 8 | "github.com/go-admin-team/go-admin-core/sdk" 9 | "github.com/go-admin-team/go-admin-core/sdk/api" 10 | "github.com/go-admin-team/go-admin-core/sdk/pkg/jwtauth" 11 | "github.com/go-admin-team/go-admin-core/sdk/pkg/response" 12 | ) 13 | 14 | // AuthCheckRole 权限检查中间件 15 | func AuthCheckRole() gin.HandlerFunc { 16 | return func(c *gin.Context) { 17 | log := api.GetRequestLogger(c) 18 | data, _ := c.Get(jwtauth.JwtPayloadKey) 19 | v := data.(jwtauth.MapClaims) 20 | e := sdk.Runtime.GetCasbinKey(c.Request.Host) 21 | // 不用鉴权的接口信息 settings.go 22 | var res, casbinExclude bool 23 | var err error 24 | //检查权限 25 | if v["rolekey"] == "admin" { 26 | res = true 27 | c.Next() 28 | return 29 | } 30 | // 不做验证的接口信息 31 | for _, i := range CasbinExclude { 32 | if util.KeyMatch2(c.Request.URL.Path, i.Url) && c.Request.Method == i.Method { 33 | casbinExclude = true 34 | break 35 | } 36 | } 37 | if casbinExclude { 38 | log.Infof("Casbin exclusion, no validation method:%s path:%s", c.Request.Method, c.Request.URL.Path) 39 | c.Next() 40 | return 41 | } 42 | res, err = e.Enforce(v["rolekey"], c.Request.URL.Path, c.Request.Method) 43 | if err != nil { 44 | log.Errorf("AuthCheckRole error:%s method:%s path:%s", err, c.Request.Method, c.Request.URL.Path) 45 | response.Error(c, 500, err, "") 46 | return 47 | } 48 | 49 | if res { 50 | log.Infof("isTrue: %v role: %s method: %s path: %s", res, v["rolekey"], c.Request.Method, c.Request.URL.Path) 51 | c.Next() 52 | } else { 53 | log.Warnf("isTrue: %v role: %s method: %s path: %s message: %s", res, v["rolekey"], c.Request.Method, c.Request.URL.Path, "当前request无权限,请管理员确认!") 54 | c.JSON(http.StatusOK, gin.H{ 55 | "code": 403, 56 | "msg": "对不起,您没有该接口访问权限,请联系管理员", 57 | }) 58 | c.Abort() 59 | return 60 | } 61 | 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/initdb.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "fmt" 5 | "io/ioutil" 6 | "log" 7 | "smart-api/common/global" 8 | "strings" 9 | 10 | "gorm.io/gorm" 11 | ) 12 | 13 | func InitDb(db *gorm.DB) (err error) { 14 | filePath := "config/db.sql" 15 | if global.Driver == "postgres" { 16 | filePath := "config/db.sql" 17 | if err = ExecSql(db, filePath); err != nil { 18 | return err 19 | } 20 | filePath = "config/pg.sql" 21 | err = ExecSql(db, filePath) 22 | } else if global.Driver == "mysql" { 23 | filePath = "config/db-begin-mysql.sql" 24 | if err = ExecSql(db, filePath); err != nil { 25 | return err 26 | } 27 | filePath = "config/db.sql" 28 | if err = ExecSql(db, filePath); err != nil { 29 | return err 30 | } 31 | filePath = "config/db-end-mysql.sql" 32 | err = ExecSql(db, filePath) 33 | } else { 34 | err = ExecSql(db, filePath) 35 | } 36 | return err 37 | } 38 | 39 | func ExecSql(db *gorm.DB, filePath string) error { 40 | sql, err := Ioutil(filePath) 41 | if err != nil { 42 | fmt.Println("数据库基础数据初始化脚本读取失败!原因:", err.Error()) 43 | return err 44 | } 45 | sqlList := strings.Split(sql, ";") 46 | for i := 0; i < len(sqlList)-1; i++ { 47 | if strings.Contains(sqlList[i], "--") { 48 | fmt.Println(sqlList[i]) 49 | continue 50 | } 51 | sql := strings.Replace(sqlList[i]+";", "\n", "", -1) 52 | sql = strings.TrimSpace(sql) 53 | if err = db.Exec(sql).Error; err != nil { 54 | log.Printf("error sql: %s", sql) 55 | if !strings.Contains(err.Error(), "Query was empty") { 56 | return err 57 | } 58 | } 59 | } 60 | return nil 61 | } 62 | 63 | func Ioutil(filePath string) (string, error) { 64 | if contents, err := ioutil.ReadFile(filePath); err == nil { 65 | //因为contents是[]byte类型,直接转换成string类型后会多一行空格,需要使用strings.Replace替换换行符 66 | result := strings.Replace(string(contents), "\n", "", 1) 67 | fmt.Println("Use ioutil.ReadFile to read a file:", result) 68 | return result, nil 69 | } else { 70 | return "", err 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/exec_machine.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/8/17 19:48 3 | package models 4 | 5 | import ( 6 | "smart-api/cmd/migrate/migration/models" 7 | models2 "smart-api/common/models" 8 | ) 9 | 10 | type ExecMachine struct { 11 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 12 | Ip string `gorm:"column:ip; type: varchar(15)" json:"ip" form:"ip"` // IP地址 13 | HostName string `gorm:"column:hostname; type: varchar(45)" json:"hostName" form:"hostName"` // 主机名 14 | UserName string `gorm:"column:username;type: varchar(45)" json:"userName" form:"username"` // 用户名 15 | PassWord string `gorm:"column:password;type: varchar(100)" json:"passWord" form:"password"` // 密码 16 | Port int `gorm:"column:port;" json:"port" form:"port"` // 端口 17 | Heartbeat models2.JSONTime `gorm:"column:heartbeat;type:timestamp;default:NULL" json:"heartbeat" form:"heartbeat"` // 最近一次心跳时间 18 | Status int `gorm:"column:status;" json:"status" form:"status"` // 状态 19 | AuthType string `gorm:"column:auth_type;type:varchar(10)" json:"authType" form:"authType"` // 认证方式:1=用户名密码,2=公私钥 20 | PrivateKey string `gorm:"column:private_key;type:varchar(4096)" json:"privateKey" form:"privateKey"` // 私钥内容 21 | Creator string `gorm:"column:creator; type: varchar(45)" json:"creator" form:"creator"` // 创建者 22 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 23 | Description string `gorm:"column:description; type: longtext" json:"description" form:"description"` // 描述信息 24 | models.ControlBy 25 | models.ModelTime 26 | } 27 | 28 | func (*ExecMachine) TableName() string { 29 | return "exec_machine" 30 | } 31 | -------------------------------------------------------------------------------- /app/system/models/sys_menu.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import "smart-api/common/models" 4 | 5 | type SysMenu struct { 6 | MenuId int `json:"menuId" gorm:"primaryKey;autoIncrement"` 7 | MenuName string `json:"menuName" gorm:"size:128;"` 8 | Title string `json:"title" gorm:"size:128;"` 9 | Icon string `json:"icon" gorm:"size:128;"` 10 | Path string `json:"path" gorm:"size:128;"` 11 | Paths string `json:"paths" gorm:"size:128;"` 12 | MenuType string `json:"menuType" gorm:"size:1;"` 13 | Action string `json:"action" gorm:"size:16;"` 14 | Permission string `json:"permission" gorm:"size:255;"` 15 | ParentId int `json:"parentId" gorm:"size:11;"` 16 | NoCache bool `json:"noCache" gorm:"size:8;"` 17 | Breadcrumb string `json:"breadcrumb" gorm:"size:255;"` 18 | Component string `json:"component" gorm:"size:255;"` 19 | Sort int `json:"sort" gorm:"size:4;"` 20 | Visible string `json:"visible" gorm:"size:1;"` 21 | IsFrame string `json:"isFrame" gorm:"size:1;DEFAULT:0;"` 22 | SysApi []SysApi `json:"sysApi" gorm:"many2many:sys_menu_api_rule"` 23 | Apis []int `json:"apis" gorm:"-"` 24 | DataScope string `json:"dataScope" gorm:"-"` 25 | Params string `json:"params" gorm:"-"` 26 | RoleId int `gorm:"-"` 27 | Children []SysMenu `json:"children,omitempty" gorm:"-"` 28 | IsSelect bool `json:"is_select" gorm:"-"` 29 | models.ControlBy 30 | models.ModelTime 31 | } 32 | 33 | type SysMenuSlice []SysMenu 34 | 35 | func (x SysMenuSlice) Len() int { return len(x) } 36 | func (x SysMenuSlice) Less(i, j int) bool { return x[i].Sort < x[j].Sort } 37 | func (x SysMenuSlice) Swap(i, j int) { x[i], x[j] = x[j], x[i] } 38 | 39 | func (*SysMenu) TableName() string { 40 | return "sys_menu" 41 | } 42 | 43 | func (e *SysMenu) Generate() models.ActiveRecord { 44 | o := *e 45 | return &o 46 | } 47 | 48 | func (e *SysMenu) GetId() interface{} { 49 | return e.MenuId 50 | } 51 | -------------------------------------------------------------------------------- /app/smart/service/dto/order_statistics.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/9/25 20:28 3 | package dto 4 | 5 | type OrderStatisticsResponse struct { 6 | TotalOrders int `json:"totalOrders"` // 总工单数 7 | TotalOrdersWeekOverWeek float64 `json:"totalOrdersWeekOverWeek"` // 总工单数周同比 8 | TotalOrdersDayOverDay float64 `json:"totalOrdersDayOverDay"` // 总工单数日同比 9 | CompletedOrders int `json:"completedOrders"` // 已完结工单 10 | CompletionRate int `json:"completionRate"` // 完成率 11 | PendingOrders int `json:"pendingOrders"` // 待办工单 12 | CurrentHandlerOrders int `json:"currentHandlerOrders"` // 当前处理的工单 13 | CurrentHandlerWeekOverWeek float64 `json:"currentHandlerWeekOverWeek"` // 当前处理工单周同比 14 | CurrentHandlerDayOverDay float64 `json:"currentHandlerDayOverDay"` // 当前处理工单日同比 15 | DailyAverage int64 `json:"dailyAverage"` // 日均工单数 16 | } 17 | 18 | type OrderCountByPeriodResponse struct { 19 | OrderStats []OrderCountStat `json:"orderStats"` // 工单统计 20 | SubmissionRanking []SubmissionRanking `json:"submissionRanking"` // 个人提交排行榜 21 | } 22 | 23 | type OrderCountStat struct { 24 | Date string `json:"date"` // 日期 25 | Total int `json:"total"` // 所有 26 | Completed int `json:"completed"` // 已完成的 27 | UnderWay int `json:"underWay"` // 进行中的 28 | } 29 | 30 | type SubmissionRanking struct { 31 | Name string `json:"name"` // 创建人 32 | Total int `json:"total"` // 提交数量 33 | } 34 | 35 | type OrderRatingsResponse struct { 36 | RatingsStats []RatingStat `json:"ratingsStats"` // 评分统计 37 | RatingRanking []RatingRanking `json:"ratingRanking"` // 个人评分排行榜 38 | } 39 | 40 | type RatingStat struct { 41 | Date string `json:"date"` // 日期 42 | Average float64 `json:"average"` // 平均评分 43 | } 44 | 45 | type RatingRanking struct { 46 | Name string `json:"name"` // 评价人 47 | Score float64 `json:"score"` // 平均评分 48 | } 49 | -------------------------------------------------------------------------------- /common/dto/search.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "github.com/go-admin-team/go-admin-core/tools/search" 5 | "gorm.io/gorm" 6 | "smart-api/common/global" 7 | ) 8 | 9 | type GeneralDelDto struct { 10 | Id int `uri:"id" json:"id" validate:"required"` 11 | Ids []int `json:"ids"` 12 | } 13 | 14 | func (g GeneralDelDto) GetIds() []int { 15 | ids := make([]int, 0) 16 | if g.Id != 0 { 17 | ids = append(ids, g.Id) 18 | } 19 | if len(g.Ids) > 0 { 20 | for _, id := range g.Ids { 21 | if id > 0 { 22 | ids = append(ids, id) 23 | } 24 | } 25 | } else { 26 | if g.Id > 0 { 27 | ids = append(ids, g.Id) 28 | } 29 | } 30 | if len(ids) <= 0 { 31 | //方式全部删除 32 | ids = append(ids, 0) 33 | } 34 | return ids 35 | } 36 | 37 | type GeneralGetDto struct { 38 | Id int `uri:"id" json:"id" validate:"required"` 39 | } 40 | 41 | func MakeCondition(q interface{}) func(db *gorm.DB) *gorm.DB { 42 | return func(db *gorm.DB) *gorm.DB { 43 | condition := &search.GormCondition{ 44 | GormPublic: search.GormPublic{}, 45 | Join: make([]*search.GormJoin, 0), 46 | } 47 | 48 | search.ResolveSearchQuery(global.Driver, q, condition) 49 | for _, join := range condition.Join { 50 | if join == nil { 51 | continue 52 | } 53 | db = db.Joins(join.JoinOn) 54 | for k, v := range join.Where { 55 | db = db.Where(k, v...) 56 | } 57 | for k, v := range join.Or { 58 | db = db.Or(k, v...) 59 | } 60 | for _, o := range join.Order { 61 | db = db.Order(o) 62 | } 63 | } 64 | for k, v := range condition.Where { 65 | db = db.Where(k, v...) 66 | } 67 | for k, v := range condition.Or { 68 | db = db.Or(k, v...) 69 | } 70 | for _, o := range condition.Order { 71 | db = db.Order(o) 72 | } 73 | return db 74 | } 75 | } 76 | 77 | func Paginate(pageSize, pageIndex int) func(db *gorm.DB) *gorm.DB { 78 | return func(db *gorm.DB) *gorm.DB { 79 | offset := (pageIndex - 1) * pageSize 80 | if offset < 0 { 81 | offset = 0 82 | } 83 | return db.Offset(offset).Limit(pageSize) 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /common/database/initialize.go: -------------------------------------------------------------------------------- 1 | package database 2 | 3 | import ( 4 | "time" 5 | 6 | log "github.com/go-admin-team/go-admin-core/logger" 7 | "github.com/go-admin-team/go-admin-core/sdk" 8 | toolsConfig "github.com/go-admin-team/go-admin-core/sdk/config" 9 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 10 | mycasbin "github.com/go-admin-team/go-admin-core/sdk/pkg/casbin" 11 | toolsDB "github.com/go-admin-team/go-admin-core/tools/database" 12 | . "github.com/go-admin-team/go-admin-core/tools/gorm/logger" 13 | "gorm.io/gorm" 14 | "gorm.io/gorm/logger" 15 | "gorm.io/gorm/schema" 16 | 17 | "smart-api/common/global" 18 | ) 19 | 20 | // Setup 配置数据库 21 | func Setup() { 22 | for k := range toolsConfig.DatabasesConfig { 23 | setupSimpleDatabase(k, toolsConfig.DatabasesConfig[k]) 24 | } 25 | } 26 | 27 | func setupSimpleDatabase(host string, c *toolsConfig.Database) { 28 | if global.Driver == "" { 29 | global.Driver = c.Driver 30 | } 31 | log.Infof("%s => %s", host, pkg.Green(c.Source)) 32 | registers := make([]toolsDB.ResolverConfigure, len(c.Registers)) 33 | for i := range c.Registers { 34 | registers[i] = toolsDB.NewResolverConfigure( 35 | c.Registers[i].Sources, 36 | c.Registers[i].Replicas, 37 | c.Registers[i].Policy, 38 | c.Registers[i].Tables) 39 | } 40 | resolverConfig := toolsDB.NewConfigure(c.Source, c.MaxIdleConns, c.MaxOpenConns, c.ConnMaxIdleTime, c.ConnMaxLifeTime, registers) 41 | db, err := resolverConfig.Init(&gorm.Config{ 42 | NamingStrategy: schema.NamingStrategy{ 43 | SingularTable: true, 44 | }, 45 | Logger: New( 46 | logger.Config{ 47 | SlowThreshold: time.Second, 48 | Colorful: true, 49 | LogLevel: logger.LogLevel( 50 | log.DefaultLogger.Options().Level.LevelForGorm()), 51 | }, 52 | ), 53 | }, opens[c.Driver]) 54 | 55 | if err != nil { 56 | log.Fatal(pkg.Red(c.Driver+" connect error :"), err) 57 | } else { 58 | log.Info(pkg.Green(c.Driver + " connect success !")) 59 | } 60 | 61 | e := mycasbin.Setup(db, "") 62 | 63 | sdk.Runtime.SetDb(host, db) 64 | sdk.Runtime.SetCasbin(host, e) 65 | } 66 | -------------------------------------------------------------------------------- /app/smart/models/exec_machine.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/8/27 21:14 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | ) 8 | 9 | type ExecMachine struct { 10 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 11 | Ip string `gorm:"column:ip; type: varchar(15)" json:"ip" form:"ip"` // IP地址 12 | HostName string `gorm:"column:hostname; type: varchar(45)" json:"hostName" form:"hostName"` // 主机名 13 | UserName string `gorm:"column:username;type: varchar(45)" json:"userName" form:"username"` // 用户名 14 | PassWord string `gorm:"column:password;type: varchar(100)" json:"passWord" form:"password"` // 密码 15 | Port int `gorm:"column:port;" json:"port" form:"port"` // 端口 16 | Status int `gorm:"column:status;" json:"status" form:"status"` // 状态 1 为在线 2为离线 17 | AuthType string `gorm:"column:auth_type;type:varchar(10)" json:"authType" form:"authType"` // 认证方式:1=用户名密码,2=公私钥 18 | PrivateKey string `gorm:"column:private_key;type:varchar(4096)" json:"privateKey" form:"privateKey"` // 私钥内容 19 | Creator string `gorm:"column:creator; type: varchar(45)" json:"creator" form:"creator"` // 创建者 20 | Heartbeat models.JSONTime `gorm:"column:heartbeat;type:timestamp;default:NULL" json:"heartbeat" form:"heartbeat"` // 最近一次心跳时间 21 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 22 | Description string `gorm:"column:description; type: longtext" json:"description" form:"description"` // 描述信息 23 | models.ControlBy 24 | models.ModelTime 25 | } 26 | 27 | func (*ExecMachine) TableName() string { 28 | return "exec_machine" 29 | } 30 | 31 | func (e *ExecMachine) Generate() models.ActiveRecord { 32 | o := *e 33 | return &o 34 | } 35 | 36 | func (e *ExecMachine) GetId() interface{} { 37 | return e.ID 38 | } 39 | 40 | -------------------------------------------------------------------------------- /app/jobs/models/sys_job.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "gorm.io/gorm" 5 | "smart-api/common/models" 6 | ) 7 | 8 | type SysJob struct { 9 | JobId int `json:"jobId" gorm:"primaryKey;autoIncrement"` // 编码 10 | JobName string `json:"jobName" gorm:"size:255;"` // 名称 11 | JobGroup string `json:"jobGroup" gorm:"size:255;"` // 任务分组 12 | JobType int `json:"jobType" gorm:"size:1;"` // 任务类型 13 | CronExpression string `json:"cronExpression" gorm:"size:255;"` // cron表达式 14 | InvokeTarget string `json:"invokeTarget" gorm:"size:255;"` // 调用目标 15 | Args string `json:"args" gorm:"size:255;"` // 目标参数 16 | MisfirePolicy int `json:"misfirePolicy" gorm:"size:255;"` // 执行策略 17 | Concurrent int `json:"concurrent" gorm:"size:1;"` // 是否并发 18 | Status int `json:"status" gorm:"size:1;"` // 状态 19 | EntryId int `json:"entry_id" gorm:"size:11;"` // job启动时返回的id 20 | models.ControlBy 21 | models.ModelTime 22 | 23 | DataScope string `json:"dataScope" gorm:"-"` 24 | } 25 | 26 | func (*SysJob) TableName() string { 27 | return "sys_job" 28 | } 29 | 30 | func (e *SysJob) Generate() models.ActiveRecord { 31 | o := *e 32 | return &o 33 | } 34 | 35 | func (e *SysJob) GetId() interface{} { 36 | return e.JobId 37 | } 38 | 39 | func (e *SysJob) SetCreateBy(createBy int) { 40 | e.CreateBy = createBy 41 | } 42 | 43 | func (e *SysJob) SetUpdateBy(updateBy int) { 44 | e.UpdateBy = updateBy 45 | } 46 | 47 | func (e *SysJob) GetList(tx *gorm.DB, list interface{}) (err error) { 48 | return tx.Table(e.TableName()).Where("status = ?", 2).Find(list).Error 49 | } 50 | 51 | // Update 更新SysJob 52 | func (e *SysJob) Update(tx *gorm.DB, id interface{}) (err error) { 53 | return tx.Table(e.TableName()).Where(id).Updates(&e).Error 54 | } 55 | 56 | func (e *SysJob) RemoveAllEntryID(tx *gorm.DB) (update SysJob, err error) { 57 | if err = tx.Table(e.TableName()).Where("entry_id > ?", 0).Update("entry_id", 0).Error; err != nil { 58 | return 59 | } 60 | return 61 | } 62 | -------------------------------------------------------------------------------- /common/middleware/settings.go: -------------------------------------------------------------------------------- 1 | package middleware 2 | 3 | type UrlInfo struct { 4 | Url string 5 | Method string 6 | } 7 | 8 | // CasbinExclude casbin 排除的路由列表 9 | var CasbinExclude = []UrlInfo{ 10 | {Url: "/api/v1/dict/type-option-select", Method: "GET"}, 11 | {Url: "/api/v1/dict-data/option-select", Method: "GET"}, 12 | {Url: "/api/v1/deptTree", Method: "GET"}, 13 | {Url: "/api/v1/db/tables/page", Method: "GET"}, 14 | {Url: "/api/v1/db/columns/page", Method: "GET"}, 15 | {Url: "/api/v1/gen/toproject/:tableId", Method: "GET"}, 16 | {Url: "/api/v1/gen/todb/:tableId", Method: "GET"}, 17 | {Url: "/api/v1/gen/tabletree", Method: "GET"}, 18 | {Url: "/api/v1/gen/preview/:tableId", Method: "GET"}, 19 | {Url: "/api/v1/gen/apitofile/:tableId", Method: "GET"}, 20 | {Url: "/api/v1/getCaptcha", Method: "GET"}, 21 | {Url: "/api/v1/getinfo", Method: "GET"}, 22 | {Url: "/api/v1/menuTreeselect", Method: "GET"}, 23 | {Url: "/api/v1/menurole", Method: "GET"}, 24 | {Url: "/api/v1/menuids", Method: "GET"}, 25 | {Url: "/api/v1/roleMenuTreeselect/:roleId", Method: "GET"}, 26 | {Url: "/api/v1/roleDeptTreeselect/:roleId", Method: "GET"}, 27 | {Url: "/api/v1/refresh_token", Method: "GET"}, 28 | {Url: "/api/v1/configKey/:configKey", Method: "GET"}, 29 | {Url: "/api/v1/app-config", Method: "GET"}, 30 | {Url: "/api/v1/user/profile", Method: "GET"}, 31 | {Url: "/info", Method: "GET"}, 32 | {Url: "/api/v1/login", Method: "POST"}, 33 | {Url: "/api/v1/logout", Method: "POST"}, 34 | {Url: "/api/v1/user/avatar", Method: "POST"}, 35 | {Url: "/api/v1/user/pwd", Method: "PUT"}, 36 | {Url: "/api/v1/metrics", Method: "GET"}, 37 | {Url: "/api/v1/health", Method: "GET"}, 38 | {Url: "/", Method: "GET"}, 39 | {Url: "/api/v1/server-monitor", Method: "GET"}, 40 | {Url: "/api/v1/public/uploadFile", Method: "POST"}, 41 | {Url: "/api/v1/user/pwd/set", Method: "PUT"}, 42 | {Url: "/api/v1/sys-user", Method: "PUT"}, 43 | {Url: "/api/v1/post", Method: "GET"}, 44 | {Url: "/api/v1/statistics/orders", Method: "GET"}, 45 | {Url: "/api/v1/statistics/orders/count", Method: "GET"}, 46 | {Url: "/api/v1/statistics/ratings", Method: "GET"}, 47 | {Url: "/api/v1/favorite", Method: "GET"}, 48 | } 49 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ master ] 6 | pull_request: 7 | branches: [ master ] 8 | 9 | env: 10 | IMAGE_NAME: registry.ap-northeast-1.aliyuncs.com/smart/smart-api # 镜像名称 11 | TAG: ${{ github.sha }} 12 | IMAGE_NAME_TAG: registry.ap-northeast-1.aliyuncs.com/smart/smart-api:${{ github.sha }} 13 | 14 | jobs: 15 | 16 | build: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v3 20 | 21 | - name: Set up Go 22 | uses: actions/setup-go@v3 23 | with: 24 | go-version: 1.24.2 25 | cache: true 26 | 27 | - name: Tidy 28 | run: go mod tidy 29 | 30 | - name: Build 31 | run: env CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -tags "sqlite3,json1" --ldflags "-extldflags -static" -o main . 32 | 33 | - name: Build the Docker image and push 34 | run: | 35 | docker login --username=${{ secrets.DOCKER_USERNAME }} registry.ap-northeast-1.aliyuncs.com --password=${{ secrets.DOCKER_PASSWORD }} 36 | echo "************ docker login end" 37 | docker build -t smart-api:latest . 38 | echo "************ docker build end" 39 | docker tag smart-api ${{ env.IMAGE_NAME_TAG }} 40 | echo "************ docker tag end" 41 | docker images 42 | echo "************ docker images end" 43 | docker push ${{ env.IMAGE_NAME_TAG }} # 推送 44 | echo "************ docker push end" 45 | 46 | - name: Restart server # 第五步,重启服务 47 | uses: appleboy/ssh-action@master 48 | env: 49 | GITHUB_SHA_X: ${GITHUB_SHA} 50 | with: 51 | host: ${{ secrets.SSH_HOST }} # 下面三个配置与上一步类似 52 | username: ${{ secrets.SSH_USERNAME }} 53 | key: ${{ secrets.DEPLOY_KEY }} 54 | # 重启的脚本,根据自身情况做相应改动,一般要做的是migrate数据库以及重启服务器 55 | script: | 56 | sudo docker rm -f smart-api 57 | sudo docker login --username=${{ secrets.DOCKER_USERNAME }} registry.ap-northeast-1.aliyuncs.com --password=${{ secrets.DOCKER_PASSWORD }} 58 | sudo docker run -d -p 8000:8000 --name smart-api ${{ env.IMAGE_NAME_TAG }} 59 | -------------------------------------------------------------------------------- /app/system/service/dto/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package dto 2 | 3 | import ( 4 | "time" 5 | 6 | "smart-api/common/dto" 7 | ) 8 | 9 | type SysLoginLogGetPageReq struct { 10 | dto.Pagination `search:"-"` 11 | Username string `form:"username" search:"type:exact;column:username;table:sys_login_log" comment:"用户名"` 12 | Status string `form:"status" search:"type:exact;column:status;table:sys_login_log" comment:"状态"` 13 | Ipaddr string `form:"ipaddr" search:"type:exact;column:ipaddr;table:sys_login_log" comment:"ip地址"` 14 | LoginLocation string `form:"loginLocation" search:"type:exact;column:login_location;table:sys_login_log" comment:"归属地"` 15 | BeginTime string `form:"beginTime" search:"type:gte;column:ctime;table:sys_login_log" comment:"创建时间"` 16 | EndTime string `form:"endTime" search:"type:lte;column:ctime;table:sys_login_log" comment:"创建时间"` 17 | SysLoginLogOrder 18 | } 19 | 20 | type SysLoginLogOrder struct { 21 | CreatedAtOrder string `search:"type:order;column:created_at;table:sys_login_log" form:"createdAtOrder"` 22 | } 23 | 24 | func (m *SysLoginLogGetPageReq) GetNeedSearch() interface{} { 25 | return *m 26 | } 27 | 28 | type SysLoginLogControl struct { 29 | ID int `uri:"Id" comment:"主键"` // 主键 30 | Username string `json:"username" comment:"用户名"` 31 | Status string `json:"status" comment:"状态"` 32 | Ipaddr string `json:"ipaddr" comment:"ip地址"` 33 | LoginLocation string `json:"loginLocation" comment:"归属地"` 34 | Browser string `json:"browser" comment:"浏览器"` 35 | Os string `json:"os" comment:"系统"` 36 | Platform string `json:"platform" comment:"固件"` 37 | LoginTime time.Time `json:"loginTime" comment:"登录时间"` 38 | Remark string `json:"remark" comment:"备注"` 39 | Msg string `json:"msg" comment:"信息"` 40 | } 41 | 42 | type SysLoginLogGetReq struct { 43 | Id int `uri:"id"` 44 | } 45 | 46 | func (s *SysLoginLogGetReq) GetId() interface{} { 47 | return s.Id 48 | } 49 | 50 | // SysLoginLogDeleteReq 功能删除请求参数 51 | type SysLoginLogDeleteReq struct { 52 | Ids []int `json:"ids"` 53 | } 54 | 55 | func (s *SysLoginLogDeleteReq) GetId() interface{} { 56 | return s.Ids 57 | } 58 | -------------------------------------------------------------------------------- /app/other/models/tools/db_tables.go: -------------------------------------------------------------------------------- 1 | package tools 2 | 3 | import ( 4 | "errors" 5 | "github.com/go-admin-team/go-admin-core/sdk/pkg" 6 | 7 | "gorm.io/gorm" 8 | 9 | config2 "github.com/go-admin-team/go-admin-core/sdk/config" 10 | ) 11 | 12 | type DBTables struct { 13 | TableName string `gorm:"column:TABLE_NAME" json:"tableName"` 14 | Engine string `gorm:"column:ENGINE" json:"engine"` 15 | TableRows string `gorm:"column:TABLE_ROWS" json:"tableRows"` 16 | TableCollation string `gorm:"column:TABLE_COLLATION" json:"tableCollation"` 17 | CreateTime string `gorm:"column:CREATE_TIME" json:"createTime"` 18 | UpdateTime string `gorm:"column:UPDATE_TIME" json:"updateTime"` 19 | TableComment string `gorm:"column:TABLE_COMMENT" json:"tableComment"` 20 | } 21 | 22 | func (e *DBTables) GetPage(tx *gorm.DB, pageSize int, pageIndex int) ([]DBTables, int, error) { 23 | var doc []DBTables 24 | table := new(gorm.DB) 25 | var count int64 26 | 27 | if config2.DatabaseConfig.Driver == "mysql" { 28 | table = tx.Table("information_schema.tables") 29 | table = table.Where("TABLE_NAME not in (select table_name from `" + config2.GenConfig.DBName + "`.sys_tables) ") 30 | table = table.Where("table_schema= ? ", config2.GenConfig.DBName) 31 | 32 | if e.TableName != "" { 33 | table = table.Where("TABLE_NAME = ?", e.TableName) 34 | } 35 | if err := table.Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&doc).Offset(-1).Limit(-1).Count(&count).Error; err != nil { 36 | return nil, 0, err 37 | } 38 | } else { 39 | pkg.Assert(true, "目前只支持mysql数据库", 500) 40 | } 41 | 42 | //table.Count(&count) 43 | return doc, int(count), nil 44 | } 45 | 46 | func (e *DBTables) Get(tx *gorm.DB) (DBTables, error) { 47 | var doc DBTables 48 | if config2.DatabaseConfig.Driver == "mysql" { 49 | table := tx.Table("information_schema.tables") 50 | table = table.Where("table_schema= ? ", config2.GenConfig.DBName) 51 | if e.TableName == "" { 52 | return doc, errors.New("table name cannot be empty!") 53 | } 54 | table = table.Where("TABLE_NAME = ?", e.TableName) 55 | if err := table.First(&doc).Error; err != nil { 56 | return doc, err 57 | } 58 | } else { 59 | pkg.Assert(true, "目前只支持mysql数据库", 500) 60 | } 61 | return doc, nil 62 | } 63 | -------------------------------------------------------------------------------- /app/system/service/sys_opera_log.go: -------------------------------------------------------------------------------- 1 | package service 2 | 3 | import ( 4 | "errors" 5 | 6 | "smart-api/app/system/models" 7 | "smart-api/app/system/service/dto" 8 | cDto "smart-api/common/dto" 9 | 10 | "github.com/go-admin-team/go-admin-core/sdk/service" 11 | "gorm.io/gorm" 12 | ) 13 | 14 | type SysOperaLog struct { 15 | service.Service 16 | } 17 | 18 | // GetPage 获取SysOperaLog列表 19 | func (e *SysOperaLog) GetPage(c *dto.SysOperaLogGetPageReq, list *[]models.SysOperaLog, count *int64) error { 20 | var err error 21 | var data models.SysOperaLog 22 | 23 | err = e.Orm.Model(&data). 24 | Scopes( 25 | cDto.MakeCondition(c.GetNeedSearch()), 26 | cDto.Paginate(c.GetPageSize(), c.GetPageIndex()), 27 | ). 28 | Find(list).Limit(-1).Offset(-1). 29 | Count(count).Error 30 | if err != nil { 31 | e.Log.Errorf("Service GetSysOperaLogPage error:%s", err.Error()) 32 | return err 33 | } 34 | return nil 35 | } 36 | 37 | // Get 获取SysOperaLog对象 38 | func (e *SysOperaLog) Get(d *dto.SysOperaLogGetReq, model *models.SysOperaLog) error { 39 | var data models.SysOperaLog 40 | 41 | err := e.Orm.Model(&data). 42 | First(model, d.GetId()).Error 43 | if err != nil && errors.Is(err, gorm.ErrRecordNotFound) { 44 | err = errors.New("查看对象不存在或无权查看") 45 | e.Log.Errorf("Service GetSysOperaLog error:%s", err.Error()) 46 | return err 47 | } 48 | if err != nil { 49 | e.Log.Errorf("Service GetSysOperaLog error:%s", err.Error()) 50 | return err 51 | } 52 | return nil 53 | } 54 | 55 | // Insert 创建SysOperaLog对象 56 | func (e *SysOperaLog) Insert(model *models.SysOperaLog) error { 57 | var err error 58 | var data models.SysOperaLog 59 | 60 | err = e.Orm.Model(&data). 61 | Create(model).Error 62 | if err != nil { 63 | e.Log.Errorf("Service InsertSysOperaLog error:%s", err.Error()) 64 | return err 65 | } 66 | return nil 67 | } 68 | 69 | // Remove 删除SysOperaLog 70 | func (e *SysOperaLog) Remove(d *dto.SysOperaLogDeleteReq) error { 71 | var err error 72 | var data models.SysOperaLog 73 | 74 | db := e.Orm.Model(&data).Delete(&data, d.GetId()) 75 | if err = db.Error; err != nil { 76 | e.Log.Errorf("Service RemoveSysOperaLog error:%s", err.Error()) 77 | return err 78 | } 79 | if db.RowsAffected == 0 { 80 | return errors.New("无权删除该数据") 81 | } 82 | return nil 83 | } 84 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/sys_tables.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | type SysTables struct { 4 | TableId int `gorm:"primaryKey;autoIncrement" json:"tableId"` //表编码 5 | TBName string `gorm:"column:table_name;size:255;" json:"tableName"` //表名称 6 | TableComment string `gorm:"size:255;" json:"tableComment"` //表备注 7 | ClassName string `gorm:"size:255;" json:"className"` //类名 8 | TplCategory string `gorm:"size:255;" json:"tplCategory"` // 9 | PackageName string `gorm:"size:255;" json:"packageName"` //包名 10 | ModuleName string `gorm:"size:255;" json:"moduleName"` //go文件名 11 | ModuleFrontName string `gorm:"size:255;comment:前端文件名;" json:"moduleFrontName"` //前端文件名 12 | BusinessName string `gorm:"size:255;" json:"businessName"` // 13 | FunctionName string `gorm:"size:255;" json:"functionName"` //功能名称 14 | FunctionAuthor string `gorm:"size:255;" json:"functionAuthor"` //功能作者 15 | PkColumn string `gorm:"size:255;" json:"pkColumn"` 16 | PkGoField string `gorm:"size:255;" json:"pkGoField"` 17 | PkJsonField string `gorm:"size:255;" json:"pkJsonField"` 18 | Options string `gorm:"size:255;" json:"options"` 19 | TreeCode string `gorm:"size:255;" json:"treeCode"` 20 | TreeParentCode string `gorm:"size:255;" json:"treeParentCode"` 21 | TreeName string `gorm:"size:255;" json:"treeName"` 22 | Tree bool `gorm:"size:1;default:0;" json:"tree"` 23 | Crud bool `gorm:"size:1;default:1;" json:"crud"` 24 | Remark string `gorm:"size:255;" json:"remark"` 25 | IsDataScope int `gorm:"size:1;" json:"isDataScope"` 26 | IsActions int `gorm:"size:1;" json:"isActions"` 27 | IsAuth int `gorm:"size:1;" json:"isAuth"` 28 | IsLogicalDelete string `gorm:"size:1;" json:"isLogicalDelete"` 29 | LogicalDelete bool `gorm:"size:1;" json:"logicalDelete"` 30 | LogicalDeleteColumn string `gorm:"size:128;" json:"logicalDeleteColumn"` 31 | ModelTime 32 | ControlBy 33 | } 34 | 35 | func (SysTables) TableName() string { 36 | return "sys_tables" 37 | } 38 | -------------------------------------------------------------------------------- /app/system/models/sys_login_log.go: -------------------------------------------------------------------------------- 1 | package models 2 | 3 | import ( 4 | "encoding/json" 5 | "errors" 6 | "time" 7 | 8 | log "github.com/go-admin-team/go-admin-core/logger" 9 | "github.com/go-admin-team/go-admin-core/sdk" 10 | "github.com/go-admin-team/go-admin-core/storage" 11 | 12 | "smart-api/common/models" 13 | ) 14 | 15 | type SysLoginLog struct { 16 | models.Model 17 | Username string `json:"username" gorm:"size:128;comment:用户名"` 18 | Status string `json:"status" gorm:"size:4;comment:状态"` 19 | Ipaddr string `json:"ipaddr" gorm:"size:255;comment:ip地址"` 20 | LoginLocation string `json:"loginLocation" gorm:"size:255;comment:归属地"` 21 | Browser string `json:"browser" gorm:"size:255;comment:浏览器"` 22 | Os string `json:"os" gorm:"size:255;comment:系统"` 23 | Platform string `json:"platform" gorm:"size:255;comment:固件"` 24 | LoginTime time.Time `json:"loginTime" gorm:"comment:登录时间"` 25 | Remark string `json:"remark" gorm:"size:255;comment:备注"` 26 | Msg string `json:"msg" gorm:"size:255;comment:信息"` 27 | CreatedAt time.Time `json:"createdAt" gorm:"comment:创建时间"` 28 | UpdatedAt time.Time `json:"updatedAt" gorm:"comment:最后更新时间"` 29 | models.ControlBy 30 | } 31 | 32 | func (*SysLoginLog) TableName() string { 33 | return "sys_login_log" 34 | } 35 | 36 | func (e *SysLoginLog) Generate() models.ActiveRecord { 37 | o := *e 38 | return &o 39 | } 40 | 41 | func (e *SysLoginLog) GetId() interface{} { 42 | return e.Id 43 | } 44 | 45 | // SaveLoginLog 从队列中获取登录日志 46 | func SaveLoginLog(message storage.Messager) (err error) { 47 | //准备db 48 | db := sdk.Runtime.GetDbByKey(message.GetPrefix()) 49 | if db == nil { 50 | err = errors.New("db not exist") 51 | log.Errorf("host[%s]'s %s", message.GetPrefix(), err.Error()) 52 | return err 53 | } 54 | var rb []byte 55 | rb, err = json.Marshal(message.GetValues()) 56 | if err != nil { 57 | log.Errorf("json Marshal error, %s", err.Error()) 58 | return err 59 | } 60 | var l SysLoginLog 61 | err = json.Unmarshal(rb, &l) 62 | if err != nil { 63 | log.Errorf("json Unmarshal error, %s", err.Error()) 64 | return err 65 | } 66 | err = db.Create(&l).Error 67 | if err != nil { 68 | log.Errorf("db create error, %s", err.Error()) 69 | return err 70 | } 71 | return nil 72 | } 73 | -------------------------------------------------------------------------------- /cmd/migrate/migration/models/order/common.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/18 16:45 3 | package models 4 | 5 | import ( 6 | "smart-api/common/models" 7 | "time" 8 | ) 9 | 10 | type OperationHistory struct { 11 | ID uint `gorm:"primaryKey" json:"id"` // 主键ID 12 | Title string `gorm:"column:title;type:varchar(100)" json:"title"` // 工单标题 13 | NodeName string `gorm:"column:node_name;type:varchar(255)" json:"nodeName"` // 节点名称 14 | Transfer string `gorm:"column:transfer;type:varchar(255)" json:"transfer"` // 流转 15 | Remark string `gorm:"column:remark;type:text" json:"remark"` // 备注 16 | Status string `gorm:"column:status;type:varchar(255)" json:"status"` // 流转状态 1 同意, 0 拒绝, 2 其他 17 | HandlerId int `gorm:"column:handlerId;" json:"handlerId"` // 处理人ID 18 | HandlerName string `gorm:"column:handlerName;type:varchar(125)" json:"handlerName"` // 处理人姓名 19 | HandleTime time.Time `gorm:"column:handleTime" json:"handleTime"` // 处理时间 20 | HandleDuration int64 `gorm:"column:handleDuration;type:bigint" json:"handleDuration"` // 处理时长 (以秒为单位) 21 | models.ModelTime 22 | } 23 | 24 | func (*OperationHistory) TableName() string { 25 | return "operation_history" 26 | } 27 | 28 | // 通知消息 29 | type WorksNotify struct { 30 | ID uint `gorm:"primaryKey;autoIncrement" json:"id"` 31 | Title string `gorm:"column:title;type:varchar(100)" json:"title"` 32 | Department string `gorm:"column:department;type:varchar(50)" json:"department"` 33 | Priority string `gorm:"column:priority;type:varchar(20)" json:"priority"` 34 | Status string `gorm:"column:status;type:varchar(20)" json:"status"` 35 | CurrentHandler int `gorm:"column:currentHandler" json:"currentHandler"` 36 | Message string `gorm:"column:message;type:text" json:"message"` // 通知的详细消息内容。 37 | ReadStatus int `gorm:"column:read_status" json:"readStatus"` // 通知的阅读状态,例如是否已读。 0为未读 1为已读 38 | OrderID uint `gorm:"column:order_id" json:"orderId"` // 关联的工单 ID,方便关联具体的工单。 39 | models.ModelTime 40 | models.ControlBy 41 | } 42 | 43 | func (*WorksNotify) TableName() string { 44 | return "works_notify" 45 | } 46 | -------------------------------------------------------------------------------- /app/smart/models/flow_manage.go: -------------------------------------------------------------------------------- 1 | // @Author sunwenbo 2 | // 2024/7/13 21:14 3 | package models 4 | 5 | import ( 6 | "database/sql/driver" 7 | "encoding/json" 8 | "errors" 9 | "smart-api/common/models" 10 | ) 11 | 12 | type StrucTure map[string]interface{} 13 | 14 | type NoticeSlice []interface{} 15 | 16 | type FlowManage struct { 17 | ID int `gorm:"primaryKey;autoIncrement" json:"id"` 18 | Name string `gorm:"column:name;type:varchar(100)" json:"name"` // 流程名称 19 | CategoryID uint `gorm:"column:categoryId" json:"categoryId"` 20 | Notice NoticeSlice `gorm:"column:notice;type:json" json:"notice"` // 变为json切片 21 | Comments bool `gorm:"column:comments;default:false" json:"comments"` 22 | Ratings bool `gorm:"column:ratings;default:false" json:"ratings"` 23 | Description string `gorm:"description:des;type:varchar(512)" json:"description"` 24 | Creator string `gorm:"creator:des;type:varchar(20)" json:"creator"` // 创建人 25 | Regenerator string `gorm:"regenerator:des;type:varchar(20)" json:"regenerator"` // 更新人 26 | StrucTure StrucTure `gorm:"column:structure;type:json" json:"structure"` 27 | models.ControlBy 28 | models.ModelTime 29 | } 30 | 31 | func (*FlowManage) TableName() string { 32 | return "flow_manage" 33 | } 34 | 35 | func (e *FlowManage) Generate() models.ActiveRecord { 36 | o := *e 37 | return &o 38 | } 39 | 40 | func (e *FlowManage) GetId() interface{} { 41 | return e.ID 42 | } 43 | 44 | // FormData 的 Scan 和 Value 方法 45 | func (e *StrucTure) Scan(value interface{}) error { 46 | bytes, ok := value.([]byte) 47 | if !ok { 48 | return errors.New("Scan source is not []byte") 49 | } 50 | return json.Unmarshal(bytes, &e) 51 | } 52 | 53 | func (e StrucTure) Value() (driver.Value, error) { 54 | bytes, err := json.Marshal(e) 55 | if err != nil { 56 | return nil, err 57 | } 58 | return string(bytes), nil 59 | } 60 | 61 | // FormData 的 Scan 和 Value 方法 62 | func (e *NoticeSlice) Scan(value interface{}) error { 63 | bytes, ok := value.([]byte) 64 | if !ok { 65 | return errors.New("scan source is not []byte") 66 | } 67 | return json.Unmarshal(bytes, &e) 68 | } 69 | 70 | func (e NoticeSlice) Value() (driver.Value, error) { 71 | bytes, err := json.Marshal(e) 72 | if err != nil { 73 | return nil, err 74 | } 75 | return string(bytes), nil 76 | } 77 | --------------------------------------------------------------------------------