发布代码生成、更新20+表单组件,优化数据字典,gf版本更新到2.3.1

This commit is contained in:
孟帅 2023-01-18 16:23:39 +08:00
parent 50207ded90
commit 87c27a17a3
386 changed files with 27926 additions and 44297 deletions

View File

@ -2,11 +2,11 @@
<div align="center">
<img width="140px" src="https://bufanyun.cn-bj.ufileos.com/hotgo/logo.sig.png">
<p>
<h1>HotGo V2.0</h1>
<h1>HotGo V2.1</h1>
</p>
<p align="center">
<a href="https://goframe.org/pages/viewpage.action?pageId=1114119" target="_blank">
<img src="https://img.shields.io/badge/goframe-2.1-green" alt="goframe">
<img src="https://img.shields.io/badge/goframe-2.3-green" alt="goframe">
</a>
<a href="https://v3.vuejs.org/" target="_blank">
<img src="https://img.shields.io/badge/vue.js-vue3.x-green" alt="vue">
@ -29,7 +29,7 @@
## 平台简介
* 基于全新Go Frame 2.0+Vue3+Naive UI开发的全栈前后端分离的管理系统
* 基于全新Go Frame 2+Vue3+Naive UI开发的全栈前后端分离的管理系统
* 前端采用naive-ui-admin 、Vue、Naive UI。
## 特征
@ -55,7 +55,7 @@
10. 调度日志:服务端运行所产生的警告、异常、崩溃日志的详细数据和堆栈信息。
11. 在线用户:当前系统中活跃用户状态监控。
12. 定时任务:在线(添加、修改、删除)任务调度包含执行结果日志。
13. 代码生成:前后端代码的生成
13. 代码生成:支持自动化生成前后端代码。CURD关联表、树表、消息队列、定时任务一键生成等
14. 服务监控监视当前系统CPU、内存、磁盘、网络、堆栈等相关信息。
15. 附件管理:文件上传,多种上传方式适配。
16. 消息队列:同时兼容 kafka、redis、rocketmq一键配置切换到自己想用的MQ。
@ -74,7 +74,7 @@
## 环境要求
- node版本 >= v16.0.0
- golang版本 >= v1.18
- gf版本 >=v2.2.5 (会保持同步gf最新版本gf小版本更新可能存在兼容问题旧版本需自行处理如非必要不建议更新)
- gf版本 >=v2.3.1 (会保持同步gf最新版本gf小版本更新可能存在兼容问题旧版本需自行处理如非必要不建议更新)
- IDE推荐Goland
- mysql版本 >=5.7
- redis版本 >=3.0
@ -93,13 +93,14 @@ git clone https://github.com/bufanyun/hotgo.git && cd hotgo
其中hotgo配置
```yaml
# hotgo配置
hotgo:
debug: true # debug开关开启后接口出现错误时会输出堆栈信息默认为true
ipMethod: "cz88" # IP归属地解析方法可选cz88|whois默认为cz88
wsAddr: "ws://你的IP:8000/socket" # 客户端websocket连接地址如果项目在公网请填写公网IP:运行端口
isDemo: false # 是否為演示系統 false | true
debug: true # debug开关开启后接口出现错误时会输出堆栈信息默认为true
ipMethod: "whois" # IP归属地解析方法可选cz88|whois默认为whois
wsAddr: "ws://127.0.0.1:8000/socket" # 客户端websocket连接地址如果项目在公网请填写公网IP:运行端口
isDemo: false # 是否為演示系統 false | true
ssl: # https
switch: false # 是否开启https访问需要配置sslCrtPath、sslKeyPath证书夹
switch: false # 是否开启https访问需要配置sslCrtPath、sslKeyPath证书夹
crtPath: "resource/ssl/server.crt"
keyPath: "resource/ssl/server.key"
log: # 全局请求日志
@ -108,10 +109,11 @@ hotgo:
module: [ "admin", "api", "default" ] # 需要记录的模块
skipCode: [ ] # 不记录的状态码,如: ["0", "-1"]
admin:
superIds: [ 1,2 ] # 后台超管账号ID通过ID验证超管
superIds: [ 1,2,3 ] # 后台超管账号ID通过ID验证超管
superRoleKey: "super" # 超管角色唯一标识符,通过角色验证超管
defaultPage: 10 # 列表分页默认加载数量
defaultPageSize: 1 # 列表分页默认加载页码
maxSortIncrement: 10 # 最大排序值增量
```
后台前端:
@ -137,10 +139,10 @@ VITE_PROXY=[["/admin","http://你的IP:8000/admin"]]
go mod tidy
# 查看命令行方法
go run main.go
go run main.go hlep
# 启动所有服务
go run main.go all
go run main.go # 热编译启动: gf run main.go
# 如果顺利至此到浏览器打开http://你的IP:8000/admin即可看到后台登录地址
# 登录账号admin, 密码123456
@ -151,7 +153,7 @@ VITE_PROXY=[["/admin","http://你的IP:8000/admin"]]
web端
```shell script
cd web
cd views
# 首先确定你以安装node16.0以上版本并安装了包[npm、yarn],否则可能会出现一些未知报错
# 安装依赖
@ -248,3 +250,6 @@ web端

View File

@ -17,3 +17,10 @@ type UploadImageReq struct {
}
type UploadImageRes *sysin.AttachmentListModel
// UploadFileReq 上传文件
type UploadFileReq struct {
g.Meta `path:"/upload/file" tags:"上传" method:"post" summary:"上传附件"`
}
type UploadFileRes *sysin.AttachmentListModel

View File

@ -8,6 +8,7 @@ package config
import (
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
)
@ -28,3 +29,9 @@ type UpdateReq struct {
}
type UpdateRes struct {
}
// TypeSelectReq 数据类型选项
type TypeSelectReq struct {
g.Meta `path:"/config/typeSelect" method:"get" tags:"配置" summary:"数据类型选项"`
}
type TypeSelectRes []form.Select

View File

@ -0,0 +1,85 @@
// Package curddemo
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.1.0
// @AutoGenerate Date 2023-01-18 15:19:42
//
package curddemo
import (
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"github.com/gogf/gf/v2/frame/g"
)
// ListReq 查询生成演示列表
type ListReq struct {
g.Meta `path:"/curdDemo/list" method:"get" tags:"生成演示" summary:"获取生成演示列表"`
sysin.CurdDemoListInp
}
type ListRes struct {
form.PageRes
List []*sysin.CurdDemoListModel `json:"list" dc:"数据列表"`
}
// ExportReq 导出生成演示列表
type ExportReq struct {
g.Meta `path:"/curdDemo/export" method:"get" tags:"生成演示" summary:"导出生成演示列表"`
sysin.CurdDemoListInp
}
type ExportRes struct{}
// ViewReq 获取生成演示指定信息
type ViewReq struct {
g.Meta `path:"/curdDemo/view" method:"get" tags:"生成演示" summary:"获取生成演示指定信息"`
sysin.CurdDemoViewInp
}
type ViewRes struct {
*sysin.CurdDemoViewModel
}
// EditReq 修改/新增生成演示
type EditReq struct {
g.Meta `path:"/curdDemo/edit" method:"post" tags:"生成演示" summary:"修改/新增生成演示"`
sysin.CurdDemoEditInp
}
type EditRes struct{}
// DeleteReq 删除生成演示
type DeleteReq struct {
g.Meta `path:"/curdDemo/delete" method:"post" tags:"生成演示" summary:"删除生成演示"`
sysin.CurdDemoDeleteInp
}
type DeleteRes struct{}
// MaxSortReq 获取生成演示最大排序
type MaxSortReq struct {
g.Meta `path:"/curdDemo/maxSort" method:"get" tags:"生成演示" summary:"获取生成演示最大排序"`
}
type MaxSortRes struct {
*sysin.CurdDemoMaxSortModel
}
// StatusReq 更新生成演示状态
type StatusReq struct {
g.Meta `path:"/curdDemo/status" method:"post" tags:"生成演示" summary:"更新生成演示状态"`
sysin.CurdDemoStatusInp
}
type StatusRes struct{}
// SwitchReq 更新生成演示开关状态
type SwitchReq struct {
g.Meta `path:"/curdDemo/switch" method:"post" tags:"生成演示" summary:"更新生成演示状态"`
sysin.CurdDemoSwitchInp
}
type SwitchRes struct{}

View File

@ -17,7 +17,7 @@ import (
type DataEditReq struct {
entity.SysDictData
TypeID int64 `json:"typeID" dc:"字典类型ID"`
g.Meta `path:"/dict_data/edit" method:"post" tags:"字典数据" summary:"修改/新增字典数据"`
g.Meta `path:"/dictData/edit" method:"post" tags:"字典数据" summary:"修改/新增字典数据"`
}
type DataEditRes struct{}
@ -25,7 +25,7 @@ type DataEditRes struct{}
// DataDeleteReq 删除字典数据
type DataDeleteReq struct {
Id interface{} `json:"id" v:"required#字典数据ID不能为空" dc:"字典数据ID"`
g.Meta `path:"/dict_data/delete" method:"post" tags:"字典数据" summary:"删除字典数据"`
g.Meta `path:"/dictData/delete" method:"post" tags:"字典数据" summary:"删除字典数据"`
}
type DataDeleteRes struct{}
@ -37,10 +37,22 @@ type DataListReq struct {
TypeID int64 `json:"typeId" v:"required#字典类型ID不能为空" dc:"字典类型ID"` //
Type string `json:"type"`
Label string `json:"label"`
g.Meta `path:"/dict_data/list" method:"get" tags:"字典数据" summary:"获取字典数据列表"`
g.Meta `path:"/dictData/list" method:"get" tags:"字典数据" summary:"获取字典数据列表"`
}
type DataListRes struct {
List []*sysin.DictDataListModel `json:"list" dc:"数据列表"`
form.PageRes
}
type DataSelectReq struct {
g.Meta `path:"/dictData/option/{Type}" method:"get" summary:"字典数据" tags:"获取指定字典选项"`
Type string `in:"path" v:"required#字典类型不能为空" dc:"字典类型"`
}
type DataSelectRes sysin.DataSelectModel
type DataSelectsReq struct {
g.Meta `path:"/dictData/options" method:"get" summary:"字典数据" tags:"获取多个字典选项"`
Types []string `json:"types"`
}
type DataSelectsRes map[string]sysin.DataSelectModel

View File

@ -14,7 +14,7 @@ import (
// TypeTreeReq 字典类型树
type TypeTreeReq struct {
g.Meta `path:"/dict_type/tree" tags:"字典类型" method:"get" summary:"字典类型树列表"`
g.Meta `path:"/dictType/tree" tags:"字典类型" method:"get" summary:"字典类型树列表"`
}
type TypeTreeRes struct {
List []map[string]interface{} `json:"list" dc:"数据列表"`
@ -23,7 +23,7 @@ type TypeTreeRes struct {
// TypeEditReq 修改/新增字典数据
type TypeEditReq struct {
entity.AdminDept
g.Meta `path:"/dict_type/edit" method:"post" tags:"字典类型" summary:"修改/新增字典类型"`
g.Meta `path:"/dictType/edit" method:"post" tags:"字典类型" summary:"修改/新增字典类型"`
}
type TypeEditRes struct{}
@ -31,13 +31,13 @@ type TypeEditRes struct{}
// TypeDeleteReq 删除字典类型
type TypeDeleteReq struct {
Id interface{} `json:"id" v:"required#字典类型ID不能为空" dc:"字典类型ID"`
g.Meta `path:"/dict_type/delete" method:"post" tags:"字典类型" summary:"删除字典类型"`
g.Meta `path:"/dictType/delete" method:"post" tags:"字典类型" summary:"删除字典类型"`
}
type TypeDeleteRes struct{}
// TypeSelectReq 修改/新增字典数据
type TypeSelectReq struct {
g.Meta `path:"/dict_type/select" method:"get" tags:"字典类型" summary:"字典类型选项"`
g.Meta `path:"/dictType/select" method:"get" tags:"字典类型" summary:"字典类型选项"`
}
type TypeSelectRes sysin.DictTypeSelectModel

View File

@ -0,0 +1,108 @@
// Package hggen
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package gencodes
import (
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
)
// ListReq 查询列表
type ListReq struct {
g.Meta `path:"/genCodes/list" method:"get" tags:"生成代码" summary:"获取生成代码列表"`
sysin.GenCodesListInp
}
type ListRes struct {
List []*sysin.GenCodesListModel `json:"list" dc:"数据列表"`
form.PageRes
}
// ViewReq 获取指定信息
type ViewReq struct {
Id int64 `json:"id" v:"required#生成代码ID不能为空" dc:"生成代码ID"`
g.Meta `path:"/genCodes/view" method:"get" tags:"生成代码" summary:"获取指定信息"`
}
type ViewRes struct {
*sysin.GenCodesViewModel
}
// EditReq 修改/新增数据
type EditReq struct {
entity.SysGenCodes
g.Meta `path:"/genCodes/edit" method:"post" tags:"生成代码" summary:"修改/新增生成代码"`
}
type EditRes struct {
*sysin.GenCodesEditModel
}
// DeleteReq 删除
type DeleteReq struct {
Id interface{} `json:"id" v:"required#生成代码ID不能为空" dc:"生成代码ID"`
g.Meta `path:"/genCodes/delete" method:"post" tags:"生成代码" summary:"删除生成代码"`
}
type DeleteRes struct{}
// MaxSortReq 最大排序
type MaxSortReq struct {
Id int64 `json:"id" dc:"生成代码ID"`
g.Meta `path:"/genCodes/max_sort" method:"get" tags:"生成代码" summary:"生成代码最大排序"`
}
type MaxSortRes struct {
Sort int `json:"sort" dc:"排序"`
}
// StatusReq 更新状态
type StatusReq struct {
entity.SysGenCodes
g.Meta `path:"/genCodes/status" method:"post" tags:"生成代码" summary:"更新生成代码状态"`
}
type StatusRes struct{}
type SelectsReq struct {
g.Meta `path:"/genCodes/selects" method:"get" tags:"生成代码" summary:"生成入口选项"`
}
type SelectsRes struct {
*sysin.GenCodesSelectsModel
}
type TableSelectReq struct {
g.Meta `path:"/genCodes/tableSelect" method:"get" tags:"生成代码" summary:"数据库表选项"`
sysin.GenCodesTableSelectInp
}
type TableSelectRes []*sysin.GenCodesTableSelectModel
type ColumnSelectReq struct {
g.Meta `path:"/genCodes/columnSelect" method:"get" tags:"生成代码" summary:"表字段选项"`
sysin.GenCodesColumnSelectInp
}
type ColumnSelectRes []*sysin.GenCodesColumnSelectModel
type ColumnListReq struct {
g.Meta `path:"/genCodes/columnList" method:"get" tags:"生成代码" summary:"表字段列表"`
sysin.GenCodesColumnListInp
}
type ColumnListRes []*sysin.GenCodesColumnListModel
// PreviewReq 生成预览
type PreviewReq struct {
g.Meta `path:"/genCodes/preview" method:"post" tags:"生成代码" summary:"生成预览"`
sysin.GenCodesPreviewInp
}
type PreviewRes struct {
*sysin.GenCodesPreviewModel
}
// BuildReq 提交生成
type BuildReq struct {
g.Meta `path:"/genCodes/build" method:"post" tags:"生成代码" summary:"提交生成"`
sysin.GenCodesPreviewInp
}
type BuildRes struct {
}

View File

@ -16,16 +16,16 @@ import (
// UpdateProfileReq 更新会员资料
type UpdateProfileReq struct {
g.Meta `path:"/member/update_profile" method:"post" tags:"会员" summary:"更新会员资料"`
g.Meta `path:"/member/updateProfile" method:"post" tags:"会员" summary:"更新会员资料"`
Mobile int `json:"mobile" dc:"手机号"`
Email string `json:"email" dc:"邮箱"`
RealName string `json:"realname" dc:"真实姓名"`
RealName string `json:"realName" dc:"真实姓名"`
}
type UpdateProfileRes struct{}
// UpdatePwdReq 修改登录密码
type UpdatePwdReq struct {
g.Meta `path:"/member/update_pwd" method:"post" tags:"会员" summary:"重置密码"`
g.Meta `path:"/member/updatePwd" method:"post" tags:"会员" summary:"重置密码"`
OldPassword string `json:"oldPassword" v:"required#原密码不能为空" dc:"原密码"`
NewPassword string `json:"newPassword" v:"required|length:6,16#新密码不能为空#新密码需在6~16之间" dc:"新密码"`
}
@ -47,7 +47,7 @@ type ProfileRes struct {
// ResetPwdReq 重置密码
type ResetPwdReq struct {
g.Meta `path:"/member/reset_pwd" method:"post" tags:"会员" summary:"重置密码"`
g.Meta `path:"/member/resetPwd" method:"post" tags:"会员" summary:"重置密码"`
Password string `json:"password" v:"required#密码不能为空" dc:"密码"`
Id int64 `json:"id" dc:"会员ID"`
}
@ -55,7 +55,7 @@ type ResetPwdRes struct{}
// EmailUniqueReq 邮箱是否唯一
type EmailUniqueReq struct {
g.Meta `path:"/member/email_unique" method:"get" tags:"会员" summary:"邮箱是否唯一"`
g.Meta `path:"/member/emailUnique" method:"get" tags:"会员" summary:"邮箱是否唯一"`
Email string `json:"email" v:"required#邮箱不能为空" dc:"邮箱"`
Id int64 `json:"id" dc:"会员ID"`
}
@ -65,7 +65,7 @@ type EmailUniqueRes struct {
// MobileUniqueReq 手机号是否唯一
type MobileUniqueReq struct {
g.Meta `path:"/member/mobile_unique" method:"get" tags:"会员" summary:"手机号是否唯一"`
g.Meta `path:"/member/mobileUnique" method:"get" tags:"会员" summary:"手机号是否唯一"`
Mobile string `json:"mobile" v:"required#手机号不能为空" dc:"手机号"`
Id int64 `json:"id" dc:"会员ID"`
}
@ -75,7 +75,7 @@ type MobileUniqueRes struct {
// NameUniqueReq 名称是否唯一
type NameUniqueReq struct {
g.Meta `path:"/member/name_unique" method:"get" tags:"会员" summary:"会员名称是否唯一"`
g.Meta `path:"/member/nameUnique" method:"get" tags:"会员" summary:"会员名称是否唯一"`
Username string `json:"username" v:"required#会员名称不能为空" dc:"会员名称"`
Id int64 `json:"id" dc:"会员ID"`
}
@ -89,13 +89,13 @@ type ListReq struct {
form.PageReq
form.RangeDateReq
form.StatusReq
DeptId int `json:"dept_id" dc:"部门ID"`
DeptId int `json:"deptId" dc:"部门ID"`
Mobile int `json:"mobile" dc:"手机号"`
Username string `json:"username" dc:"用户名"`
Realname string `json:"realname" dc:"真实姓名"`
Realname string `json:"realName" dc:"真实姓名"`
Name string `json:"name" dc:"岗位名称"`
Code string `json:"code" dc:"岗位编码"`
CreatedAt []int64 `json:"created_at" dc:"创建时间"`
CreatedAt []int64 `json:"createdAt" dc:"创建时间"`
}
type ListRes struct {
@ -114,7 +114,7 @@ type ViewRes struct {
PostIds []int64 `json:"postIds" dc:"当前岗位"`
Roles []*adminin.RoleListModel `json:"roles" dc:"可选角色"`
RoleIds []int64 `json:"roleIds" dc:"当前角色"`
DeptName string `json:"dept_name" dc:"部门名称"`
DeptName string `json:"deptName" dc:"部门名称"`
}
// EditReq 修改/新增
@ -147,13 +147,6 @@ type InfoReq struct {
type InfoRes struct {
adminin.MemberLoginModel
//DefaultPortalConfig []*PortalConfig `json:"defaultPortalConfig" dc:"默认用户配置"`
//LincenseInfo string `json:"lincenseInfo" dc:"应用版本号"`
//Permissions []string `json:"permissions" dc:"权限"`
//Roles []string `json:"roles" dc:"角色"`
//SysNoticeList []*entity.AdminNotice `json:"sysNoticeList" dc:"系统公告"`
//UserPortalConfig []*PortalConfig `json:"userPortalConfig" dc:"用户配置"`
//User model.Identity `json:"member" dc:"用户信息"`
}
type PortalConfigContentOptions struct {

View File

@ -20,7 +20,7 @@ type MemberListReq struct {
form.RangeDateReq
form.StatusReq
Role int `json:"role" description:"角色ID"`
DeptId int `json:"dept_id" description:"部门ID"`
DeptId int `json:"deptId" description:"部门ID"`
Mobile int `json:"mobile" description:"手机号"`
Username string `json:"username" description:"用户名"`
Realname string `json:"realname" description:"真实姓名"`
@ -41,7 +41,7 @@ type ListReq struct {
form.PageReq
form.RangeDateReq
form.StatusReq
DeptId int `json:"dept_id" description:"部门ID"`
DeptId int `json:"deptId" description:"部门ID"`
Mobile int `json:"mobile" description:"手机号"`
Username string `json:"username" description:"用户名"`
Realname string `json:"realname" description:"真实姓名"`
@ -129,3 +129,18 @@ type DeleteReq struct {
Id int64 `json:"id" v:"required"`
}
type DeleteRes struct{}
// DataScopeSelectReq 获取数据权限选项
type DataScopeSelectReq struct {
g.Meta `path:"/role/dataScope/select" method:"get" summary:"角色" tags:"获取数据权限选项"`
}
type DataScopeSelectRes struct {
List form.Selects `json:"list" dc:"数据选项"`
}
// DataScopeEditReq 修改指定角色的数据权限
type DataScopeEditReq struct {
g.Meta `path:"/role/dataScope/edit" method:"post" tags:"角色" summary:"修改指定角色的数据权限"`
adminin.DataScopeEditInp
}
type DataScopeEditRes struct{}

View File

@ -0,0 +1,77 @@
// Package test
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package test
import (
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/model/input/adminin"
"hotgo/internal/model/input/form"
)
// ListReq 查询列表
type ListReq struct {
g.Meta `path:"/test/list" method:"get" tags:"测试" summary:"获取测试列表"`
adminin.TestListInp
}
type ListRes struct {
form.PageRes
List []*adminin.TestListModel `json:"list" dc:"数据列表"`
}
// ExportReq 导出列表
type ExportReq struct {
g.Meta `path:"/test/export" method:"get" tags:"测试" summary:"导出测试列表"`
adminin.TestListInp
}
type ExportRes struct{}
// ViewReq 获取信息
type ViewReq struct {
g.Meta `path:"/test/view" method:"get" tags:"测试" summary:"获取指定信息"`
adminin.TestViewInp
}
type ViewRes struct {
*adminin.TestViewModel
}
// EditReq 修改/新增
type EditReq struct {
g.Meta `path:"/test/edit" method:"post" tags:"测试" summary:"修改/新增测试"`
adminin.TestEditInp
}
type EditRes struct{}
// DeleteReq 删除
type DeleteReq struct {
g.Meta `path:"/test/delete" method:"post" tags:"测试" summary:"删除测试"`
adminin.TestDeleteInp
}
type DeleteRes struct{}
// MaxSortReq 最大排序
type MaxSortReq struct {
g.Meta `path:"/test/maxSort" method:"get" tags:"测试" summary:"测试最大排序"`
}
type MaxSortRes struct {
*adminin.TestMaxSortModel
}
// StatusReq 更新状态
type StatusReq struct {
g.Meta `path:"/test/status" method:"post" tags:"测试" summary:"更新测试状态"`
adminin.TestStatusInp
}
type StatusRes struct{}
// SwitchReq 更新开关状态
type SwitchReq struct {
g.Meta `path:"/test/switch" method:"post" tags:"测试" summary:"更新测试状态"`
adminin.TestSwitchInp
}
type SwitchRes struct{}

View File

@ -9,9 +9,11 @@ require (
github.com/bufanyun/pool v0.2.1
github.com/casbin/casbin/v2 v2.55.0
github.com/dgrijalva/jwt-go v3.2.0+incompatible
github.com/forgoer/openssl v1.4.0
github.com/go-resty/resty/v2 v2.7.0
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.2.0-beta2
github.com/gogf/gf/v2 v2.2.5
github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.0
github.com/gogf/gf/v2 v2.3.0
github.com/golang/mock v1.6.0 // indirect
github.com/gomodule/redigo v1.8.8
github.com/google/btree v1.1.2 // indirect
@ -19,13 +21,16 @@ require (
github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794
github.com/mattn/go-colorable v0.1.12 // indirect
github.com/mojocn/base64Captcha v1.3.5
github.com/olekukonko/tablewriter v0.0.5
github.com/shirou/gopsutil v3.21.11+incompatible
github.com/shopspring/decimal v1.3.1
github.com/tklauser/go-sysconf v0.3.10 // indirect
github.com/ufilesdk-dev/ufile-gosdk v1.0.3
github.com/xuri/excelize/v2 v2.6.0
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4 // indirect
golang.org/x/tools v0.1.7
golang.org/x/xerrors v0.0.0-20220411194840-2f41105eb62f // indirect
google.golang.org/protobuf v1.28.0 // indirect
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
)

View File

@ -92,6 +92,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/forgoer/openssl v1.4.0 h1:rPMnQ92OKuBsKnfY/GmUDunnP72Cy+zviAompWMdC9U=
github.com/forgoer/openssl v1.4.0/go.mod h1:NMVFOzYeLVR7UiGTxsa+A21nrERTZ3Rv2JHDPcJpDyI=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@ -126,9 +128,11 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.2.0-beta2 h1:QgVPXrGp8wJx18HIOsNATaIiHjXsd/Rk1F1QyxfWv+g=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.2.0-beta2/go.mod h1:z+/0qiOwMroAnj5ESuobTv0l5P83rf+XR3r6Fj8WJyk=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.0 h1:r2q8MLwF6yUIEm6Hhwsfo/ixaJTKluTXSjU8rSeXo3c=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.3.0/go.mod h1:V9o2BF9ovJnaZhHImHAanqUgjX4kI51lgU45u5rPqvw=
github.com/gogf/gf/v2 v2.0.0/go.mod h1:apktt6TleWtCIwpz63vBqUnw8MX8gWKoZyxgDpXFtgM=
github.com/gogf/gf/v2 v2.2.5 h1:XyRSfn/gqdrGb03p1OGhXd4q6kVf1BL/pryT2Y1NyBA=
github.com/gogf/gf/v2 v2.2.5/go.mod h1:thvkyb43RWUu/m05sRm4CbH9r7t7/FrW2M56L9Ystwk=
github.com/gogf/gf/v2 v2.3.0 h1:Uz4z6tMqnpH9azLFrfBX1R1k/73d7QPC2E4Ab8L3y4g=
github.com/gogf/gf/v2 v2.3.0/go.mod h1:tsbmtwcAl2chcYoq/fP9W2FZf06aw4i89X34nbSHo9Y=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
@ -373,6 +377,8 @@ github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03O
github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
github.com/tklauser/numcpus v0.4.0 h1:E53Dm1HjH1/R2/aoCtXtPgzmElmn51aOkhCFSuZq//o=
github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
github.com/ufilesdk-dev/ufile-gosdk v1.0.3 h1:M85lCFBmCHcFfXldFOb+Lkdw10fLZXvqVUnyZ852Nhk=
github.com/ufilesdk-dev/ufile-gosdk v1.0.3/go.mod h1:R5FMQxkQ+QK/9Vz+jfnJP4rZIktYrRcWmuAnbOSkROI=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
@ -452,6 +458,7 @@ golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -624,6 +631,7 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@ -705,9 +713,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=

View File

@ -15,10 +15,18 @@ gfcli:
gen:
dao:
- link: "mysql:hotgo:hg123456.@tcp(127.0.0.1:3306)/hotgo?loc=Local&parseTime=true"
group: "default" # 分组使用hotgo代码生成功能时必须填
# path: "./app"
# tables: "" #指定当前数据库中需要执行代码生成的数据表如果为空表示数据库的所有表都会生成
# tablesEx: "" #指定当前数据库中需要排除代码生成的数据表
removePrefix: "hg_"
descriptionTag: true
noModelComment: true
jsonCase: "CamelLower"
jsonCase: "CamelLower"
gJsonSupport: true
# service:
# srcFolder: "internal/logic"
# dstFolder: "internal/service"
# dstFileNameCase: "CamelLower"
# clear: true

View File

@ -16,26 +16,33 @@ import (
var (
serverCloseSignal chan struct{}
Main = &gcmd.Command{
Description: `
命令提示符
---------------------------------------------------------------------------------
启动服务
>> HTTP服务 [go run main.go http]
>> 消息队列 [go run main.go queue]
>> 所有服务 [go run main.go all]
---------------------------------------------------------------------------------
工具
>> 释放casbin权限用于清理无效的权限设置 [go run main.go tools -m=casbin -a1=refresh]
`,
Description: `默认启动所有服务`,
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
return All.Func(ctx, parser)
},
}
Help = &gcmd.Command{
Name: "help",
Brief: "查看帮助",
Description: `
github地址:https://github.com/bufanyun/hotgo
文档地址:文档正在书写中请耐心等一等
命令提示符
---------------------------------------------------------------------------------
启动服务
>> 所有服务 [go run main.go] 热编译 [gf run main.go]
>> HTTP服务 [go run main.go http]
>> 消息队列 [go run main.go queue]
>> 查看帮助 [go run main.go help]
---------------------------------------------------------------------------------
工具
>> 释放casbin权限用于清理无效的权限设置 [go run main.go tools -m=casbin -a1=refresh]
---------------------------------------------------------------------------------
更多
github地址https://github.com/bufanyun/hotgo
文档地址文档正在书写中请耐心等一等
HotGo框架交流1群190966648
`,
}
@ -44,7 +51,7 @@ var (
Brief: "start all server",
Description: "this is the command entry for starting all server",
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
g.Log().Info(ctx, "start all server")
g.Log().Debug(ctx, "starting all server")
simple.SafeGo(ctx, func(ctx context.Context) {
if err := Http.Func(ctx, parser); err != nil {

View File

@ -11,10 +11,7 @@ import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gcmd"
baseApi "hotgo/api/home/base"
"hotgo/internal/controller/home/base"
"hotgo/internal/library/casbin"
"hotgo/internal/model"
"hotgo/internal/router"
"hotgo/internal/service"
)
@ -25,10 +22,6 @@ var (
Usage: "http",
Brief: "HTTP服务",
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
if _, err := g.Cfg().Get(ctx, "hotgo.debug"); err != nil {
g.Log().Fatal(ctx, "配置读取异常:", err, "\r\n你确定 config/config.yaml 文件存在且格式正确吗?\r\n")
}
// 加载权限
casbin.InitEnforcer(ctx)
@ -55,20 +48,10 @@ var (
service.Middleware().ResponseHandler,
)
// 注册默认首页路由
group.ALL("/", func(r *ghttp.Request) {
_, _ = base.Site.Index(r.Context(), &baseApi.SiteIndexReq{})
return
})
group.ALL("/login", func(r *ghttp.Request) {
r.Response.RedirectTo("/admin")
})
// 注册后台路由
router.Admin(ctx, group)
// 注册前台路由
// 注册Api路由
router.Api(ctx, group)
// 注册websocket路由
@ -84,18 +67,8 @@ var (
// 信号监听
signalListen(ctx, signalHandlerForCron, signalHandlerForWebSocket)
// 开启https访问
var (
sSLConfig *model.SSLConfig
ssl, _ = g.Cfg().Get(ctx, "hotgo.ssl")
)
if err := ssl.Struct(&sSLConfig); err != nil {
g.Log().Fatalf(ctx, "hotgo启动失败, ssl err:", err)
return err
}
if sSLConfig != nil && sSLConfig.Switch {
s.EnableHTTPS(sSLConfig.CrtPath, sSLConfig.KeyPath)
}
// https
setSSL(ctx, s)
// Just run the server.
s.Run()
@ -104,3 +77,14 @@ var (
},
}
)
func setSSL(ctx context.Context, s *ghttp.Server) {
config, err := service.SysConfig().GetLoadSSL(ctx)
if err != nil {
g.Log().Fatal(ctx, "ssl配置获取失败err:%+v", err)
return
}
if config != nil && config.Switch {
s.EnableHTTPS(config.CrtPath, config.KeyPath)
}
}

View File

@ -19,7 +19,7 @@ var (
Brief: "消息队列",
Description: ``,
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
g.Log().Infof(ctx, "start queue consumer..")
g.Log().Debug(ctx, "start queue consumer..")
queues.Run(ctx)
return
},

View File

@ -20,7 +20,7 @@ var (
Description: ``,
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
flags := parser.GetOptAll()
g.Log().Warningf(ctx, "flags:%+v", flags)
g.Log().Debug(ctx, "flags:%+v", flags)
if len(flags) == 0 {
g.Log().Fatal(ctx, "工具参数不能为空")
return

View File

@ -1,31 +0,0 @@
// Package consts
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package consts
// 全局状态码
const (
CodeNil = -1 // No error code specified.
CodeOK = 0 // It is OK.
CodeInternalError = 50 // An error occurred internally.
CodeValidationFailed = 51 // Data validation failed.
CodeDbOperationError = 52 // Database operation error.
CodeInvalidParameter = 53 // The given parameter for current operation is invalid.
CodeMissingParameter = 54 // Parameter for current operation is missing.
CodeInvalidOperation = 55 // The function cannot be used like this.
CodeInvalidConfiguration = 56 // The configuration is invalid for current operation.
CodeMissingConfiguration = 57 // The configuration is missing for current operation.
CodeNotImplemented = 58 // The operation is not implemented yet.
CodeNotSupported = 59 // The operation is not supported yet.
CodeOperationFailed = 60 // I tried, but I cannot give you what you want.
CodeNotAuthorized = 61 // Not Authorized.
CodeSecurityReason = 62 // Security Reason.
CodeServerBusy = 63 // Server is busy, please try again later.
CodeUnknown = 64 // Unknown error.
CodeNotFound = 65 // Resource does not exist.
CodeInvalidRequest = 66 // Invalid request.
CodeBusinessValidationFailed = 300 // Business validation failed.
)

View File

@ -6,10 +6,74 @@
//
package consts
import "github.com/gogf/gf/v2/util/gconv"
// 配置数据类型
const (
ConfigTypeString = "string"
ConfigTypeInt = "int"
ConfigTypeBool = "bool"
ConfigTypeArray = "array"
ConfigTypeDate = "date"
ConfigTypeString = "string"
ConfigTypeInt = "int"
ConfigTypeInt8 = "int8"
ConfigTypeInt16 = "int16"
ConfigTypeInt32 = "int32"
ConfigTypeInt64 = "int64"
ConfigTypeUint = "uint"
ConfigTypeUint8 = "uint8"
ConfigTypeUint16 = "uint16"
ConfigTypeUint32 = "uint32"
ConfigTypeUint64 = "uint64"
ConfigTypeFloat32 = "float32"
ConfigTypeFloat64 = "float64"
ConfigTypeBool = "bool"
ConfigTypeDate = "date"
ConfigTypeDateTime = "datetime"
)
var ConfigTypes = []string{ConfigTypeString,
ConfigTypeInt, ConfigTypeInt8, ConfigTypeInt16, ConfigTypeInt32, ConfigTypeInt64,
ConfigTypeUint, ConfigTypeUint8, ConfigTypeUint16, ConfigTypeUint32, ConfigTypeUint64,
ConfigTypeFloat32, ConfigTypeFloat64,
ConfigTypeBool,
ConfigTypeDate, ConfigTypeDateTime,
}
// ConvType 类型转换
func ConvType(val interface{}, t string) interface{} {
switch t {
case ConfigTypeString:
val = gconv.String(val)
case ConfigTypeInt:
val = gconv.Int(val)
case ConfigTypeInt8:
val = gconv.Int8(val)
case ConfigTypeInt16:
val = gconv.Int16(val)
case ConfigTypeInt32:
val = gconv.Int32(val)
case ConfigTypeInt64:
val = gconv.Int64(val)
case ConfigTypeUint:
val = gconv.Uint(val)
case ConfigTypeUint8:
val = gconv.Uint8(val)
case ConfigTypeUint16:
val = gconv.Uint16(val)
case ConfigTypeUint32:
val = gconv.Uint32(val)
case ConfigTypeUint64:
val = gconv.Uint64(val)
case ConfigTypeFloat32:
val = gconv.Float32(val)
case ConfigTypeFloat64:
val = gconv.Float64(val)
case ConfigTypeBool:
val = gconv.Bool(val)
case ConfigTypeDate:
val = gconv.Time(val, "Y-m-d")
case ConfigTypeDateTime:
val = gconv.Time(val, "Y-m-d H:i:s")
default:
val = gconv.String(val)
}
return val
}

View File

@ -9,5 +9,6 @@ package consts
// 碎片
const (
DemoTips = "演示系统已隐藏"
DemoTips = "演示系统已隐藏"
NilJsonToString = "{}" // 空json初始化值
)

View File

@ -0,0 +1,74 @@
// Package consts
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package consts
// 生成代码类型
const (
GenCodesTypeCurd = 10 // 增删改查列表
GenCodesTypeTree = 11 // 树列表
GenCodesTypeQueue = 20 // 队列消费者
GenCodesTypeCron = 30 // 定时任务
)
var GenCodesTypeNameMap = map[int]string{
GenCodesTypeCurd: "增删改查列表",
GenCodesTypeTree: "关系树列表(未实现)",
GenCodesTypeQueue: "队列消费者(未实现)",
GenCodesTypeCron: "定时任务(未实现)",
}
// 生成代码状态
const (
GenCodesStatusOk = 1 // 生成成功
GenCodesStatusWait = 2 // 未生成
GenCodesStatusFail = 3 // 生成失败
)
var GenCodesStatusNameMap = map[int]string{
GenCodesStatusOk: "生成成功",
GenCodesStatusWait: "未生成",
GenCodesStatusFail: "生成失败",
}
// 生成代码关联表方式
const (
GenCodesJoinLeft = 1 // 左关联
GenCodesJoinRight = 2 // 右关联
GenCodesJoinInner = 3 // 内关联
)
var GenCodesJoinNameMap = map[int]string{
GenCodesJoinLeft: "左关联",
GenCodesJoinRight: "右关联",
GenCodesJoinInner: "内关联",
}
var GenCodesJoinLinkMap = map[int]string{
GenCodesJoinLeft: "LeftJoin",
GenCodesJoinRight: "RightJoin",
GenCodesJoinInner: "InnerJoin",
}
// 生成代码的生成方式
const (
GenCodesBuildMethCreate = 1 // 创建
GenCodesBuildMethCover = 2 // 覆盖
GenCodesBuildMethSkip = 3 // 跳过
GenCodesBuildIgnore = 4 // 不生成
)
var GenCodesBuildMethNameMap = map[int]string{
GenCodesBuildMethCreate: "创建文件",
GenCodesBuildMethCover: "强制覆盖",
GenCodesBuildMethSkip: "已存在跳过",
GenCodesBuildIgnore: "不生成",
}
const (
GenCodesIndexPK = "PRI" // 主键索引
GenCodesIndexUNI = "UNI" // 唯一索引
)

View File

@ -0,0 +1,32 @@
// Package consts
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package consts
// 数据范围
const (
RoleDataAll = 1 // 全部权限
// 通过部门划分
RoleDataNowDept = 2 // 当前部门
RoleDataDeptAndSub = 3 // 当前部门及以下部门
RoleDataDeptCustom = 4 // 自定义部门
// 通过上下级关系划分
RoleDataSelf = 5 // 仅自己
RoleDataSelfAndSub = 6 // 自己和直属下级
RoleDataSelfAndAllSub = 7 // 自己和全部下级
)
var RoleDataNameMap = map[int]string{
RoleDataAll: "全部权限",
RoleDataNowDept: "当前部门",
RoleDataDeptAndSub: "当前及以下部门",
RoleDataDeptCustom: "自定义部门",
RoleDataSelf: "仅自己",
RoleDataSelfAndSub: "自己和直属下级",
RoleDataSelfAndAllSub: "自己和全部下级",
}

View File

@ -7,6 +7,7 @@
package consts
const (
UploadDriveLocal = "local" // 本地驱动
UploadDriveOss = "oss" // 阿里云oss
UploadDriveLocal = "local" // 本地驱动
UploadDriveOss = "oss" // 阿里云oss
UploadDriveUCloud = "ucloud" // ucloud对象存储
)

View File

@ -6,7 +6,7 @@
//
package consts
// VersionApp 应用版本
// VersionApp HotGo版本
const (
VersionApp = "2.0.3"
VersionApp = "2.1.0"
)

View File

@ -81,14 +81,14 @@ func (c *cMember) Profile(ctx context.Context, req *member.ProfileReq) (*member.
res.SysDept = sysDept
// 角色列表
sysRoles, err := service.AdminRole().GetMemberList(ctx, memberInfo.Role)
sysRoles, err := service.AdminRole().GetMemberList(ctx, memberInfo.RoleId)
if err != nil {
return nil, err
}
res.SysRoles = sysRoles
// 获取角色名称
roleGroup, err := service.AdminRole().GetName(ctx, memberInfo.Role)
roleGroup, err := service.AdminRole().GetName(ctx, memberInfo.RoleId)
if err != nil {
return nil, err
}
@ -174,6 +174,8 @@ func (c *cMember) Edit(ctx context.Context, req *member.EditReq) (res *member.Ed
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
in.PostIds = req.PostIds
if err = service.AdminMember().Edit(ctx, in); err != nil {
return nil, err
}
@ -227,7 +229,7 @@ func (c *cMember) View(ctx context.Context, req *member.ViewReq) (*member.ViewRe
return nil, err
}
res.RoleIds = []int64{memberInfo.Role}
res.RoleIds = []int64{memberInfo.RoleId}
res.DeptName, err = service.AdminDept().GetName(ctx, memberInfo.DeptId)
if err != nil {
return nil, err

View File

@ -56,7 +56,7 @@ func (c *cMonitor) OnlineList(ctx context.Context, req *monitor.OnlineListReq) (
var (
res monitor.OnlineListRes
clients []*monitor.OnlineModel
i int64
i int
)
if c.wsManager.GetClientsLen() == 0 {
@ -86,16 +86,16 @@ func (c *cMonitor) OnlineList(ctx context.Context, req *monitor.OnlineListReq) (
})
}
res.PageCount = form.CalPageCount(int64(len(clients)), req.PerPage)
res.PageCount = form.CalPageCount(len(clients), req.PerPage)
res.Page = req.Page
res.PerPage = req.PerPage
sort.Sort(monitor.OnlineModels(clients))
isDemo, _ := g.Cfg().Get(ctx, "hotgo.isDemo", false)
isDemo := g.Cfg().MustGet(ctx, "hotgo.isDemo", false)
_, perPage, offset := form.CalPage(ctx, req.Page, req.PerPage)
for k, v := range clients {
if int64(k) >= offset && i <= perPage {
if k >= offset && i <= perPage {
i++
if isDemo.Bool() {
v.Addr = consts.DemoTips

View File

@ -45,11 +45,11 @@ func (c *cRole) RoleMemberList(ctx context.Context, req *role.MemberListReq) (*r
// List 获取列表
func (c *cRole) List(ctx context.Context, req *role.ListReq) (*role.ListRes, error) {
list, totalCount, err := service.AdminRole().List(ctx, adminin.RoleListInp{
Page: req.Page,
PerPage: req.PerPage,
})
var in adminin.RoleListInp
if err := gconv.Scan(req, &in); err != nil {
return nil, err
}
list, totalCount, err := service.AdminRole().List(ctx, in)
if err != nil {
return nil, err
}
@ -57,7 +57,7 @@ func (c *cRole) List(ctx context.Context, req *role.ListReq) (*role.ListRes, err
var res role.ListRes
res.List = list
res.PageCount = form.CalPageCount(totalCount, req.PerPage)
res.PerPage = req.Page
res.Page = req.Page
res.PerPage = req.PerPage
return &res, nil
@ -115,3 +115,27 @@ func (c *cRole) UpdatePermissions(ctx context.Context, req *role.UpdatePermissio
}
return res, nil
}
// DataScopeSelect 获取数据权限选项
func (c *cRole) DataScopeSelect(ctx context.Context, req *role.DataScopeSelectReq) (res *role.DataScopeSelectRes, err error) {
data := service.AdminRole().DataScopeSelect(ctx)
res = new(role.DataScopeSelectRes)
res.List = data
return res, nil
}
// DataScopeEdit 获取数据权限选项
func (c *cRole) DataScopeEdit(ctx context.Context, req *role.DataScopeEditReq) (res *role.DataScopeEditRes, err error) {
var in adminin.DataScopeEditInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
in.CustomDept = req.CustomDept
err = service.AdminRole().DataScopeEdit(ctx, &in)
if err != nil {
return nil, err
}
return res, nil
}

View File

@ -0,0 +1,144 @@
// Package admin
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package admin
import (
"context"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/test"
"hotgo/internal/model/input/adminin"
"hotgo/internal/model/input/form"
"hotgo/internal/service"
"hotgo/utility/validate"
)
var (
Test = cTest{}
)
type cTest struct{}
// List 查看列表
func (c *cTest) List(ctx context.Context, req *test.ListReq) (res *test.ListRes, err error) {
var in adminin.TestListInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
list, totalCount, err := service.AdminTest().List(ctx, in)
if err != nil {
return nil, err
}
res = new(test.ListRes)
res.List = list
res.PageCount = form.CalPageCount(totalCount, req.PerPage)
res.Page = req.Page
res.PerPage = req.PerPage
return res, nil
}
// Export 导出列表
func (c *cTest) Export(ctx context.Context, req *test.ExportReq) (res *test.ExportRes, err error) {
var in adminin.TestListInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.AdminTest().Export(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Edit 更新
func (c *cTest) Edit(ctx context.Context, req *test.EditReq) (res *test.EditRes, err error) {
var in adminin.TestEditInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.AdminTest().Edit(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// MaxSort 最大排序
func (c *cTest) MaxSort(ctx context.Context, req *test.MaxSortReq) (res *test.MaxSortRes, err error) {
data, err := service.AdminTest().MaxSort(ctx, adminin.TestMaxSortInp{})
if err != nil {
return nil, err
}
res = new(test.MaxSortRes)
res.TestMaxSortModel = data
return res, nil
}
// View 获取指定信息
func (c *cTest) View(ctx context.Context, req *test.ViewReq) (res *test.ViewRes, err error) {
var in adminin.TestViewInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
data, err := service.AdminTest().View(ctx, in)
if err != nil {
return nil, err
}
res = new(test.ViewRes)
res.TestViewModel = data
return res, nil
}
// Delete 删除
func (c *cTest) Delete(ctx context.Context, req *test.DeleteReq) (res *test.DeleteRes, err error) {
var in adminin.TestDeleteInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.AdminTest().Delete(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Status 更新状态
func (c *cTest) Status(ctx context.Context, req *test.StatusReq) (res *test.StatusRes, err error) {
var in adminin.TestStatusInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.AdminTest().Status(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Switch 更新开关状态
func (c *cTest) Switch(ctx context.Context, req *test.SwitchReq) (res *test.SwitchRes, err error) {
var in adminin.TestSwitchInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.AdminTest().Switch(ctx, in); err != nil {
return nil, err
}
return res, nil
}

View File

@ -33,16 +33,31 @@ func (c *cSite) Ping(ctx context.Context, req *common.SitePingReq) (res *common.
// Config 获取配置
func (c *cSite) Config(ctx context.Context, req *common.SiteConfigReq) (res *common.SiteConfigRes, err error) {
wsAddr, _ := g.Cfg().Get(ctx, "hotgo.wsAddr", "ws://127.0.0.1:8000/ws")
g.Log().Warningf(ctx, "wsAddr:%+v", wsAddr.String())
res = &common.SiteConfigRes{
Version: consts.VersionApp,
WsAddr: wsAddr.String(),
WsAddr: c.getWsAddr(ctx),
}
return
}
func (c *cSite) getWsAddr(ctx context.Context) string {
ws := g.Cfg().MustGet(ctx, "hotgo.wsAddr", "ws://127.0.0.1:8000/socket")
return ws.String()
//// nginx负载均衡部署
//// 如果是IP访问则认为是调试模式走配置中的ws地址否则走实际请求中的域名+协议
//if !validate.IsDNSName(ghttp.RequestFromCtx(ctx).Host) {
// ws := g.Cfg().MustGet(ctx, "hotgo.wsAddr", "ws://127.0.0.1:8000/socket")
// return ws.String()
//}
//
//if !validate.IsHTTPS(ctx) {
// return fmt.Sprintf("ws://%s/socket", url.GetDomain(ctx))
//}
//
//return fmt.Sprintf("wss://%s/socket", url.GetDomain(ctx))
}
// Captcha 登录验证码
func (c *cSite) Captcha(ctx context.Context, req *common.LoginCaptchaReq) (res *common.LoginCaptchaRes, err error) {

View File

@ -34,3 +34,20 @@ func (c *cUpload) UploadImage(ctx context.Context, req *common.UploadImageReq) (
return
}
// UploadFile 上传附件
func (c *cUpload) UploadFile(ctx context.Context, req *common.UploadFileReq) (res common.UploadFileRes, err error) {
r := g.RequestFromCtx(ctx)
file := r.GetUploadFile("file")
if file == nil {
err = gerror.New("没有找到上传的文件")
return
}
res, err = service.CommonUpload().UploadFile(ctx, file)
if err != nil {
return
}
return
}

View File

@ -10,6 +10,8 @@ import (
"context"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/config"
"hotgo/internal/consts"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
@ -55,3 +57,15 @@ func (c *cConfig) UpdateConfig(ctx context.Context, req *config.UpdateReq) (*con
return &res, nil
}
// TypeSelect 数据类型选项
func (c *cConfig) TypeSelect(ctx context.Context, req *config.TypeSelectReq) (res config.TypeSelectRes, err error) {
for _, v := range consts.ConfigTypes {
res = append(res, form.Select{
Value: v,
Name: v,
Label: v,
})
}
return
}

View File

@ -0,0 +1,169 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.1.0
// @AutoGenerate Date 2023-01-18 15:19:42
//
package sys
import (
"context"
"hotgo/api/backend/curddemo"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/validate"
"github.com/gogf/gf/v2/util/gconv"
)
var (
CurdDemo = cCurdDemo{}
)
type cCurdDemo struct{}
// List 查看生成演示列表
func (c *cCurdDemo) List(ctx context.Context, req *curddemo.ListReq) (res *curddemo.ListRes, err error) {
var in sysin.CurdDemoListInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
list, totalCount, err := service.SysCurdDemo().List(ctx, in)
if err != nil {
return nil, err
}
res = new(curddemo.ListRes)
res.List = list
res.PageCount = form.CalPageCount(totalCount, req.PerPage)
res.Page = req.Page
res.PerPage = req.PerPage
return res, nil
}
// Export 导出生成演示列表
func (c *cCurdDemo) Export(ctx context.Context, req *curddemo.ExportReq) (res *curddemo.ExportRes, err error) {
var in sysin.CurdDemoListInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysCurdDemo().Export(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Edit 更新生成演示
func (c *cCurdDemo) Edit(ctx context.Context, req *curddemo.EditReq) (res *curddemo.EditRes, err error) {
var in sysin.CurdDemoEditInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysCurdDemo().Edit(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// MaxSort 获取生成演示最大排序
func (c *cCurdDemo) MaxSort(ctx context.Context, req *curddemo.MaxSortReq) (res *curddemo.MaxSortRes, err error) {
data, err := service.SysCurdDemo().MaxSort(ctx, sysin.CurdDemoMaxSortInp{})
if err != nil {
return nil, err
}
res = new(curddemo.MaxSortRes)
res.CurdDemoMaxSortModel = data
return res, nil
}
// View 获取指定生成演示信息
func (c *cCurdDemo) View(ctx context.Context, req *curddemo.ViewReq) (res *curddemo.ViewRes, err error) {
var in sysin.CurdDemoViewInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
data, err := service.SysCurdDemo().View(ctx, in)
if err != nil {
return nil, err
}
res = new(curddemo.ViewRes)
res.CurdDemoViewModel = data
return res, nil
}
// Delete 删除生成演示
func (c *cCurdDemo) Delete(ctx context.Context, req *curddemo.DeleteReq) (res *curddemo.DeleteRes, err error) {
var in sysin.CurdDemoDeleteInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysCurdDemo().Delete(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Status 更新生成演示状态
func (c *cCurdDemo) Status(ctx context.Context, req *curddemo.StatusReq) (res *curddemo.StatusRes, err error) {
var in sysin.CurdDemoStatusInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysCurdDemo().Status(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Switch 更新生成演示开关状态
func (c *cCurdDemo) Switch(ctx context.Context, req *curddemo.SwitchReq) (res *curddemo.SwitchRes, err error) {
var in sysin.CurdDemoSwitchInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = validate.PreFilter(ctx, &in); err != nil {
return nil, err
}
if err = service.SysCurdDemo().Switch(ctx, in); err != nil {
return nil, err
}
return res, nil
}

View File

@ -49,7 +49,6 @@ func (c *cDictData) Edit(ctx context.Context, req *dict.DataEditReq) (res *dict.
// List 查看列表
func (c *cDictData) List(ctx context.Context, req *dict.DataListReq) (*dict.DataListRes, error) {
var (
in sysin.DictDataListInp
res dict.DataListRes
@ -71,3 +70,37 @@ func (c *cDictData) List(ctx context.Context, req *dict.DataListReq) (*dict.Data
return &res, nil
}
// Select 指定选项
func (c *cDictData) Select(ctx context.Context, req *dict.DataSelectReq) (*dict.DataSelectRes, error) {
var (
in sysin.DataSelectInp
res dict.DataSelectRes
)
if err := gconv.Scan(req, &in); err != nil {
return nil, err
}
list, err := service.SysDictData().Select(ctx, in)
if err != nil {
return nil, err
}
res = dict.DataSelectRes(list)
return &res, nil
}
// Selects 多个选项
func (c *cDictData) Selects(ctx context.Context, req *dict.DataSelectsReq) (*dict.DataSelectsRes, error) {
res := make(dict.DataSelectsRes)
for _, v := range req.Types {
option, err := service.SysDictData().Select(ctx, sysin.DataSelectInp{Type: v})
if err != nil {
return nil, err
}
res[v] = option
}
return &res, nil
}

View File

@ -0,0 +1,208 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package sys
import (
"context"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/api/backend/gencodes"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
var (
GenCodes = cGenCodes{}
)
type cGenCodes struct{}
// Delete 删除
func (c *cGenCodes) Delete(ctx context.Context, req *gencodes.DeleteReq) (res *gencodes.DeleteRes, err error) {
var in sysin.GenCodesDeleteInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.SysGenCodes().Delete(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Edit 更新
func (c *cGenCodes) Edit(ctx context.Context, req *gencodes.EditReq) (res *gencodes.EditRes, err error) {
var in sysin.GenCodesEditInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
data, err := service.SysGenCodes().Edit(ctx, in)
if err != nil {
return nil, err
}
res = new(gencodes.EditRes)
res.GenCodesEditModel = data
return res, nil
}
// MaxSort 最大排序
func (c *cGenCodes) MaxSort(ctx context.Context, req *gencodes.MaxSortReq) (*gencodes.MaxSortRes, error) {
data, err := service.SysGenCodes().MaxSort(ctx, sysin.GenCodesMaxSortInp{Id: req.Id})
if err != nil {
return nil, err
}
var res gencodes.MaxSortRes
res.Sort = data.Sort
return &res, nil
}
// View 获取指定信息
func (c *cGenCodes) View(ctx context.Context, req *gencodes.ViewReq) (*gencodes.ViewRes, error) {
data, err := service.SysGenCodes().View(ctx, sysin.GenCodesViewInp{Id: req.Id})
if err != nil {
return nil, err
}
var res gencodes.ViewRes
res.GenCodesViewModel = data
return &res, nil
}
// List 查看列表
func (c *cGenCodes) List(ctx context.Context, req *gencodes.ListReq) (*gencodes.ListRes, error) {
var (
in sysin.GenCodesListInp
res gencodes.ListRes
)
if err := gconv.Scan(req, &in); err != nil {
return nil, err
}
list, totalCount, err := service.SysGenCodes().List(ctx, in)
if err != nil {
return nil, err
}
res.List = list
res.PageCount = form.CalPageCount(totalCount, req.PerPage)
res.Page = req.Page
res.PerPage = req.PerPage
return &res, nil
}
// Status 更新部门状态
func (c *cGenCodes) Status(ctx context.Context, req *gencodes.StatusReq) (res *gencodes.StatusRes, err error) {
var in sysin.GenCodesStatusInp
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.SysGenCodes().Status(ctx, in); err != nil {
return nil, err
}
return res, nil
}
// Selects 获取指定信息
func (c *cGenCodes) Selects(ctx context.Context, req *gencodes.SelectsReq) (*gencodes.SelectsRes, error) {
data, err := service.SysGenCodes().Selects(ctx, sysin.GenCodesSelectsInp{})
if err != nil {
return nil, err
}
var res gencodes.SelectsRes
res.GenCodesSelectsModel = data
return &res, nil
}
// TableSelect 数据库表选项
func (c *cGenCodes) TableSelect(ctx context.Context, req *gencodes.TableSelectReq) (*gencodes.TableSelectRes, error) {
data, err := service.SysGenCodes().TableSelect(ctx, sysin.GenCodesTableSelectInp{Name: req.Name})
if err != nil {
return nil, err
}
var res gencodes.TableSelectRes
res = data
return &res, nil
}
// ColumnSelect 表字段选项
func (c *cGenCodes) ColumnSelect(ctx context.Context, req *gencodes.ColumnSelectReq) (*gencodes.ColumnSelectRes, error) {
data, err := service.SysGenCodes().ColumnSelect(ctx, sysin.GenCodesColumnSelectInp{Name: req.Name, Table: req.Table})
if err != nil {
return nil, err
}
var res gencodes.ColumnSelectRes
res = data
return &res, nil
}
// ColumnList 表字段列表
func (c *cGenCodes) ColumnList(ctx context.Context, req *gencodes.ColumnListReq) (*gencodes.ColumnListRes, error) {
var (
in sysin.GenCodesColumnListInp
err error
)
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
data, err := service.SysGenCodes().ColumnList(ctx, in)
if err != nil {
return nil, err
}
var res gencodes.ColumnListRes
res = data
return &res, nil
}
// Preview 生成预览
func (c *cGenCodes) Preview(ctx context.Context, req *gencodes.PreviewReq) (*gencodes.PreviewRes, error) {
var (
in sysin.GenCodesPreviewInp
err error
)
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
data, err := service.SysGenCodes().Preview(ctx, in)
if err != nil {
return nil, err
}
res := new(gencodes.PreviewRes)
res.GenCodesPreviewModel = data
return res, nil
}
// Build 生成预览
func (c *cGenCodes) Build(ctx context.Context, req *gencodes.BuildReq) (*gencodes.BuildRes, error) {
var (
in sysin.GenCodesBuildInp
err error
)
if err = gconv.Scan(req, &in); err != nil {
return nil, err
}
if err = service.SysGenCodes().Build(ctx, in); err != nil {
return nil, err
}
return nil, nil
}

View File

@ -24,6 +24,7 @@ func (a *cSite) Index(ctx context.Context, req *base.SiteIndexReq) (res *base.Si
service.View().Render(ctx, model.View{Data: g.Map{
"name": "HotGo",
"version": consts.VersionApp,
"debug": g.Cfg().MustGet(ctx, "hotgo.debug", true),
}})
return
}

View File

@ -78,7 +78,7 @@ func (c *cMonitor) RunInfo(client *websocket.Client, req *websocket.WRequest) {
"goSize": file.DirSize(pwd),
}
isDemo, _ := g.Cfg().Get(client.Context(), "hotgo.isDemo", false)
isDemo := g.Cfg().MustGet(client.Context(), "hotgo.isDemo", false)
if isDemo.Bool() {
data["rootPath"] = consts.DemoTips
data["pwd"] = consts.DemoTips

View File

@ -130,7 +130,7 @@ func StartALL(sysCron []*entity.SysCron) error {
}
}
g.Log().Info(ct, "定时任务启动完毕...")
g.Log().Debug(ct, "load scheduled task complete..")
return nil
}

View File

@ -29,15 +29,9 @@ var (
}
)
// UpdatePostIds
// @Description:
// @receiver dao
// @param ctx
// @param memberId
// @param postIds
// @return err
//
// UpdatePostIds 更新管理员岗位
func (dao *adminMemberPostDao) UpdatePostIds(ctx context.Context, memberId int64, postIds []int64) (err error) {
g.DumpWithType(postIds)
_, err = dao.Ctx(ctx).
Where("member_id", memberId).
Delete()
@ -61,16 +55,8 @@ func (dao *adminMemberPostDao) UpdatePostIds(ctx context.Context, memberId int64
return nil
}
// GetMemberByIds 获取指定会员的岗位ids
// @Description:
// @receiver dao
// @param ctx
// @param memberId
// @return postIds
// @return err
//
// GetMemberByIds 获取指定关联员的岗位ids
func (dao *adminMemberPostDao) GetMemberByIds(ctx context.Context, memberId int64) (postIds []int64, err error) {
var list []*entity.AdminMemberPost
err = dao.Ctx(ctx).
Fields("post_id").
@ -85,6 +71,5 @@ func (dao *adminMemberPostDao) GetMemberByIds(ctx context.Context, memberId int6
postIds = append(postIds, list[i].PostId)
}
g.Log().Print(ctx, "post_ids:", postIds)
return postIds, nil
}

View File

@ -1,27 +0,0 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"hotgo/internal/dao/internal"
)
// internalAdminRoleDeptDao is internal type for wrapping internal DAO implements.
type internalAdminRoleDeptDao = *internal.AdminRoleDeptDao
// adminRoleDeptDao is the data access object for table hg_admin_role_dept.
// You can define custom methods on it to extend its functionality as you wish.
type adminRoleDeptDao struct {
internalAdminRoleDeptDao
}
var (
// AdminRoleDept is globally common accessible object for table hg_admin_role_dept operations.
AdminRoleDept = adminRoleDeptDao{
internal.NewAdminRoleDeptDao(),
}
)
// Fill with you ideas below.

View File

@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"hotgo/internal/dao/internal"
)
// internalDemoDao is internal type for wrapping internal DAO implements.
type internalDemoDao = *internal.DemoDao
// demoDao is the data access object for table hg_demo.
// You can define custom methods on it to extend its functionality as you wish.
type demoDao struct {
internalDemoDao
}
var (
// Demo is globally public accessible object for table hg_demo operations.
Demo = demoDao{
internal.NewDemoDao(),
}
)
// Fill with you ideas below.

View File

@ -20,8 +20,8 @@ type AdminDeptDao struct {
// AdminDeptColumns defines and stores column names for table hg_admin_dept.
type AdminDeptColumns struct {
Id string // 部门id
Pid string // 父部门id
Id string // 部门ID
Pid string // 父部门ID
Name string // 部门名称
Code string // 部门编码
Type string // 部门类型
@ -34,7 +34,7 @@ type AdminDeptColumns struct {
UpdatedAt string // 更新时间
}
// adminDeptColumns holds the columns for table hg_admin_dept.
// adminDeptColumns holds the columns for table hg_admin_dept.
var adminDeptColumns = AdminDeptColumns{
Id: "id",
Pid: "pid",
@ -90,6 +90,6 @@ func (dao *AdminDeptDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminDeptDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminDeptDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,64 +20,64 @@ type AdminMemberDao struct {
// AdminMemberColumns defines and stores column names for table hg_admin_member.
type AdminMemberColumns struct {
Id string //
Id string // 管理员ID
DeptId string // 部门ID
RoleId string // 角色ID
RealName string // 真实姓名
Username string // 帐号
PasswordHash string // 密码
Salt string // 密码盐
AuthKey string // 授权令牌
PasswordResetToken string // 密码重置令牌
Type string // 1:普通管理员;10超级管理员
Realname string // 真实姓名
Avatar string // 头像
Sex string // 性别[1:男;2:女;3:未知]
Sex string // 性别
Qq string // qq
Email string // 邮箱
Birthday string // 生日
ProvinceId string // 省
CityId string // 城市
AreaId string // 地区
Address string // 默认地址
Mobile string // 手机号码
HomePhone string // 家庭号码
DingtalkRobotToken string // 钉钉机器人token
Birthday string // 生日
ProvinceId string // 省编码
CityId string // 城市编码
CountyId string // 区域编码
Address string // 联系地址
VisitCount string // 访问次数
LastTime string // 最后一次登录时间
LastIp string // 最后一次登录ip
Role string // 权限
Pid string // 上级管理员ID
Level string // 关系树等级
Tree string // 关系树
Remark string // 备注
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
}
// adminMemberColumns holds the columns for table hg_admin_member.
// adminMemberColumns holds the columns for table hg_admin_member.
var adminMemberColumns = AdminMemberColumns{
Id: "id",
DeptId: "dept_id",
RoleId: "role_id",
RealName: "real_name",
Username: "username",
PasswordHash: "password_hash",
Salt: "salt",
AuthKey: "auth_key",
PasswordResetToken: "password_reset_token",
Type: "type",
Realname: "realname",
Avatar: "avatar",
Sex: "sex",
Qq: "qq",
Email: "email",
Mobile: "mobile",
Birthday: "birthday",
ProvinceId: "province_id",
CityId: "city_id",
AreaId: "area_id",
CountyId: "county_id",
Address: "address",
Mobile: "mobile",
HomePhone: "home_phone",
DingtalkRobotToken: "dingtalk_robot_token",
VisitCount: "visit_count",
LastTime: "last_time",
LastIp: "last_ip",
Role: "role",
Pid: "pid",
Level: "level",
Tree: "tree",
Remark: "remark",
Status: "status",
CreatedAt: "created_at",
@ -124,6 +124,6 @@ func (dao *AdminMemberDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminMemberDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminMemberDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,11 +20,11 @@ type AdminMemberPostDao struct {
// AdminMemberPostColumns defines and stores column names for table hg_admin_member_post.
type AdminMemberPostColumns struct {
MemberId string // 用户ID
MemberId string // 管理员ID
PostId string // 岗位ID
}
// adminMemberPostColumns holds the columns for table hg_admin_member_post.
// adminMemberPostColumns holds the columns for table hg_admin_member_post.
var adminMemberPostColumns = AdminMemberPostColumns{
MemberId: "member_id",
PostId: "post_id",
@ -70,6 +70,6 @@ func (dao *AdminMemberPostDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminMemberPostDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminMemberPostDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,11 +20,11 @@ type AdminMemberRoleDao struct {
// AdminMemberRoleColumns defines and stores column names for table hg_admin_member_role.
type AdminMemberRoleColumns struct {
MemberId string // 用户ID
MemberId string // 管理员ID
RoleId string // 角色ID
}
// adminMemberRoleColumns holds the columns for table hg_admin_member_role.
// adminMemberRoleColumns holds the columns for table hg_admin_member_role.
var adminMemberRoleColumns = AdminMemberRoleColumns{
MemberId: "member_id",
RoleId: "role_id",
@ -70,6 +70,6 @@ func (dao *AdminMemberRoleDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminMemberRoleDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminMemberRoleDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -39,8 +39,8 @@ type AdminMenuColumns struct {
KeepAlive string // 缓存该路由
Hidden string // 是否隐藏
Affix string // 是否固定
Level string //
Tree string //
Level string // 关系树等
Tree string // 关系
Sort string // 排序
Remark string // 备注
Status string // 菜单状态
@ -48,7 +48,7 @@ type AdminMenuColumns struct {
UpdatedAt string // 更新时间
}
// adminMenuColumns holds the columns for table hg_admin_menu.
// adminMenuColumns holds the columns for table hg_admin_menu.
var adminMenuColumns = AdminMenuColumns{
Id: "id",
Pid: "pid",
@ -118,6 +118,6 @@ func (dao *AdminMenuDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminMenuDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminMenuDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -22,7 +22,7 @@ type AdminNoticeDao struct {
type AdminNoticeColumns struct {
Id string // 公告ID
Title string // 公告标题
Type string // 公告类型1通知 2公告
Type string // 公告类型
Content string // 公告内容
Receiver string // 接收者
Reader string // 已读人
@ -33,7 +33,7 @@ type AdminNoticeColumns struct {
UpdatedAt string // 更新时间
}
// adminNoticeColumns holds the columns for table hg_admin_notice.
// adminNoticeColumns holds the columns for table hg_admin_notice.
var adminNoticeColumns = AdminNoticeColumns{
Id: "id",
Title: "title",
@ -88,6 +88,6 @@ func (dao *AdminNoticeDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminNoticeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminNoticeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -30,7 +30,7 @@ type AdminPostColumns struct {
UpdatedAt string // 更新时间
}
// adminPostColumns holds the columns for table hg_admin_post.
// adminPostColumns holds the columns for table hg_admin_post.
var adminPostColumns = AdminPostColumns{
Id: "id",
Code: "code",
@ -82,6 +82,6 @@ func (dao *AdminPostDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminPostDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminPostDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,32 +20,36 @@ type AdminRoleDao struct {
// AdminRoleColumns defines and stores column names for table hg_admin_role.
type AdminRoleColumns struct {
Id string // 角色ID
Name string // 角色名称
Key string // 角色权限字符串
DataScope string // 数据范围1全部数据权限 2自定数据权限 3本部门数据权限 4本部门及以下数据权限
MenuCheckStrictly string // 菜单树选择项是否关联显示
DeptCheckStrictly string // 部门树选择项是否关联显示
Remark string // 备注
Sort string // 排序
Status string // 角色状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
Id string // 角色ID
Name string // 角色名称
Key string // 角色权限字符串
DataScope string // 数据范围
CustomDept string // 自定义部门权限
Pid string // 上级角色ID
Level string // 关系树等级
Tree string // 关系树
Remark string // 备注
Sort string // 排序
Status string // 角色状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// adminRoleColumns holds the columns for table hg_admin_role.
// adminRoleColumns holds the columns for table hg_admin_role.
var adminRoleColumns = AdminRoleColumns{
Id: "id",
Name: "name",
Key: "key",
DataScope: "data_scope",
MenuCheckStrictly: "menu_check_strictly",
DeptCheckStrictly: "dept_check_strictly",
Remark: "remark",
Sort: "sort",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
Id: "id",
Name: "name",
Key: "key",
DataScope: "data_scope",
CustomDept: "custom_dept",
Pid: "pid",
Level: "level",
Tree: "tree",
Remark: "remark",
Sort: "sort",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewAdminRoleDao creates and returns a new DAO object for table data access.
@ -88,6 +92,6 @@ func (dao *AdminRoleDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminRoleDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminRoleDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -30,7 +30,7 @@ type AdminRoleCasbinColumns struct {
V5 string //
}
// adminRoleCasbinColumns holds the columns for table hg_admin_role_casbin.
// adminRoleCasbinColumns holds the columns for table hg_admin_role_casbin.
var adminRoleCasbinColumns = AdminRoleCasbinColumns{
Id: "id",
PType: "p_type",
@ -82,6 +82,6 @@ func (dao *AdminRoleCasbinDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminRoleCasbinDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminRoleCasbinDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -1,75 +0,0 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// AdminRoleDeptDao is the data access object for table hg_admin_role_dept.
type AdminRoleDeptDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns AdminRoleDeptColumns // columns contains all the column names of Table for convenient usage.
}
// AdminRoleDeptColumns defines and stores column names for table hg_admin_role_dept.
type AdminRoleDeptColumns struct {
RoleId string // 角色ID
DeptId string // 部门ID
}
// adminRoleDeptColumns holds the columns for table hg_admin_role_dept.
var adminRoleDeptColumns = AdminRoleDeptColumns{
RoleId: "role_id",
DeptId: "dept_id",
}
// NewAdminRoleDeptDao creates and returns a new DAO object for table data access.
func NewAdminRoleDeptDao() *AdminRoleDeptDao {
return &AdminRoleDeptDao{
group: "default",
table: "hg_admin_role_dept",
columns: adminRoleDeptColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *AdminRoleDeptDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *AdminRoleDeptDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *AdminRoleDeptDao) Columns() AdminRoleDeptColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *AdminRoleDeptDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *AdminRoleDeptDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminRoleDeptDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -24,7 +24,7 @@ type AdminRoleMenuColumns struct {
MenuId string // 菜单ID
}
// adminRoleMenuColumns holds the columns for table hg_admin_role_menu.
// adminRoleMenuColumns holds the columns for table hg_admin_role_menu.
var adminRoleMenuColumns = AdminRoleMenuColumns{
RoleId: "role_id",
MenuId: "menu_id",
@ -70,6 +70,6 @@ func (dao *AdminRoleMenuDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AdminRoleMenuDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *AdminRoleMenuDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -0,0 +1,143 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// DemoDao is the data access object for table hg_demo.
type DemoDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns DemoColumns // columns contains all the column names of Table for convenient usage.
}
// DemoColumns defines and stores column names for table hg_demo.
type DemoColumns struct {
Id string // ID
CategoryId string // 分类ID
Flag string // 标签
Title string // 标题
Description string // 描述
Content string // 内容
Image string // 单图
Images string // 多图
Attachfile string // 附件
Attachfiles string // 多附件
Map string // 动态键值对
Star string // 推荐星
Price string // 价格
Views string // 浏览次数
ActivityAt string // 活动时间
StartAt string // 开启时间
EndAt string // 结束时间
Switch string // 开关
Sort string // 排序
Avatar string // 头像
Sex string // 性别
Qq string // qq
Email string // 邮箱
Mobile string // 手机号码
Hobby string // 爱好
Channel string // 渠道
Pid string // 上级ID
Level string // 树等级
Tree string // 关系树
Remark string // 备注
Status string // 状态
CreatedBy string // 创建者
UpdatedBy string // 更新者
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
DeletedAt string // 删除时间
}
// demoColumns holds the columns for table hg_demo.
var demoColumns = DemoColumns{
Id: "id",
CategoryId: "category_id",
Flag: "flag",
Title: "title",
Description: "description",
Content: "content",
Image: "image",
Images: "images",
Attachfile: "attachfile",
Attachfiles: "attachfiles",
Map: "map",
Star: "star",
Price: "price",
Views: "views",
ActivityAt: "activity_at",
StartAt: "start_at",
EndAt: "end_at",
Switch: "switch",
Sort: "sort",
Avatar: "avatar",
Sex: "sex",
Qq: "qq",
Email: "email",
Mobile: "mobile",
Hobby: "hobby",
Channel: "channel",
Pid: "pid",
Level: "level",
Tree: "tree",
Remark: "remark",
Status: "status",
CreatedBy: "created_by",
UpdatedBy: "updated_by",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
DeletedAt: "deleted_at",
}
// NewDemoDao creates and returns a new DAO object for table data access.
func NewDemoDao() *DemoDao {
return &DemoDao{
group: "default",
table: "hg_demo",
columns: demoColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *DemoDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *DemoDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *DemoDao) Columns() DemoColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *DemoDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *DemoDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *DemoDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,18 +20,18 @@ type SysAttachmentDao struct {
// SysAttachmentColumns defines and stores column names for table hg_sys_attachment.
type SysAttachmentColumns struct {
Id string //
Id string // 文件ID
AppId string // 应用ID
MemberId string // 用户
CateId string // 分类
Drive string // 驱动
MemberId string // 管理员ID
CateId string // 上传分类
Drive string // 上传驱动
Name string // 文件原始名
Kind string // 上传类型
MetaType string // 类别
MetaType string // 文件类型
NaiveType string // NaiveUI类型
Path string // 本地路径
FileUrl string // url
Size string // 长度
Size string // 文件大小
Ext string // 扩展名
Md5 string // md5校验码
Status string // 状态
@ -39,7 +39,7 @@ type SysAttachmentColumns struct {
UpdatedAt string // 修改时间
}
// sysAttachmentColumns holds the columns for table hg_sys_attachment.
// sysAttachmentColumns holds the columns for table hg_sys_attachment.
var sysAttachmentColumns = SysAttachmentColumns{
Id: "id",
AppId: "app_id",
@ -100,6 +100,6 @@ func (dao *SysAttachmentDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysAttachmentDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysAttachmentDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,15 +20,15 @@ type SysBlacklistDao struct {
// SysBlacklistColumns defines and stores column names for table hg_sys_blacklist.
type SysBlacklistColumns struct {
Id string // 主键
Ip string // ip地址
Id string // 黑名单ID
Ip string // IP地址
Remark string // 备注
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysBlacklistColumns holds the columns for table hg_sys_blacklist.
// sysBlacklistColumns holds the columns for table hg_sys_blacklist.
var sysBlacklistColumns = SysBlacklistColumns{
Id: "id",
Ip: "ip",
@ -78,6 +78,6 @@ func (dao *SysBlacklistDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysBlacklistDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysBlacklistDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -21,21 +21,21 @@ type SysConfigDao struct {
// SysConfigColumns defines and stores column names for table hg_sys_config.
type SysConfigColumns struct {
Id string // 配置ID
Group string // 分组
Group string // 配置分组
Name string // 参数名称
Type string // 类型:string,text,int,bool,array,datetime,date,file
Type string // 键值类型:string,int,uint,bool,datetime,date
Key string // 参数键名
Value string // 参数键值
DefaultValue string // 默认值
Sort string // 排序
Tip string // 变量描述
IsDefault string // 是否默认
IsDefault string // 是否为系统默认
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysConfigColumns holds the columns for table hg_sys_config.
// sysConfigColumns holds the columns for table hg_sys_config.
var sysConfigColumns = SysConfigColumns{
Id: "id",
Group: "group",
@ -92,6 +92,6 @@ func (dao *SysConfigDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysConfigDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysConfigDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,7 +20,7 @@ type SysCronDao struct {
// SysCronColumns defines and stores column names for table hg_sys_cron.
type SysCronColumns struct {
Id string // 主键
Id string // 任务ID
GroupId string // 分组ID
Name string // 任务名称
Params string // 函数参数
@ -29,12 +29,12 @@ type SysCronColumns struct {
Count string // 执行次数
Sort string // 排序
Remark string // 备注
Status string // 状态
Status string // 任务状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysCronColumns holds the columns for table hg_sys_cron.
// sysCronColumns holds the columns for table hg_sys_cron.
var sysCronColumns = SysCronColumns{
Id: "id",
GroupId: "group_id",
@ -90,6 +90,6 @@ func (dao *SysCronDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysCronDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysCronDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,18 +20,18 @@ type SysCronGroupDao struct {
// SysCronGroupColumns defines and stores column names for table hg_sys_cron_group.
type SysCronGroupColumns struct {
Id string // 主键
Pid string // 父类ID
Id string // 任务分组ID
Pid string // 父类任务分组ID
Name string // 分组名称
IsDefault string // 是否默认
Sort string // 排序
Remark string // 备注
Status string // 状态
Status string // 分组状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysCronGroupColumns holds the columns for table hg_sys_cron_group.
// sysCronGroupColumns holds the columns for table hg_sys_cron_group.
var sysCronGroupColumns = SysCronGroupColumns{
Id: "id",
Pid: "pid",
@ -84,6 +84,6 @@ func (dao *SysCronGroupDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysCronGroupDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysCronGroupDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,12 +20,13 @@ type SysDictDataDao struct {
// SysDictDataColumns defines and stores column names for table hg_sys_dict_data.
type SysDictDataColumns struct {
Id string // 字典编码
Id string // 字典数据ID
Label string // 字典标签
Value string // 字典键值
ValueType string // 键值数据类型string,int,uint,bool,datetime,date
Type string // 字典类型
ListClass string // 表格回显样式
IsDefault string // 是否默认
IsDefault string // 是否为系统默认
Sort string // 字典排序
Remark string // 备注
Status string // 状态
@ -33,11 +34,12 @@ type SysDictDataColumns struct {
UpdatedAt string // 更新时间
}
// sysDictDataColumns holds the columns for table hg_sys_dict_data.
// sysDictDataColumns holds the columns for table hg_sys_dict_data.
var sysDictDataColumns = SysDictDataColumns{
Id: "id",
Label: "label",
Value: "value",
ValueType: "value_type",
Type: "type",
ListClass: "list_class",
IsDefault: "is_default",
@ -88,6 +90,6 @@ func (dao *SysDictDataDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysDictDataDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysDictDataDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,18 +20,18 @@ type SysDictTypeDao struct {
// SysDictTypeColumns defines and stores column names for table hg_sys_dict_type.
type SysDictTypeColumns struct {
Id string // 字典主键
Pid string // 父类ID
Name string // 字典名称
Id string // 字典类型ID
Pid string // 父类字典类型ID
Name string // 字典类型名称
Type string // 字典类型
Sort string // 排序
Remark string // 备注
Status string // 状态
Status string // 字典类型状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysDictTypeColumns holds the columns for table hg_sys_dict_type.
// sysDictTypeColumns holds the columns for table hg_sys_dict_type.
var sysDictTypeColumns = SysDictTypeColumns{
Id: "id",
Pid: "pid",
@ -84,6 +84,6 @@ func (dao *SysDictTypeDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysDictTypeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysDictTypeDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -0,0 +1,95 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// SysGenCodesDao is the data access object for table hg_sys_gen_codes.
type SysGenCodesDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns SysGenCodesColumns // columns contains all the column names of Table for convenient usage.
}
// SysGenCodesColumns defines and stores column names for table hg_sys_gen_codes.
type SysGenCodesColumns struct {
Id string // 生成ID
GenType string // 生成类型
VarName string // 实体命名
Options string // 配置选项
DbName string // 数据库名称
TableName string // 主表名称
TableComment string // 主表注释
DaoName string // 主表dao模型
MasterColumns string // 主表字段
Status string // 生成状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysGenCodesColumns holds the columns for table hg_sys_gen_codes.
var sysGenCodesColumns = SysGenCodesColumns{
Id: "id",
GenType: "gen_type",
VarName: "var_name",
Options: "options",
DbName: "db_name",
TableName: "table_name",
TableComment: "table_comment",
DaoName: "dao_name",
MasterColumns: "master_columns",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewSysGenCodesDao creates and returns a new DAO object for table data access.
func NewSysGenCodesDao() *SysGenCodesDao {
return &SysGenCodesDao{
group: "default",
table: "hg_sys_gen_codes",
columns: sysGenCodesColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *SysGenCodesDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *SysGenCodesDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *SysGenCodesDao) Columns() SysGenCodesColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *SysGenCodesDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *SysGenCodesDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysGenCodesDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -0,0 +1,101 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// SysGenCurdDemoDao is the data access object for table hg_sys_gen_curd_demo.
type SysGenCurdDemoDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns SysGenCurdDemoColumns // columns contains all the column names of Table for convenient usage.
}
// SysGenCurdDemoColumns defines and stores column names for table hg_sys_gen_curd_demo.
type SysGenCurdDemoColumns struct {
Id string // ID
CategoryId string // 分类ID
Title string // 标题
Description string // 描述
Content string // 内容
Image string // 单图
Attachfile string // 附件
Switch string // 显示开关
Sort string // 排序
Status string // 状态
CreatedBy string // 创建者
UpdatedBy string // 更新者
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
DeletedAt string // 删除时间
}
// sysGenCurdDemoColumns holds the columns for table hg_sys_gen_curd_demo.
var sysGenCurdDemoColumns = SysGenCurdDemoColumns{
Id: "id",
CategoryId: "category_id",
Title: "title",
Description: "description",
Content: "content",
Image: "image",
Attachfile: "attachfile",
Switch: "switch",
Sort: "sort",
Status: "status",
CreatedBy: "created_by",
UpdatedBy: "updated_by",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
DeletedAt: "deleted_at",
}
// NewSysGenCurdDemoDao creates and returns a new DAO object for table data access.
func NewSysGenCurdDemoDao() *SysGenCurdDemoDao {
return &SysGenCurdDemoDao{
group: "default",
table: "hg_sys_gen_curd_demo",
columns: sysGenCurdDemoColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *SysGenCurdDemoDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *SysGenCurdDemoDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *SysGenCurdDemoDao) Columns() SysGenCurdDemoColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *SysGenCurdDemoDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *SysGenCurdDemoDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysGenCurdDemoDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,23 +20,23 @@ type SysLogDao struct {
// SysLogColumns defines and stores column names for table hg_sys_log.
type SysLogColumns struct {
Id string //
AppId string // 应用id
MerchantId string // 商户id
MemberId string // 用户id
Id string // 日志ID
AppId string // 应用ID
MerchantId string // 商户ID
MemberId string // 用户ID
Method string // 提交类型
Module string // 模块
Module string // 访问模块
Url string // 提交url
GetData string // get数据
PostData string // post数据
HeaderData string // header数据
Ip string // ip地址
Ip string // IP地址
ProvinceId string // 省编码
CityId string // 市编码
ErrorCode string // 报错code
ErrorMsg string // 报错信息
ErrorData string // 报错日志
ReqId string // 对外id
ReqId string // 对外ID
Timestamp string // 响应时间
UserAgent string // UA信息
TakeUpTime string // 请求耗时
@ -45,7 +45,7 @@ type SysLogColumns struct {
UpdatedAt string // 修改时间
}
// sysLogColumns holds the columns for table hg_sys_log.
// sysLogColumns holds the columns for table hg_sys_log.
var sysLogColumns = SysLogColumns{
Id: "id",
AppId: "app_id",
@ -112,6 +112,6 @@ func (dao *SysLogDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysLogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysLogDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -20,34 +20,34 @@ type SysProvincesDao struct {
// SysProvincesColumns defines and stores column names for table hg_sys_provinces.
type SysProvincesColumns struct {
Id string // ID
Title string // 栏目名
Pid string // 父栏目
Id string // 省市区ID
Title string // 栏目名称
ShortTitle string // 缩写
Areacode string // 区域编码
Zipcode string // 邮政编码
Pinyin string // 拼音
Lng string // 经度
Lat string // 纬度
Level string // 级别
Tree string //
Pid string // 父栏目
Level string // 关系树等级
Tree string // 关系
Sort string // 排序
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 更新时间
}
// sysProvincesColumns holds the columns for table hg_sys_provinces.
// sysProvincesColumns holds the columns for table hg_sys_provinces.
var sysProvincesColumns = SysProvincesColumns{
Id: "id",
Title: "title",
Pid: "pid",
ShortTitle: "short_title",
Areacode: "areacode",
Zipcode: "zipcode",
Pinyin: "pinyin",
Lng: "lng",
Lat: "lat",
Pid: "pid",
Level: "level",
Tree: "tree",
Sort: "sort",
@ -96,6 +96,6 @@ func (dao *SysProvincesDao) Ctx(ctx context.Context) *gdb.Model {
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *SysProvincesDao) Transaction(ctx context.Context, f func(ctx context.Context, tx *gdb.TX) error) (err error) {
func (dao *SysProvincesDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -0,0 +1,143 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// TestDao is the data access object for table hg_test.
type TestDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns TestColumns // columns contains all the column names of Table for convenient usage.
}
// TestColumns defines and stores column names for table hg_test.
type TestColumns struct {
Id string // ID
CategoryId string // 分类ID
Flag string // 标签
Title string // 标题
Description string // 描述
Content string // 内容
Image string // 单图
Images string // 多图
Attachfile string // 附件
Attachfiles string // 多附件
Map string // 动态键值对
Star string // 推荐星
Price string // 价格
Views string // 浏览次数
ActivityAt string // 活动时间
StartAt string // 开启时间
EndAt string // 结束时间
Switch string // 开关
Sort string // 排序
Avatar string // 头像
Sex string // 性别
Qq string // qq
Email string // 邮箱
Mobile string // 手机号码
Hobby string // 爱好
Channel string // 渠道
Pid string // 上级ID
Level string // 树等级
Tree string // 关系树
Remark string // 备注
Status string // 状态
CreatedBy string // 创建者
UpdatedBy string // 更新者
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
DeletedAt string // 删除时间
}
// testColumns holds the columns for table hg_test.
var testColumns = TestColumns{
Id: "id",
CategoryId: "category_id",
Flag: "flag",
Title: "title",
Description: "description",
Content: "content",
Image: "image",
Images: "images",
Attachfile: "attachfile",
Attachfiles: "attachfiles",
Map: "map",
Star: "star",
Price: "price",
Views: "views",
ActivityAt: "activity_at",
StartAt: "start_at",
EndAt: "end_at",
Switch: "switch",
Sort: "sort",
Avatar: "avatar",
Sex: "sex",
Qq: "qq",
Email: "email",
Mobile: "mobile",
Hobby: "hobby",
Channel: "channel",
Pid: "pid",
Level: "level",
Tree: "tree",
Remark: "remark",
Status: "status",
CreatedBy: "created_by",
UpdatedBy: "updated_by",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
DeletedAt: "deleted_at",
}
// NewTestDao creates and returns a new DAO object for table data access.
func NewTestDao() *TestDao {
return &TestDao{
group: "default",
table: "hg_test",
columns: testColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *TestDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *TestDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *TestDao) Columns() TestColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *TestDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *TestDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *TestDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -0,0 +1,89 @@
// ==========================================================================
// Code generated by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// TestCategoryDao is the data access object for table hg_test_category.
type TestCategoryDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns TestCategoryColumns // columns contains all the column names of Table for convenient usage.
}
// TestCategoryColumns defines and stores column names for table hg_test_category.
type TestCategoryColumns struct {
Id string // 分类ID
Name string // 分类名称
Description string // 描述
Sort string // 排序
Remark string // 备注
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
DeletedAt string // 删除时间
}
// testCategoryColumns holds the columns for table hg_test_category.
var testCategoryColumns = TestCategoryColumns{
Id: "id",
Name: "name",
Description: "description",
Sort: "sort",
Remark: "remark",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
DeletedAt: "deleted_at",
}
// NewTestCategoryDao creates and returns a new DAO object for table data access.
func NewTestCategoryDao() *TestCategoryDao {
return &TestCategoryDao{
group: "default",
table: "hg_test_category",
columns: testCategoryColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *TestCategoryDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *TestCategoryDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *TestCategoryDao) Columns() TestCategoryColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *TestCategoryDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *TestCategoryDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *TestCategoryDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

@ -7,6 +7,8 @@ package dao
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/consts"
"hotgo/internal/dao/internal"
"hotgo/internal/model/input/sysin"
@ -31,10 +33,8 @@ var (
)
func (dao *sysAttachmentDao) GetMd5File(ctx context.Context, md5 string) (data *sysin.AttachmentListModel, err error) {
if err = dao.Ctx(ctx).
Where("md5", md5).
Where("status", consts.StatusEnabled).
Scan(&data); err != nil {
err = gerror.Wrap(err, consts.ErrorORM)
return nil, err
@ -44,8 +44,21 @@ func (dao *sysAttachmentDao) GetMd5File(ctx context.Context, md5 string) (data *
return nil, nil
}
conf, err := service.SysConfig().GetUpload(ctx)
if err != nil {
return nil, nil
}
data.SizeFormat = format.FileSize(data.Size)
data.FileUrl = service.CommonUpload().LastUrl(ctx, data.FileUrl, data.Drive)
data.FileUrl = service.CommonUpload().LastUrl(ctx, conf, data.FileUrl, data.Drive)
// 只有在上传时才会检查md5值如果文件存在则更新最后上传时间保证上传列表更新显示在最前面
if data.Id > 0 {
_, _ = dao.Ctx(ctx).Where("id", data.Id).Data(g.Map{
"status": consts.StatusEnabled,
"updated_at": gtime.Now(),
}).Update()
}
return data, nil
}

View File

@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"hotgo/internal/dao/internal"
)
// internalSysGenCodesDao is internal type for wrapping internal DAO implements.
type internalSysGenCodesDao = *internal.SysGenCodesDao
// sysGenCodesDao is the data access object for table hg_sys_gen_codes.
// You can define custom methods on it to extend its functionality as you wish.
type sysGenCodesDao struct {
internalSysGenCodesDao
}
var (
// SysGenCodes is globally public accessible object for table hg_sys_gen_codes operations.
SysGenCodes = sysGenCodesDao{
internal.NewSysGenCodesDao(),
}
)
// Fill with you ideas below.

View File

@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"hotgo/internal/dao/internal"
)
// internalSysGenCurdDemoDao is internal type for wrapping internal DAO implements.
type internalSysGenCurdDemoDao = *internal.SysGenCurdDemoDao
// sysGenCurdDemoDao is the data access object for table hg_sys_gen_curd_demo.
// You can define custom methods on it to extend its functionality as you wish.
type sysGenCurdDemoDao struct {
internalSysGenCurdDemoDao
}
var (
// SysGenCurdDemo is globally public accessible object for table hg_sys_gen_curd_demo operations.
SysGenCurdDemo = sysGenCurdDemoDao{
internal.NewSysGenCurdDemoDao(),
}
)
// Fill with you ideas below.

View File

@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"hotgo/internal/dao/internal"
)
// internalTestDao is internal type for wrapping internal DAO implements.
type internalTestDao = *internal.TestDao
// testDao is the data access object for table hg_test.
// You can define custom methods on it to extend its functionality as you wish.
type testDao struct {
internalTestDao
}
var (
// Test is globally public accessible object for table hg_test operations.
Test = testDao{
internal.NewTestDao(),
}
)
// Fill with you ideas below.

View File

@ -0,0 +1,27 @@
// =================================================================================
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
// =================================================================================
package dao
import (
"hotgo/internal/dao/internal"
)
// internalTestCategoryDao is internal type for wrapping internal DAO implements.
type internalTestCategoryDao = *internal.TestCategoryDao
// testCategoryDao is the data access object for table hg_test_category.
// You can define custom methods on it to extend its functionality as you wish.
type testCategoryDao struct {
internalTestCategoryDao
}
var (
// TestCategory is globally public accessible object for table hg_test_category operations.
TestCategory = testCategoryDao{
internal.NewTestCategoryDao(),
}
)
// Fill with you ideas below.

View File

@ -10,29 +10,55 @@ import (
"context"
"fmt"
"github.com/gogf/gf/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcache"
"github.com/gogf/gf/v2/os/gtime"
"hotgo/internal/consts"
"hotgo/internal/library/hggen"
"hotgo/internal/library/location"
"hotgo/utility/simple"
"os"
)
func Init(ctx context.Context) {
if _, err := g.Cfg().Get(ctx, "hotgo.debug"); err != nil {
g.Log().Fatal(ctx, "配置读取异常:", err, "\r\n你确定 config/config.yaml 文件存在且格式正确吗?\r\n")
}
// 默认上海时区
if err := gtime.SetTimeZone("Asia/Shanghai"); err != nil {
fmt.Printf("时区设置异常err%v \r\n", err)
g.Log().Fatalf(ctx, "时区设置异常err%+v", err)
return
}
RootPtah, _ = os.Getwd()
fmt.Printf("欢迎使用HotGo\r\n当前运行环境%v, 运行根路径为:%v \r\nHotGo版本v%v, gf版本%v \n", SysType, RootPtah, consts.VersionApp, gf.VERSION)
loadMonitor(ctx)
setOrmCacheAdapter()
startMonitor(ctx)
hggen.InIt(ctx)
}
func loadMonitor(ctx context.Context) {
func startMonitor(ctx context.Context) {
simple.SafeGo(ctx, func(ctx context.Context) {
MonitorData.STartTime = gtime.Now()
MonitorData.IntranetIP, _ = location.GetLocalIP()
MonitorData.PublicIP, _ = location.GetPublicIP()
intranetIP, err := location.GetLocalIP()
if err != nil {
g.Log().Warningf(ctx, "parse intranetIP err:%+v", err)
}
MonitorData.IntranetIP = intranetIP
publicIP, err := location.GetPublicIP(ctx)
if err != nil {
g.Log().Warningf(ctx, "parse publicIP err:%+v", err)
}
MonitorData.PublicIP = publicIP
})
}
func setOrmCacheAdapter() {
redisCache := gcache.NewAdapterRedis(g.Redis())
g.DB().GetCache().SetAdapter(redisCache)
}

View File

@ -13,7 +13,6 @@ import (
"github.com/casbin/casbin/v2/model"
"github.com/casbin/casbin/v2/persist"
"github.com/gogf/gf/v2/database/gdb"
"log"
"math"
"strings"
)
@ -119,7 +118,6 @@ func (a *adapter) dropPolicyTable() (err error) {
// LoadPolicy loads all policy rules from the storage.
func (a *adapter) LoadPolicy(model model.Model) (err error) {
log.Println("LoadPolicy...")
var rules []policyRule
if err = a.model().Scan(&rules); err != nil {
@ -248,7 +246,7 @@ func (a *adapter) UpdatePolicies(sec string, ptype string, oldRules, newRules []
return
}
err = a.db.Transaction(context.TODO(), func(ctx context.Context, tx *gdb.TX) error {
err = a.db.Transaction(context.TODO(), func(ctx context.Context, tx gdb.TX) error {
for i := 0; i < int(math.Min(float64(len(oldRules)), float64(len(newRules)))); i++ {
if _, err = tx.Model(a.table).Update(a.buildPolicyRule(ptype, newRules[i]), a.buildPolicyRule(ptype, oldRules[i])); err != nil {
return err

View File

@ -29,8 +29,8 @@ var Enforcer *casbin.Enforcer
// InitEnforcer 初始化
func InitEnforcer(ctx context.Context) {
var (
link, _ = g.Cfg().Get(ctx, "database.default.link")
a, err = NewAdapter(link.String())
link = g.Cfg().MustGet(ctx, "database.default.link")
a, err = NewAdapter(link.String())
)
if err != nil {
@ -53,10 +53,10 @@ func loadPermissions(ctx context.Context) {
Permissions string `json:"permissions"`
}
var (
rules [][]string
polices []*Policy
err error
superRoleKey, _ = g.Cfg().Get(ctx, "hotgo.admin.superRoleKey")
rules [][]string
polices []*Policy
err error
superRoleKey = g.Cfg().MustGet(ctx, "hotgo.admin.superRoleKey")
)
err = g.Model("hg_admin_role r").

View File

@ -67,7 +67,7 @@ func GetRoleId(ctx context.Context) int64 {
return 0
}
return user.Role
return user.RoleId
}
// GetRoleKey 获取用户角色唯一编码

View File

@ -0,0 +1,13 @@
// Package debris
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package debris
// 碎片
func Test() {
}

View File

@ -0,0 +1,192 @@
// Package hggen
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package hggen
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/library/hggen/internal/cmd"
"hotgo/internal/library/hggen/internal/cmd/gendao"
"hotgo/internal/library/hggen/views"
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"sort"
)
// Dao 生成数据库实体
func Dao(ctx context.Context) (err error) {
for _, v := range daoConfig {
inp := defaultGenDaoInput
err = gconv.Scan(v, &inp)
if err != nil {
return
}
gendao.DoGenDaoForArray(ctx, inp)
}
return
}
// Service 生成业务接口
func Service(ctx context.Context) (err error) {
_, err = cmd.Gen.Service(ctx, GetServiceConfig())
return
}
// TableColumns 获取指定表生成字段列表
func TableColumns(ctx context.Context, in sysin.GenCodesColumnListInp) (fields []*sysin.GenCodesColumnListModel, err error) {
return views.DoTableColumns(ctx, in, GetDaoConfig(in.Name))
}
func TableSelects(ctx context.Context, in sysin.GenCodesSelectsInp) (res *sysin.GenCodesSelectsModel, err error) {
res = new(sysin.GenCodesSelectsModel)
for k, v := range consts.GenCodesTypeNameMap {
res.GenType = append(res.GenType, &form.Select{
Value: k,
Name: v,
Label: v,
})
}
sort.Sort(res.GenType)
res.Db = DbSelect(ctx)
for k, v := range consts.GenCodesStatusNameMap {
res.Status = append(res.Status, &form.Select{
Value: k,
Name: v,
Label: v,
})
}
sort.Sort(res.Status)
for k, v := range consts.GenCodesJoinNameMap {
res.LinkMode = append(res.LinkMode, &form.Select{
Value: k,
Name: v,
Label: v,
})
}
sort.Sort(res.LinkMode)
for k, v := range consts.GenCodesBuildMethNameMap {
res.BuildMeth = append(res.BuildMeth, &form.Select{
Value: k,
Name: v,
Label: v,
})
}
sort.Sort(res.BuildMeth)
for _, v := range views.FormModes {
res.FormMode = append(res.FormMode, &form.Select{
Value: v,
Name: views.FormModeMap[v],
Label: views.FormModeMap[v],
})
}
sort.Sort(res.FormMode)
for k, v := range views.FormRoleMap {
res.FormRole = append(res.FormRole, &form.Select{
Value: k,
Name: v,
Label: v,
})
}
sort.Sort(res.FormRole)
dictMode, _ := service.SysDictType().TreeSelect(ctx, sysin.DictTreeSelectInp{})
res.DictMode = dictMode
for _, v := range views.WhereModes {
res.WhereMode = append(res.WhereMode, &form.Select{
Value: v,
Name: v,
Label: v,
})
}
return
}
// DbSelect db选项
func DbSelect(ctx context.Context) (res form.Selects) {
dbs := g.Cfg().MustGet(ctx, "hggen.selectDbs")
if len(dbs.Strings()) == 0 {
res = make(form.Selects, 0)
return res
}
for _, v := range dbs.Strings() {
res = append(res, &form.Select{
Value: v,
Label: v,
Name: v,
})
}
return res
}
// Preview 生成预览
func Preview(ctx context.Context, in sysin.GenCodesPreviewInp) (res *sysin.GenCodesPreviewModel, err error) {
genConfig, err := service.SysConfig().GetLoadGenerate(ctx)
if err != nil {
return nil, err
}
switch in.GenType {
case consts.GenCodesTypeCurd:
return views.Curd.DoPreview(ctx, &views.CurdPreviewInput{
In: in,
DaoConfig: GetDaoConfig(in.DbName),
Config: genConfig,
})
case consts.GenCodesTypeTree:
err = gerror.Newf("生成类型开发中!")
return
case consts.GenCodesTypeQueue:
err = gerror.Newf("生成类型开发中!")
return
default:
err = gerror.Newf("生成类型暂不支持!")
return
}
}
// Build 提交生成
func Build(ctx context.Context, in sysin.GenCodesBuildInp) (err error) {
genConfig, err := service.SysConfig().GetLoadGenerate(ctx)
if err != nil {
return err
}
switch in.GenType {
case consts.GenCodesTypeCurd:
return views.Curd.DoBuild(ctx, &views.CurdBuildInput{
PreviewIn: &views.CurdPreviewInput{
In: sysin.GenCodesPreviewInp(in),
DaoConfig: GetDaoConfig(in.DbName),
Config: genConfig,
},
BeforeEvent: views.CurdBuildEvent{"runDao": Dao},
AfterEvent: views.CurdBuildEvent{"runService": Service},
})
case consts.GenCodesTypeTree:
err = gerror.Newf("生成类型开发中!")
return
case consts.GenCodesTypeQueue:
err = gerror.Newf("生成类型开发中!")
return
default:
err = gerror.Newf("生成类型暂不支持!")
return
}
}

View File

@ -0,0 +1,133 @@
// Package hggen
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2022 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package hggen
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/util/gconv"
"gopkg.in/yaml.v3"
"hotgo/internal/library/hggen/internal/cmd/gendao"
"hotgo/internal/library/hggen/internal/cmd/genservice"
)
const (
cliFolderName = `hack/config.yaml`
RequiredErrorTag = `the cli configuration file must be configured %s`
)
var (
config g.Map
daoConfig []interface{}
serviceConfig g.Map
// 生成service默认参数请不要直接修改以下配置如需调整请到/hack/config.yaml可参考https://goframe.org/pages/viewpage.action?pageId=49770772
defaultGenServiceInput = genservice.CGenServiceInput{
SrcFolder: "internal/logic",
DstFolder: "internal/service",
DstFileNameCase: "Snake",
StPattern: `s([A-Z]\w+)`,
Clear: false,
}
// 生成dao默认参数请不要直接修改以下配置如需调整请到/hack/config.yaml可参考https://goframe.org/pages/viewpage.action?pageId=3673173
defaultGenDaoInput = gendao.CGenDaoInput{
Path: "internal",
Group: "default",
JsonCase: "CamelLower",
DaoPath: "dao",
DoPath: "model/do",
EntityPath: "model/entity",
StdTime: false,
WithTime: false,
GJsonSupport: false,
OverwriteDao: false,
DescriptionTag: true,
NoJsonTag: false,
NoModelComment: false,
Clear: false,
}
)
func GetServiceConfig() genservice.CGenServiceInput {
inp := defaultGenServiceInput
_ = gconv.Scan(serviceConfig, &inp)
return inp
}
func GetDaoConfig(group string) gendao.CGenDaoInput {
inp := defaultGenDaoInput
find := func(group string) g.Map {
for _, v := range daoConfig {
if v.(g.Map)["group"].(string) == group {
return v.(g.Map)
}
}
return nil
}
v := find(group)
if v != nil {
err := gconv.Scan(v, &inp)
if err != nil {
panic(err)
}
}
return inp
}
func InIt(ctx context.Context) {
path, err := gfile.Search(cliFolderName)
if err != nil {
g.Log().Fatalf(ctx, "get cli configuration file:%v, err:%+v", cliFolderName, err)
}
if path == "" {
g.Log().Fatalf(ctx, "get cli configuration file:%v fail", cliFolderName)
}
if config == nil {
config = make(g.Map)
}
err = yaml.Unmarshal(gfile.GetBytes(path), &config)
if err != nil {
g.Log().Fatalf(ctx, "load cli configuration file:%v, yaml err:%+v", cliFolderName, err)
}
loadConfig(ctx)
}
func loadConfig(ctx context.Context) {
if _, ok := config["gfcli"]; !ok {
g.Log().Fatalf(ctx, RequiredErrorTag, "gfcli")
}
if _, ok := config["gfcli"].(g.Map)["gen"]; !ok {
g.Log().Fatalf(ctx, RequiredErrorTag, "gfcli.gen")
}
dao, ok := config["gfcli"].(g.Map)["gen"].(map[string]interface{})["dao"]
if !ok {
g.Log().Fatalf(ctx, RequiredErrorTag, "gfcli.gen.dao")
}
daoConf, ok := dao.([]interface{})
if !ok {
g.Log().Fatalf(ctx, RequiredErrorTag, "gfcli.gen.dao format error")
}
daoConfig = daoConf
for _, v := range daoConfig {
if _, ok := v.(g.Map)["group"].(string); !ok {
g.Log().Fatalf(ctx, "group must be configured in %s: `gfcli.gen.dao` and must be the same as the database group", cliFolderName)
}
}
if serviceConf, ok := config["gfcli"].(g.Map)["gen"].(map[string]interface{})["service"]; ok {
if serviceConfig == nil {
serviceConfig = make(g.Map)
}
serviceConfig = serviceConf.(g.Map)
}
}

View File

@ -0,0 +1,66 @@
package cmd
import (
"context"
"strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/util/gtag"
"hotgo/internal/library/hggen/internal/service"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
GF = cGF{}
)
type cGF struct {
g.Meta `name:"gf" ad:"{cGFAd}"`
}
const (
cGFAd = `
ADDITIONAL
Use "gf COMMAND -h" for details about a command.
`
)
func init() {
gtag.Sets(g.MapStrStr{
`cGFAd`: cGFAd,
})
}
type cGFInput struct {
g.Meta `name:"gf"`
Yes bool `short:"y" name:"yes" brief:"all yes for all command without prompt ask" orphan:"true"`
Version bool `short:"v" name:"version" brief:"show version information of current binary" orphan:"true"`
Debug bool `short:"d" name:"debug" brief:"show internal detailed debugging information" orphan:"true"`
}
type cGFOutput struct{}
func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error) {
// Version.
if in.Version {
_, err = Version.Index(ctx, cVersionInput{})
return
}
// No argument or option, do installation checks.
if !service.Install.IsInstalled() {
mlog.Print("hi, it seams it's the first time you installing gf cli.")
s := gcmd.Scanf("do you want to install gf binary to your system? [y/n]: ")
if strings.EqualFold(s, "y") {
if err = service.Install.Run(ctx); err != nil {
return
}
gcmd.Scan("press `Enter` to exit...")
return
}
}
// Print help content.
gcmd.CommandFromCtx(ctx).Print()
return
}

View File

@ -0,0 +1,327 @@
package cmd
import (
"context"
"encoding/json"
"fmt"
"os"
"regexp"
"runtime"
"strings"
"github.com/gogf/gf/v2/encoding/gbase64"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/genv"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Build = cBuild{
nodeNameInConfigFile: "gfcli.build",
packedGoFileName: "internal/packed/build_pack_data.go",
}
)
type cBuild struct {
g.Meta `name:"build" brief:"{cBuildBrief}" dc:"{cBuildDc}" eg:"{cBuildEg}" ad:"{cBuildAd}"`
nodeNameInConfigFile string // nodeNameInConfigFile is the node name for compiler configurations in configuration file.
packedGoFileName string // packedGoFileName specifies the file name for packing common folders into one single go file.
}
const (
cBuildBrief = `cross-building go project for lots of platforms`
cBuildEg = `
gf build main.go
gf build main.go --pack public,template
gf build main.go --cgo
gf build main.go -m none
gf build main.go -n my-app -a all -s all
gf build main.go -n my-app -a amd64,386 -s linux -p .
gf build main.go -n my-app -v 1.0 -a amd64,386 -s linux,windows,darwin -p ./docker/bin
`
cBuildDc = `
The "build" command is most commonly used command, which is designed as a powerful wrapper for
"go build" command for convenience cross-compiling usage.
It provides much more features for building binary:
1. Cross-Compiling for many platforms and architectures.
2. Configuration file support for compiling.
3. Build-In Variables.
`
cBuildAd = `
PLATFORMS
darwin amd64,arm64
freebsd 386,amd64,arm
linux 386,amd64,arm,arm64,ppc64,ppc64le,mips,mipsle,mips64,mips64le
netbsd 386,amd64,arm
openbsd 386,amd64,arm
windows 386,amd64
`
// https://golang.google.cn/doc/install/source
cBuildPlatforms = `
darwin amd64
darwin arm64
ios amd64
ios arm64
freebsd 386
freebsd amd64
freebsd arm
linux 386
linux amd64
linux arm
linux arm64
linux ppc64
linux ppc64le
linux mips
linux mipsle
linux mips64
linux mips64le
netbsd 386
netbsd amd64
netbsd arm
openbsd 386
openbsd amd64
openbsd arm
windows 386
windows amd64
android arm
dragonfly amd64
plan9 386
plan9 amd64
solaris amd64
`
)
func init() {
gtag.Sets(g.MapStrStr{
`cBuildBrief`: cBuildBrief,
`cBuildDc`: cBuildDc,
`cBuildEg`: cBuildEg,
`cBuildAd`: cBuildAd,
})
}
type cBuildInput struct {
g.Meta `name:"build" config:"gfcli.build"`
File string `name:"FILE" arg:"true" brief:"building file path"`
Name string `short:"n" name:"name" brief:"output binary name"`
Version string `short:"v" name:"version" brief:"output binary version"`
Arch string `short:"a" name:"arch" brief:"output binary architecture, multiple arch separated with ','"`
System string `short:"s" name:"system" brief:"output binary system, multiple os separated with ','"`
Output string `short:"o" name:"output" brief:"output binary path, used when building single binary file"`
Path string `short:"p" name:"path" brief:"output binary directory path, default is './temp'" d:"./temp"`
Extra string `short:"e" name:"extra" brief:"extra custom \"go build\" options"`
Mod string `short:"m" name:"mod" brief:"like \"-mod\" option of \"go build\", use \"-m none\" to disable go module"`
Cgo bool `short:"c" name:"cgo" brief:"enable or disable cgo feature, it's disabled in default" orphan:"true"`
VarMap g.Map `short:"r" name:"varMap" brief:"custom built embedded variable into binary"`
PackSrc string `short:"ps" name:"packSrc" brief:"pack one or more folders into one go file before building"`
PackDst string `short:"pd" name:"packDst" brief:"temporary go file path for pack, this go file will be automatically removed after built" d:"internal/packed/build_pack_data.go"`
ExitWhenError bool `short:"ew" name:"exitWhenError" brief:"exit building when any error occurs, default is false" orphan:"true"`
}
type cBuildOutput struct{}
func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, err error) {
mlog.SetHeaderPrint(true)
mlog.Debugf(`build input: %+v`, in)
// Necessary check.
if gproc.SearchBinary("go") == "" {
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
}
var (
parser = gcmd.ParserFromCtx(ctx)
file = parser.GetArg(2).String()
)
if len(file) < 1 {
// Check and use the main.go file.
if gfile.Exists("main.go") {
file = "main.go"
} else {
mlog.Fatal("build file path cannot be empty")
}
}
if in.Name == "" {
in.Name = gfile.Name(file)
}
if len(in.Name) < 1 || in.Name == "*" {
mlog.Fatal("name cannot be empty")
}
if in.Mod != "" && in.Mod != "none" {
mlog.Debugf(`mod is %s`, in.Mod)
if in.Extra == "" {
in.Extra = fmt.Sprintf(`-mod=%s`, in.Mod)
} else {
in.Extra = fmt.Sprintf(`-mod=%s %s`, in.Mod, in.Extra)
}
}
if in.Extra != "" {
in.Extra += " "
}
var (
customSystems = gstr.SplitAndTrim(in.System, ",")
customArches = gstr.SplitAndTrim(in.Arch, ",")
)
if len(in.Version) > 0 {
in.Path += "/" + in.Version
}
// System and arch checks.
var (
spaceRegex = regexp.MustCompile(`\s+`)
platformMap = make(map[string]map[string]bool)
)
for _, line := range strings.Split(strings.TrimSpace(cBuildPlatforms), "\n") {
line = gstr.Trim(line)
line = spaceRegex.ReplaceAllString(line, " ")
var (
array = strings.Split(line, " ")
system = strings.TrimSpace(array[0])
arch = strings.TrimSpace(array[1])
)
if platformMap[system] == nil {
platformMap[system] = make(map[string]bool)
}
platformMap[system][arch] = true
}
// Auto packing.
if in.PackSrc != "" {
if in.PackDst == "" {
mlog.Fatal(`parameter "packDst" should not be empty when "packSrc" is used`)
}
if gfile.Exists(in.PackDst) && !gfile.IsFile(in.PackDst) {
mlog.Fatalf(`parameter "packDst" path "%s" should be type of file not directory`, in.PackDst)
}
if !gfile.Exists(in.PackDst) {
// Remove the go file that is automatically packed resource.
defer func() {
_ = gfile.Remove(in.PackDst)
mlog.Printf(`remove the automatically generated resource go file: %s`, in.PackDst)
}()
}
// remove black space in separator.
in.PackSrc, _ = gregex.ReplaceString(`,\s+`, `,`, in.PackSrc)
packCmd := fmt.Sprintf(`gf pack %s %s --keepPath=true`, in.PackSrc, in.PackDst)
mlog.Print(packCmd)
gproc.MustShellRun(ctx, packCmd)
}
// Injected information by building flags.
ldFlags := fmt.Sprintf(
`-X 'github.com/gogf/gf/v2/os/gbuild.builtInVarStr=%v'`,
c.getBuildInVarStr(ctx, in),
)
// start building
mlog.Print("start building...")
if in.Cgo {
genv.MustSet("CGO_ENABLED", "1")
} else {
genv.MustSet("CGO_ENABLED", "0")
}
var (
cmd = ""
ext = ""
)
for system, item := range platformMap {
cmd = ""
ext = ""
if len(customSystems) > 0 && customSystems[0] != "all" && !gstr.InArray(customSystems, system) {
continue
}
for arch, _ := range item {
if len(customArches) > 0 && customArches[0] != "all" && !gstr.InArray(customArches, arch) {
continue
}
if len(customSystems) == 0 && len(customArches) == 0 {
if runtime.GOOS == "windows" {
ext = ".exe"
}
// Single binary building, output the binary to current working folder.
output := ""
if len(in.Output) > 0 {
output = "-o " + in.Output + ext
} else {
output = "-o " + in.Name + ext
}
cmd = fmt.Sprintf(`go build %s -ldflags "%s" %s %s`, output, ldFlags, in.Extra, file)
} else {
// Cross-building, output the compiled binary to specified path.
if system == "windows" {
ext = ".exe"
}
genv.MustSet("GOOS", system)
genv.MustSet("GOARCH", arch)
cmd = fmt.Sprintf(
`go build -o %s/%s/%s%s -ldflags "%s" %s%s`,
in.Path, system+"_"+arch, in.Name, ext, ldFlags, in.Extra, file,
)
}
mlog.Debug(cmd)
// It's not necessary printing the complete command string.
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
mlog.Print(cmdShow)
if result, err := gproc.ShellExec(ctx, cmd); err != nil {
mlog.Printf(
"failed to build, os:%s, arch:%s, error:\n%s\n\n%s\n",
system, arch, gstr.Trim(result),
`you may use command option "--debug" to enable debug info and check the details`,
)
if in.ExitWhenError {
os.Exit(1)
}
} else {
mlog.Debug(gstr.Trim(result))
}
// single binary building.
if len(customSystems) == 0 && len(customArches) == 0 {
goto buildDone
}
}
}
buildDone:
mlog.Print("done!")
return
}
// getBuildInVarMapJson retrieves and returns the custom build-in variables in configuration
// file as json.
func (c cBuild) getBuildInVarStr(ctx context.Context, in cBuildInput) string {
buildInVarMap := in.VarMap
if buildInVarMap == nil {
buildInVarMap = make(g.Map)
}
buildInVarMap["builtGit"] = c.getGitCommit(ctx)
buildInVarMap["builtTime"] = gtime.Now().String()
b, err := json.Marshal(buildInVarMap)
if err != nil {
mlog.Fatal(err)
}
return gbase64.EncodeToString(b)
}
// getGitCommit retrieves and returns the latest git commit hash string if present.
func (c cBuild) getGitCommit(ctx context.Context) string {
if gproc.SearchBinary("git") == "" {
return ""
}
var (
cmd = `git log -1 --format="%cd %H" --date=format:"%Y-%m-%d %H:%M:%S"`
s, _ = gproc.ShellExec(ctx, cmd)
)
mlog.Debug(cmd)
if s != "" {
if !gstr.Contains(s, "fatal") {
return gstr.Trim(s)
}
}
return ""
}

View File

@ -0,0 +1,163 @@
package cmd
import (
"context"
"fmt"
"runtime"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Docker = cDocker{}
)
type cDocker struct {
g.Meta `name:"docker" usage:"{cDockerUsage}" brief:"{cDockerBrief}" eg:"{cDockerEg}" dc:"{cDockerDc}"`
}
const (
cDockerUsage = `gf docker [MAIN] [OPTION]`
cDockerBrief = `build docker image for current GoFrame project`
cDockerEg = `
gf docker
gf docker -t hub.docker.com/john/image:tag
gf docker -p -t hub.docker.com/john/image:tag
gf docker main.go
gf docker main.go -t hub.docker.com/john/image:tag
gf docker main.go -t hub.docker.com/john/image:tag
gf docker main.go -p -t hub.docker.com/john/image:tag
`
cDockerDc = `
The "docker" command builds the GF project to a docker images.
It runs "gf build" firstly to compile the project to binary file.
It then runs "docker build" command automatically to generate the docker image.
You should have docker installed, and there must be a Dockerfile in the root of the project.
`
cDockerMainBrief = `main file path for "gf build", it's "main.go" in default. empty string for no binary build`
cDockerBuildBrief = `binary build options before docker image build, it's "-a amd64 -s linux" in default`
cDockerFileBrief = `file path of the Dockerfile. it's "manifest/docker/Dockerfile" in default`
cDockerShellBrief = `path of the shell file which is executed before docker build`
cDockerPushBrief = `auto push the docker image to docker registry if "-t" option passed`
cDockerTagNameBrief = `tag name for this docker, pattern like "image:tag". this option is required with TagPrefixes`
cDockerTagPrefixesBrief = `tag prefixes for this docker, which are used for docker push. this option is required with TagName`
cDockerExtraBrief = `extra build options passed to "docker image"`
)
func init() {
gtag.Sets(g.MapStrStr{
`cDockerUsage`: cDockerUsage,
`cDockerBrief`: cDockerBrief,
`cDockerEg`: cDockerEg,
`cDockerDc`: cDockerDc,
`cDockerMainBrief`: cDockerMainBrief,
`cDockerFileBrief`: cDockerFileBrief,
`cDockerShellBrief`: cDockerShellBrief,
`cDockerBuildBrief`: cDockerBuildBrief,
`cDockerPushBrief`: cDockerPushBrief,
`cDockerTagNameBrief`: cDockerTagNameBrief,
`cDockerTagPrefixesBrief`: cDockerTagPrefixesBrief,
`cDockerExtraBrief`: cDockerExtraBrief,
})
}
type cDockerInput struct {
g.Meta `name:"docker" config:"gfcli.docker"`
Main string `name:"MAIN" arg:"true" brief:"{cDockerMainBrief}" d:"main.go"`
File string `name:"file" short:"f" brief:"{cDockerFileBrief}" d:"manifest/docker/Dockerfile"`
Shell string `name:"shell" short:"s" brief:"{cDockerShellBrief}" d:"manifest/docker/docker.sh"`
Build string `name:"build" short:"b" brief:"{cDockerBuildBrief}" d:"-a amd64 -s linux"`
TagName string `name:"tagName" short:"tn" brief:"{cDockerTagNameBrief}" v:"required-with:TagPrefixes"`
TagPrefixes []string `name:"tagPrefixes" short:"tp" brief:"{cDockerTagPrefixesBrief}" v:"required-with:TagName"`
Push bool `name:"push" short:"p" brief:"{cDockerPushBrief}" orphan:"true"`
Extra string `name:"extra" short:"e" brief:"{cDockerExtraBrief}"`
}
type cDockerOutput struct{}
func (c cDocker) Index(ctx context.Context, in cDockerInput) (out *cDockerOutput, err error) {
// Necessary check.
if gproc.SearchBinary("docker") == "" {
mlog.Fatalf(`command "docker" not found in your environment, please install docker first to proceed this command`)
}
// Binary build.
in.Build += " --exit"
if in.Main != "" {
if err = gproc.ShellRun(ctx, fmt.Sprintf(`gf build %s %s`, in.Main, in.Build)); err != nil {
return
}
}
// Shell executing.
if in.Shell != "" && gfile.Exists(in.Shell) {
if err = c.exeDockerShell(ctx, in.Shell); err != nil {
return
}
}
// Docker build.
var (
dockerBuildOptions string
dockerTags []string
dockerTagBase string
)
if len(in.TagPrefixes) > 0 {
for _, tagPrefix := range in.TagPrefixes {
tagPrefix = gstr.TrimRight(tagPrefix, "/")
dockerTags = append(dockerTags, fmt.Sprintf(`%s/%s`, tagPrefix, in.TagName))
}
}
if len(dockerTags) == 0 {
dockerTags = []string{""}
}
for i, dockerTag := range dockerTags {
if i > 0 {
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker tag %s %s`, dockerTagBase, dockerTag))
if err != nil {
return
}
continue
}
dockerTagBase = dockerTag
dockerBuildOptions = ""
if dockerTag != "" {
dockerBuildOptions = fmt.Sprintf(`-t %s`, dockerTag)
}
if in.Extra != "" {
dockerBuildOptions = fmt.Sprintf(`%s %s`, dockerBuildOptions, in.Extra)
}
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker build -f %s . %s`, in.File, dockerBuildOptions))
if err != nil {
return
}
}
// Docker push.
if !in.Push {
return
}
for _, dockerTag := range dockerTags {
if dockerTag == "" {
continue
}
err = gproc.ShellRun(ctx, fmt.Sprintf(`docker push %s`, dockerTag))
if err != nil {
return
}
}
return
}
func (c cDocker) exeDockerShell(ctx context.Context, shellFilePath string) error {
if gfile.ExtName(shellFilePath) == "sh" && runtime.GOOS == "windows" {
mlog.Debugf(`ignore shell file "%s", as it cannot be run on windows system`, shellFilePath)
return nil
}
return gproc.ShellRun(ctx, gfile.GetContents(shellFilePath))
}

View File

@ -0,0 +1,63 @@
package cmd
import (
"bytes"
"context"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/olekukonko/tablewriter"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Env = cEnv{}
)
type cEnv struct {
g.Meta `name:"env" brief:"show current Golang environment variables"`
}
type cEnvInput struct {
g.Meta `name:"env"`
}
type cEnvOutput struct{}
func (c cEnv) Index(ctx context.Context, in cEnvInput) (out *cEnvOutput, err error) {
result, err := gproc.ShellExec(ctx, "go env")
if err != nil {
mlog.Fatal(err)
}
if result == "" {
mlog.Fatal(`retrieving Golang environment variables failed, did you install Golang?`)
}
var (
lines = gstr.Split(result, "\n")
buffer = bytes.NewBuffer(nil)
)
array := make([][]string, 0)
for _, line := range lines {
line = gstr.Trim(line)
if line == "" {
continue
}
if gstr.Pos(line, "set ") == 0 {
line = line[4:]
}
match, _ := gregex.MatchString(`(.+?)=(.*)`, line)
if len(match) < 3 {
mlog.Fatalf(`invalid Golang environment variable: "%s"`, line)
}
array = append(array, []string{gstr.Trim(match[1]), gstr.Trim(match[2])})
}
tw := tablewriter.NewWriter(buffer)
tw.SetColumnAlignment([]int{tablewriter.ALIGN_LEFT, tablewriter.ALIGN_LEFT})
tw.AppendBulk(array)
tw.Render()
mlog.Print(buffer.String())
return
}

View File

@ -0,0 +1,99 @@
package cmd
import (
"context"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Fix = cFix{}
)
type cFix struct {
g.Meta `name:"fix" brief:"auto fixing codes after upgrading to new GoFrame version" usage:"gf fix" `
}
type cFixInput struct {
g.Meta `name:"fix"`
}
type cFixOutput struct{}
type cFixItem struct {
Version string
Func func(version string) error
}
func (c cFix) Index(ctx context.Context, in cFixInput) (out *cFixOutput, err error) {
mlog.Print(`start auto fixing...`)
defer mlog.Print(`done!`)
err = c.doFix()
return
}
func (c cFix) doFix() (err error) {
version, err := c.getVersion()
if err != nil {
mlog.Fatal(err)
}
if version == "" {
mlog.Print(`no GoFrame usage found, exit fixing`)
return
}
mlog.Debugf(`current GoFrame version found "%s"`, version)
var items = []cFixItem{
{Version: "v2.3", Func: c.doFixV23},
}
for _, item := range items {
if gstr.CompareVersionGo(version, item.Version) < 0 {
mlog.Debugf(
`current GoFrame version "%s" is lesser than "%s", nothing to do`,
version, item.Version,
)
continue
}
if err = item.Func(version); err != nil {
return
}
}
return
}
// doFixV23 fixes code when upgrading to GoFrame v2.3.
func (c cFix) doFixV23(version string) error {
replaceFunc := func(path, content string) string {
content = gstr.Replace(content, "*gdb.TX", "gdb.TX")
return content
}
return gfile.ReplaceDirFunc(replaceFunc, ".", "*.go", true)
}
func (c cFix) getVersion() (string, error) {
var (
err error
path = "go.mod"
version string
)
if !gfile.Exists(path) {
return "", gerror.Newf(`"%s" not found in current working directory`, path)
}
err = gfile.ReadLines(path, func(line string) error {
array := gstr.SplitAndTrim(line, " ")
if len(array) > 0 {
if array[0] == gfPackage {
version = array[1]
}
}
return nil
})
if err != nil {
mlog.Fatal(err)
}
return version, nil
}

View File

@ -0,0 +1,34 @@
package cmd
import (
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gtag"
)
var (
Gen = cGen{}
)
type cGen struct {
g.Meta `name:"hggen" brief:"{cGenBrief}" dc:"{cGenDc}"`
cGenDao
cGenPb
cGenPbEntity
cGenService
}
const (
cGenBrief = `automatically generate go files for dao/do/entity/pb/pbentity`
cGenDc = `
The "hggen" command is designed for multiple generating purposes.
It's currently supporting generating go files for ORM models, protobuf and protobuf entity files.
Please use "gf hggen dao -h" for specified type help.
`
)
func init() {
gtag.Sets(g.MapStrStr{
`cGenBrief`: cGenBrief,
`cGenDc`: cGenDc,
})
}

View File

@ -0,0 +1,15 @@
package cmd
import (
//_ "github.com/gogf/gf/contrib/drivers/mssql/v2"
//_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
//_ "github.com/gogf/gf/contrib/drivers/oracle/v2"
//_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
//_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
"hotgo/internal/library/hggen/internal/cmd/gendao"
)
type (
cGenDao = gendao.CGenDao
)

View File

@ -0,0 +1,79 @@
package cmd
import (
"context"
"fmt"
"github.com/gogf/gf/v2/container/gset"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/genv"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
type (
cGenPb struct{}
cGenPbInput struct {
g.Meta `name:"pb" brief:"parse proto files and generate protobuf go files"`
}
cGenPbOutput struct{}
)
func (c cGenPb) Pb(ctx context.Context, in cGenPbInput) (out *cGenPbOutput, err error) {
// Necessary check.
if gproc.SearchBinary("protoc") == "" {
mlog.Fatalf(`command "protoc" not found in your environment, please install protoc first to proceed this command`)
}
// protocol fold checks.
protoFolder := "protocol"
if !gfile.Exists(protoFolder) {
mlog.Fatalf(`proto files folder "%s" does not exist`, protoFolder)
}
// folder scanning.
files, err := gfile.ScanDirFile(protoFolder, "*.proto", true)
if err != nil {
mlog.Fatal(err)
}
if len(files) == 0 {
mlog.Fatalf(`no proto files found in folder "%s"`, protoFolder)
}
dirSet := gset.NewStrSet()
for _, file := range files {
dirSet.Add(gfile.Dir(file))
}
var (
servicePath = gfile.RealPath(".")
goPathSrc = gfile.RealPath(gfile.Join(genv.Get("GOPATH").String(), "src"))
)
dirSet.Iterator(func(protoDirPath string) bool {
parsingCommand := fmt.Sprintf(
"protoc --gofast_out=plugins=grpc:. %s/*.proto -I%s",
protoDirPath,
servicePath,
)
if goPathSrc != "" {
parsingCommand += " -I" + goPathSrc
}
mlog.Print(parsingCommand)
if output, err := gproc.ShellExec(ctx, parsingCommand); err != nil {
mlog.Print(output)
mlog.Fatal(err)
}
return true
})
// Custom replacement.
//pbFolder := "protobuf"
//_, _ = gfile.ScanDirFileFunc(pbFolder, "*.go", true, func(path string) string {
// content := gfile.GetContents(path)
// content = gstr.ReplaceByArray(content, g.SliceStr{
// `gtime "gtime"`, `gtime "github.com/gogf/gf/v2/os/gtime"`,
// })
// _ = gfile.PutContents(path, content)
// utils.GoFmt(path)
// return path
//})
mlog.Print("done!")
return
}

View File

@ -0,0 +1,411 @@
package cmd
import (
"bytes"
"context"
"fmt"
"strings"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"github.com/gogf/gf/v2/util/gtag"
"github.com/olekukonko/tablewriter"
"hotgo/internal/library/hggen/internal/consts"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
type (
cGenPbEntity struct{}
cGenPbEntityInput struct {
g.Meta `name:"pbentity" config:"{cGenPbEntityConfig}" brief:"{cGenPbEntityBrief}" eg:"{cGenPbEntityEg}" ad:"{cGenPbEntityAd}"`
Path string `name:"path" short:"p" brief:"{cGenPbEntityBriefPath}"`
Package string `name:"package" short:"k" brief:"{cGenPbEntityBriefPackage}"`
Link string `name:"link" short:"l" brief:"{cGenPbEntityBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{cGenPbEntityBriefTables}"`
Prefix string `name:"prefix" short:"f" brief:"{cGenPbEntityBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{cGenPbEntityBriefRemovePrefix}"`
NameCase string `name:"nameCase" short:"n" brief:"{cGenPbEntityBriefNameCase}" d:"Camel"`
JsonCase string `name:"jsonCase" short:"j" brief:"{cGenPbEntityBriefJsonCase}" d:"CamelLower"`
Option string `name:"option" short:"o" brief:"{cGenPbEntityBriefOption}"`
}
cGenPbEntityOutput struct{}
cGenPbEntityInternalInput struct {
cGenPbEntityInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
}
)
const (
cGenPbEntityConfig = `gfcli.hggen.pbentity`
cGenPbEntityBrief = `generate entity message files in protobuf3 format`
cGenPbEntityEg = `
gf hggen pbentity
gf hggen pbentity -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
gf hggen pbentity -p ./protocol/demos/entity -t user,user_detail,user_login
gf hggen pbentity -r user_
`
cGenPbEntityAd = `
CONFIGURATION SUPPORT
Options are also supported by configuration file.
It's suggested using configuration file instead of command line arguments making producing.
The configuration node name is "gf.hggen.pbentity", which also supports multiple databases, for example(config.yaml):
gfcli:
hggen:
- pbentity:
link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
path: "protocol/demos/entity"
tables: "order,products"
package: "demos"
- pbentity:
link: "mysql:root:12345678@tcp(127.0.0.1:3306)/primary"
path: "protocol/demos/entity"
prefix: "primary_"
tables: "user, userDetail"
package: "demos"
option: |
option go_package = "protobuf/demos";
option java_package = "protobuf/demos";
option php_namespace = "protobuf/demos";
`
cGenPbEntityBriefPath = `directory path for generated files`
cGenPbEntityBriefPackage = `package name for all entity proto files`
cGenPbEntityBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
cGenPbEntityBriefTables = `generate models only for given tables, multiple table names separated with ','`
cGenPbEntityBriefPrefix = `add specified prefix for all entity names and entity proto files`
cGenPbEntityBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
cGenPbEntityBriefOption = `extra protobuf options`
cGenPbEntityBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
`
cGenPbEntityBriefNameCase = `
case for message attribute names, default is "Camel":
| Case | Example |
|---------------- |--------------------|
| Camel | AnyKindOfString |
| CamelLower | anyKindOfString | default
| Snake | any_kind_of_string |
| SnakeScreaming | ANY_KIND_OF_STRING |
| SnakeFirstUpper | rgb_code_md5 |
| Kebab | any-kind-of-string |
| KebabScreaming | ANY-KIND-OF-STRING |
`
cGenPbEntityBriefJsonCase = `
case for message json tag, cases are the same as "nameCase", default "CamelLower".
set it to "none" to ignore json tag generating.
`
)
func init() {
gtag.Sets(g.MapStrStr{
`cGenPbEntityConfig`: cGenPbEntityConfig,
`cGenPbEntityBrief`: cGenPbEntityBrief,
`cGenPbEntityEg`: cGenPbEntityEg,
`cGenPbEntityAd`: cGenPbEntityAd,
`cGenPbEntityBriefPath`: cGenPbEntityBriefPath,
`cGenPbEntityBriefPackage`: cGenPbEntityBriefPackage,
`cGenPbEntityBriefLink`: cGenPbEntityBriefLink,
`cGenPbEntityBriefTables`: cGenPbEntityBriefTables,
`cGenPbEntityBriefPrefix`: cGenPbEntityBriefPrefix,
`cGenPbEntityBriefRemovePrefix`: cGenPbEntityBriefRemovePrefix,
`cGenPbEntityBriefGroup`: cGenPbEntityBriefGroup,
`cGenPbEntityBriefNameCase`: cGenPbEntityBriefNameCase,
`cGenPbEntityBriefJsonCase`: cGenPbEntityBriefJsonCase,
`cGenPbEntityBriefOption`: cGenPbEntityBriefOption,
})
}
func (c cGenPbEntity) PbEntity(ctx context.Context, in cGenPbEntityInput) (out *cGenPbEntityOutput, err error) {
var (
config = g.Cfg()
)
if config.Available(ctx) {
v := config.MustGet(ctx, cGenPbEntityConfig)
if v.IsSlice() {
for i := 0; i < len(v.Interfaces()); i++ {
doGenPbEntityForArray(ctx, i, in)
}
} else {
doGenPbEntityForArray(ctx, -1, in)
}
} else {
doGenPbEntityForArray(ctx, -1, in)
}
mlog.Print("done!")
return
}
func doGenPbEntityForArray(ctx context.Context, index int, in cGenPbEntityInput) {
var (
err error
db gdb.DB
)
if index >= 0 {
err = g.Cfg().MustGet(
ctx,
fmt.Sprintf(`%s.%d`, cGenPbEntityConfig, index),
).Scan(&in)
if err != nil {
mlog.Fatalf(`invalid configuration of "%s": %+v`, cGenPbEntityConfig, err)
}
}
if in.Package == "" {
mlog.Fatal("package name should not be empty")
}
removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",")
// It uses user passed database configuration.
if in.Link != "" {
var (
tempGroup = gtime.TimestampNanoStr()
match, _ = gregex.MatchString(`([a-z]+):(.+)`, in.Link)
)
if len(match) == 3 {
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
Type: gstr.Trim(match[1]),
Link: gstr.Trim(match[2]),
})
db, _ = gdb.Instance(tempGroup)
}
} else {
db = g.DB()
}
if db == nil {
mlog.Fatal("database initialization failed")
}
tableNames := ([]string)(nil)
if in.Tables != "" {
tableNames = gstr.SplitAndTrim(in.Tables, ",")
} else {
tableNames, err = db.Tables(context.TODO())
if err != nil {
mlog.Fatalf("fetching tables failed: \n %v", err)
}
}
for _, tableName := range tableNames {
newTableName := tableName
for _, v := range removePrefixArray {
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
}
generatePbEntityContentFile(ctx, db, cGenPbEntityInternalInput{
cGenPbEntityInput: in,
TableName: tableName,
NewTableName: newTableName,
})
}
}
// generatePbEntityContentFile generates the protobuf files for given table.
func generatePbEntityContentFile(ctx context.Context, db gdb.DB, in cGenPbEntityInternalInput) {
fieldMap, err := db.TableFields(ctx, in.TableName)
if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", in.TableName, err)
}
// Change the `newTableName` if `Prefix` is given.
newTableName := "Entity_" + in.Prefix + in.NewTableName
var (
tableNameCamelCase = gstr.CaseCamel(newTableName)
tableNameSnakeCase = gstr.CaseSnake(newTableName)
entityMessageDefine = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in)
fileName = gstr.Trim(tableNameSnakeCase, "-_.")
path = gfile.Join(in.Path, fileName+".proto")
)
entityContent := gstr.ReplaceByMap(getTplPbEntityContent(""), g.MapStrStr{
"{PackageName}": in.Package,
"{OptionContent}": in.Option,
"{EntityMessage}": entityMessageDefine,
})
if err := gfile.PutContents(path, strings.TrimSpace(entityContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
mlog.Print("generated:", path)
}
}
// generateEntityMessageDefinition generates and returns the message definition for specified table.
func generateEntityMessageDefinition(entityName string, fieldMap map[string]*gdb.TableField, in cGenPbEntityInternalInput) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForPbEntity(fieldMap)
)
for index, name := range names {
array[index] = generateMessageFieldForPbEntity(index+1, fieldMap[name], in)
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
stContent := buffer.String()
// Let's do this hack of table writer for indent!
stContent = gstr.Replace(stContent, " #", "")
buffer.Reset()
buffer.WriteString(fmt.Sprintf("message %s {\n", entityName))
buffer.WriteString(stContent)
buffer.WriteString("}")
return buffer.String()
}
// generateMessageFieldForPbEntity generates and returns the message definition for specified field.
func generateMessageFieldForPbEntity(index int, field *gdb.TableField, in cGenPbEntityInternalInput) []string {
var (
typeName string
comment string
jsonTagStr string
)
t, _ := gregex.ReplaceString(`\(.+\)`, "", field.Type)
t = gstr.Split(gstr.Trim(t), " ")[0]
t = gstr.ToLower(t)
switch t {
case "binary", "varbinary", "blob", "tinyblob", "mediumblob", "longblob":
typeName = "bytes"
case "bit", "int", "tinyint", "small_int", "smallint", "medium_int", "mediumint", "serial":
if gstr.ContainsI(field.Type, "unsigned") {
typeName = "uint32"
} else {
typeName = "int32"
}
case "int8", "big_int", "bigint", "bigserial":
if gstr.ContainsI(field.Type, "unsigned") {
typeName = "uint64"
} else {
typeName = "int64"
}
case "real":
typeName = "float"
case "float", "double", "decimal", "smallmoney":
typeName = "double"
case "bool":
typeName = "bool"
case "datetime", "timestamp", "date", "time":
typeName = "int64"
default:
// Auto detecting type.
switch {
case strings.Contains(t, "int"):
typeName = "int"
case strings.Contains(t, "text") || strings.Contains(t, "char"):
typeName = "string"
case strings.Contains(t, "float") || strings.Contains(t, "double"):
typeName = "double"
case strings.Contains(t, "bool"):
typeName = "bool"
case strings.Contains(t, "binary") || strings.Contains(t, "blob"):
typeName = "bytes"
case strings.Contains(t, "date") || strings.Contains(t, "time"):
typeName = "int64"
default:
typeName = "string"
}
}
comment = gstr.ReplaceByArray(field.Comment, g.SliceStr{
"\n", " ",
"\r", " ",
})
comment = gstr.Trim(comment)
comment = gstr.Replace(comment, `\n`, " ")
comment, _ = gregex.ReplaceString(`\s{2,}`, ` `, comment)
if jsonTagName := formatCase(field.Name, in.JsonCase); jsonTagName != "" {
jsonTagStr = fmt.Sprintf(`[(gogoproto.jsontag) = "%s"]`, jsonTagName)
// beautiful indent.
if index < 10 {
// 3 spaces
jsonTagStr = " " + jsonTagStr
} else if index < 100 {
// 2 spaces
jsonTagStr = " " + jsonTagStr
} else {
// 1 spaces
jsonTagStr = " " + jsonTagStr
}
}
return []string{
" #" + typeName,
" #" + formatCase(field.Name, in.NameCase),
" #= " + gconv.String(index) + jsonTagStr + ";",
" #" + fmt.Sprintf(`// %s`, comment),
}
}
func getTplPbEntityContent(tplEntityPath string) string {
if tplEntityPath != "" {
return gfile.GetContents(tplEntityPath)
}
return consts.TemplatePbEntityMessageContent
}
// formatCase call gstr.Case* function to convert the s to specified case.
func formatCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("Snake"):
return gstr.CaseSnake(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
case "none":
return ""
}
return str
}
func sortFieldKeyForPbEntity(fieldMap map[string]*gdb.TableField) []string {
names := make(map[int]string)
for _, field := range fieldMap {
names[field.Index] = field.Name
}
var (
result = make([]string, len(names))
i = 0
j = 0
)
for {
if len(names) == 0 {
break
}
if val, ok := names[i]; ok {
result[j] = val
j++
delete(names, i)
}
i++
}
return result
}

View File

@ -0,0 +1,9 @@
package cmd
import (
"hotgo/internal/library/hggen/internal/cmd/genservice"
)
type (
cGenService = genservice.CGenService
)

View File

@ -0,0 +1,126 @@
package cmd
import (
"context"
"fmt"
"strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/util/gtag"
"hotgo/internal/library/hggen/internal/utility/allyes"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Init = cInit{}
)
type cInit struct {
g.Meta `name:"init" brief:"{cInitBrief}" eg:"{cInitEg}"`
}
const (
cInitRepoPrefix = `github.com/gogf/`
cInitMonoRepo = `template-mono`
cInitSingleRepo = `template-single`
cInitBrief = `create and initialize an empty GoFrame project`
cInitEg = `
gf init my-project
gf init my-mono-repo -m
`
cInitNameBrief = `
name for the project. It will create a folder with NAME in current directory.
The NAME will also be the module name for the project.
`
)
func init() {
gtag.Sets(g.MapStrStr{
`cInitBrief`: cInitBrief,
`cInitEg`: cInitEg,
`cInitNameBrief`: cInitNameBrief,
})
}
type cInitInput struct {
g.Meta `name:"init"`
Name string `name:"NAME" arg:"true" v:"required" brief:"{cInitNameBrief}"`
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
}
type cInitOutput struct{}
func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
if !gfile.IsEmpty(in.Name) && !allyes.Check() {
s := gcmd.Scanf(`the folder "%s" is not empty, files might be overwrote, continue? [y/n]: `, in.Name)
if strings.EqualFold(s, "n") {
return
}
}
mlog.Print("initializing...")
// Create project folder and files.
var (
templateRepoName string
)
if in.Mono {
templateRepoName = cInitMonoRepo
} else {
templateRepoName = cInitSingleRepo
}
err = gres.Export(templateRepoName, in.Name, gres.ExportOption{
RemovePrefix: templateRepoName,
})
if err != nil {
return
}
// Replace template name to project name.
err = gfile.ReplaceDir(
cInitRepoPrefix+templateRepoName,
gfile.Basename(gfile.RealPath(in.Name)),
in.Name,
"*",
true,
)
if err != nil {
return
}
// Update the GoFrame version.
if in.Update {
mlog.Print("update goframe...")
// go get -u github.com/gogf/gf/v2@latest
updateCommand := `go get -u github.com/gogf/gf/v2@latest`
if in.Name != "." {
updateCommand = fmt.Sprintf(`cd %s && %s`, in.Name, updateCommand)
}
if err = gproc.ShellRun(ctx, updateCommand); err != nil {
mlog.Fatal(err)
}
// go mod tidy
gomModTidyCommand := `go mod tidy`
if in.Name != "." {
gomModTidyCommand = fmt.Sprintf(`cd %s && %s`, in.Name, gomModTidyCommand)
}
if err = gproc.ShellRun(ctx, gomModTidyCommand); err != nil {
mlog.Fatal(err)
}
}
mlog.Print("initialization done! ")
if !in.Mono {
enjoyCommand := `gf run main.go`
if in.Name != "." {
enjoyCommand = fmt.Sprintf(`cd %s && %s`, in.Name, enjoyCommand)
}
mlog.Printf(`you can now run "%s" to start your journey, enjoy!`, enjoyCommand)
}
return
}

View File

@ -0,0 +1,28 @@
package cmd
import (
"context"
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/library/hggen/internal/service"
)
var (
Install = cInstall{}
)
type cInstall struct {
g.Meta `name:"install" brief:"install gf binary to system (might need root/admin permission)"`
}
type cInstallInput struct {
g.Meta `name:"install"`
}
type cInstallOutput struct{}
func (c cInstall) Index(ctx context.Context, in cInstallInput) (out *cInstallOutput, err error) {
err = service.Install.Run(ctx)
return
}

View File

@ -0,0 +1,98 @@
package cmd
import (
"context"
"strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gres"
"github.com/gogf/gf/v2/util/gtag"
"hotgo/internal/library/hggen/internal/utility/allyes"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Pack = cPack{}
)
type cPack struct {
g.Meta `name:"pack" usage:"{cPackUsage}" brief:"{cPackBrief}" eg:"{cPackEg}"`
}
const (
cPackUsage = `gf pack SRC DST`
cPackBrief = `packing any file/directory to a resource file, or a go file`
cPackEg = `
gf pack public data.bin
gf pack public,template data.bin
gf pack public,template packed/data.go
gf pack public,template,config packed/data.go
gf pack public,template,config packed/data.go -n=packed -p=/var/www/my-app
gf pack /var/www/public packed/data.go -n=packed
`
cPackSrcBrief = `source path for packing, which can be multiple source paths.`
cPackDstBrief = `
destination file path for packed file. if extension of the filename is ".go" and "-n" option is given,
it enables packing SRC to go file, or else it packs SRC into a binary file.
`
cPackNameBrief = `package name for output go file, it's set as its directory name if no name passed`
cPackPrefixBrief = `prefix for each file packed into the resource file`
cPackKeepPathBrief = `keep the source path from system to resource file, usually for relative path`
)
func init() {
gtag.Sets(g.MapStrStr{
`cPackUsage`: cPackUsage,
`cPackBrief`: cPackBrief,
`cPackEg`: cPackEg,
`cPackSrcBrief`: cPackSrcBrief,
`cPackDstBrief`: cPackDstBrief,
`cPackNameBrief`: cPackNameBrief,
`cPackPrefixBrief`: cPackPrefixBrief,
`cPackKeepPathBrief`: cPackKeepPathBrief,
})
}
type cPackInput struct {
g.Meta `name:"pack"`
Src string `name:"SRC" arg:"true" v:"required" brief:"{cPackSrcBrief}"`
Dst string `name:"DST" arg:"true" v:"required" brief:"{cPackDstBrief}"`
Name string `name:"name" short:"n" brief:"{cPackNameBrief}"`
Prefix string `name:"prefix" short:"p" brief:"{cPackPrefixBrief}"`
KeepPath bool `name:"keepPath" short:"k" brief:"{cPackKeepPathBrief}" orphan:"true"`
}
type cPackOutput struct{}
func (c cPack) Index(ctx context.Context, in cPackInput) (out *cPackOutput, err error) {
if gfile.Exists(in.Dst) && gfile.IsDir(in.Dst) {
mlog.Fatalf("DST path '%s' cannot be a directory", in.Dst)
}
if !gfile.IsEmpty(in.Dst) && !allyes.Check() {
s := gcmd.Scanf("path '%s' is not empty, files might be overwrote, continue? [y/n]: ", in.Dst)
if strings.EqualFold(s, "n") {
return
}
}
if in.Name == "" && gfile.ExtName(in.Dst) == "go" {
in.Name = gfile.Basename(gfile.Dir(in.Dst))
}
var option = gres.Option{
Prefix: in.Prefix,
KeepPath: in.KeepPath,
}
if in.Name != "" {
if err = gres.PackToGoFileWithOption(in.Src, in.Dst, in.Name, option); err != nil {
mlog.Fatalf("pack failed: %v", err)
}
} else {
if err = gres.PackToFileWithOption(in.Src, in.Dst, option); err != nil {
mlog.Fatalf("pack failed: %v", err)
}
}
mlog.Print("done!")
return
}

View File

@ -0,0 +1,166 @@
package cmd
import (
"context"
"fmt"
"runtime"
"github.com/gogf/gf/v2/container/gtype"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gfsnotify"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/os/gtimer"
"github.com/gogf/gf/v2/util/gtag"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Run = cRun{}
)
type cRun struct {
g.Meta `name:"run" usage:"{cRunUsage}" brief:"{cRunBrief}" eg:"{cRunEg}" dc:"{cRunDc}"`
}
type cRunApp struct {
File string // Go run file name.
Path string // Directory storing built binary.
Options string // Extra "go run" options.
Args string // Custom arguments.
}
const (
cRunUsage = `gf run FILE [OPTION]`
cRunBrief = `running go codes with hot-compiled-like feature`
cRunEg = `
gf run main.go
gf run main.go --args "server -p 8080"
gf run main.go -mod=vendor
`
cRunDc = `
The "run" command is used for running go codes with hot-compiled-like feature,
which compiles and runs the go codes asynchronously when codes change.
`
cRunFileBrief = `building file path.`
cRunPathBrief = `output directory path for built binary file. it's "manifest/output" in default`
cRunExtraBrief = `the same options as "go run"/"go build" except some options as follows defined`
cRunArgsBrief = `custom arguments for your process`
)
var (
process *gproc.Process
)
func init() {
gtag.Sets(g.MapStrStr{
`cRunUsage`: cRunUsage,
`cRunBrief`: cRunBrief,
`cRunEg`: cRunEg,
`cRunDc`: cRunDc,
`cRunFileBrief`: cRunFileBrief,
`cRunPathBrief`: cRunPathBrief,
`cRunExtraBrief`: cRunExtraBrief,
`cRunArgsBrief`: cRunArgsBrief,
})
}
type (
cRunInput struct {
g.Meta `name:"run"`
File string `name:"FILE" arg:"true" brief:"{cRunFileBrief}" v:"required"`
Path string `name:"path" short:"p" brief:"{cRunPathBrief}" d:"./"`
Extra string `name:"extra" short:"e" brief:"{cRunExtraBrief}"`
Args string `name:"args" short:"a" brief:"{cRunArgsBrief}"`
}
cRunOutput struct{}
)
func (c cRun) Index(ctx context.Context, in cRunInput) (out *cRunOutput, err error) {
// Necessary check.
if gproc.SearchBinary("go") == "" {
mlog.Fatalf(`command "go" not found in your environment, please install golang first to proceed this command`)
}
app := &cRunApp{
File: in.File,
Path: in.Path,
Options: in.Extra,
Args: in.Args,
}
dirty := gtype.NewBool()
_, err = gfsnotify.Add(gfile.RealPath("."), func(event *gfsnotify.Event) {
if gfile.ExtName(event.Path) != "go" {
return
}
// Variable `dirty` is used for running the changes only one in one second.
if !dirty.Cas(false, true) {
return
}
// With some delay in case of multiple code changes in very short interval.
gtimer.SetTimeout(ctx, 1500*gtime.MS, func(ctx context.Context) {
defer dirty.Set(false)
mlog.Printf(`go file changes: %s`, event.String())
app.Run(ctx)
})
})
if err != nil {
mlog.Fatal(err)
}
go app.Run(ctx)
select {}
}
func (app *cRunApp) Run(ctx context.Context) {
// Rebuild and run the codes.
renamePath := ""
mlog.Printf("build: %s", app.File)
outputPath := gfile.Join(app.Path, gfile.Name(app.File))
if runtime.GOOS == "windows" {
outputPath += ".exe"
if gfile.Exists(outputPath) {
renamePath = outputPath + "~"
if err := gfile.Rename(outputPath, renamePath); err != nil {
mlog.Print(err)
}
}
}
// In case of `pipe: too many open files` error.
// Build the app.
buildCommand := fmt.Sprintf(
`go build -o %s %s %s`,
outputPath,
app.Options,
app.File,
)
mlog.Print(buildCommand)
result, err := gproc.ShellExec(ctx, buildCommand)
if err != nil {
mlog.Printf("build error: \n%s%s", result, err.Error())
return
}
// Kill the old process if build successfully.
if process != nil {
if err := process.Kill(); err != nil {
mlog.Debugf("kill process error: %s", err.Error())
//return
}
}
// Run the binary file.
runCommand := fmt.Sprintf(`%s %s`, outputPath, app.Args)
mlog.Print(runCommand)
if runtime.GOOS == "windows" {
// Special handling for windows platform.
// DO NOT USE "cmd /c" command.
process = gproc.NewProcess(runCommand, nil)
} else {
process = gproc.NewProcessCmd(runCommand, nil)
}
if pid, err := process.Start(ctx); err != nil {
mlog.Printf("build running error: %s", err.Error())
} else {
mlog.Printf("build running pid: %d", pid)
}
}

View File

@ -0,0 +1,168 @@
package cmd
import (
"context"
"github.com/gogf/gf/v2/encoding/gjson"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
"github.com/gogf/gf/v2/util/gutil"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Tpl = cTpl{}
)
type cTpl struct {
g.Meta `name:"tpl" brief:"{cTplBrief}" dc:"{cTplDc}"`
}
const (
cTplBrief = `template parsing and building commands`
cTplDc = `
The "tpl" command is used for template parsing and building purpose.
It can parse either template file or folder with multiple types of values support,
like json/xml/yaml/toml/ini.
`
cTplParseBrief = `parse either template file or folder with multiple types of values`
cTplParseEg = `
gf tpl parse -p ./template -v values.json -r
gf tpl parse -p ./template -v values.json -n *.tpl -r
gf tpl parse -p ./template -v values.json -d '${,}}' -r
gf tpl parse -p ./template -v values.json -o ./template.parsed
`
cTplSupportValuesFilePattern = `*.json,*.xml,*.yaml,*.yml,*.toml,*.ini`
)
type (
cTplParseInput struct {
g.Meta `name:"parse" brief:"{cTplParseBrief}" eg:"{cTplParseEg}"`
Path string `name:"path" short:"p" brief:"template file or folder path" v:"required"`
Pattern string `name:"pattern" short:"n" brief:"template file pattern when path is a folder, default is:*" d:"*"`
Recursive bool `name:"recursive" short:"c" brief:"recursively parsing files if path is folder, default is:true" d:"true"`
Values string `name:"values" short:"v" brief:"template values file/folder, support file types like: json/xml/yaml/toml/ini" v:"required"`
Output string `name:"output" short:"o" brief:"output file/folder path"`
Delimiters string `name:"delimiters" short:"d" brief:"delimiters for template content parsing, default is:{{,}}" d:"{{,}}"`
Replace bool `name:"replace" short:"r" brief:"replace original files" orphan:"true"`
}
cTplParseOutput struct{}
)
func init() {
gtag.Sets(g.MapStrStr{
`cTplBrief`: cTplBrief,
`cTplDc`: cTplDc,
`cTplParseEg`: cTplParseEg,
`cTplParseBrief`: cTplParseBrief,
})
}
func (c *cTpl) Parse(ctx context.Context, in cTplParseInput) (out *cTplParseOutput, err error) {
if in.Output == "" && in.Replace == false {
return nil, gerror.New(`parameter output and replace should not be both empty`)
}
delimiters := gstr.SplitAndTrim(in.Delimiters, ",")
mlog.Debugf("delimiters input:%s, parsed:%#v", in.Delimiters, delimiters)
if len(delimiters) != 2 {
return nil, gerror.Newf(`invalid delimiters: %s`, in.Delimiters)
}
g.View().SetDelimiters(delimiters[0], delimiters[1])
valuesMap, err := c.loadValues(ctx, in.Values)
if err != nil {
return nil, err
}
if len(valuesMap) == 0 {
return nil, gerror.Newf(`empty values loaded from values file/folder "%s"`, in.Values)
}
err = c.parsePath(ctx, valuesMap, in)
if err == nil {
mlog.Print("done!")
}
return
}
func (c *cTpl) parsePath(ctx context.Context, values g.Map, in cTplParseInput) (err error) {
if !gfile.Exists(in.Path) {
return gerror.Newf(`path "%s" does not exist`, in.Path)
}
var (
path string
files []string
relativePath string
outputPath string
)
path = gfile.RealPath(in.Path)
if gfile.IsDir(path) {
files, err = gfile.ScanDirFile(path, in.Pattern, in.Recursive)
if err != nil {
return err
}
for _, file := range files {
relativePath = gstr.Replace(file, path, "")
if in.Output != "" {
outputPath = gfile.Join(in.Output, relativePath)
}
if err = c.parseFile(ctx, file, outputPath, values, in); err != nil {
return
}
}
return
}
if in.Output != "" {
outputPath = in.Output
}
err = c.parseFile(ctx, path, outputPath, values, in)
return
}
func (c *cTpl) parseFile(ctx context.Context, file string, output string, values g.Map, in cTplParseInput) (err error) {
output = gstr.ReplaceByMap(output, g.MapStrStr{
`\\`: `\`,
`//`: `/`,
})
content, err := g.View().Parse(ctx, file, values)
if err != nil {
return err
}
if output != "" {
mlog.Printf(`parse file "%s" to "%s"`, file, output)
return gfile.PutContents(output, content)
}
if in.Replace {
mlog.Printf(`parse and replace file "%s"`, file)
return gfile.PutContents(file, content)
}
return nil
}
func (c *cTpl) loadValues(ctx context.Context, valuesPath string) (data g.Map, err error) {
if !gfile.Exists(valuesPath) {
return nil, gerror.Newf(`values file/folder "%s" does not exist`, valuesPath)
}
var j *gjson.Json
if gfile.IsDir(valuesPath) {
var valueFiles []string
valueFiles, err = gfile.ScanDirFile(valuesPath, cTplSupportValuesFilePattern, true)
if err != nil {
return nil, err
}
data = make(g.Map)
for _, file := range valueFiles {
if j, err = gjson.Load(file); err != nil {
return nil, err
}
gutil.MapMerge(data, j.Map())
}
return
}
if j, err = gjson.Load(valuesPath); err != nil {
return nil, err
}
data = j.Map()
return
}

View File

@ -0,0 +1,121 @@
package cmd
import (
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gproc"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Up = cUp{}
)
type cUp struct {
g.Meta `name:"up" brief:"upgrade GoFrame version/tool to latest one in current project" eg:"{cUpEg}" `
}
const (
gfPackage = `github.com/gogf/gf/v2`
cUpEg = `
gf up
gf up -a
gf up -c
gf up -f -c
`
)
func init() {
gtag.Sets(g.MapStrStr{
`cUpEg`: cUpEg,
})
}
type cUpInput struct {
g.Meta `name:"up" config:"gfcli.up"`
All bool `name:"all" short:"a" brief:"upgrade both version and cli, auto fix codes" orphan:"true"`
Fix bool `name:"fix" short:"f" brief:"auto fix codes" orphan:"true"`
Cli bool `name:"cli" short:"c" brief:"also upgrade CLI tool (not supported yet)" orphan:"true"`
}
type cUpOutput struct{}
func (c cUp) Index(ctx context.Context, in cUpInput) (out *cUpOutput, err error) {
defer mlog.Print(`done!`)
if in.All {
in.Cli = true
in.Fix = true
}
if err = c.doUpgradeVersion(ctx); err != nil {
return nil, err
}
if in.Fix {
if err = c.doAutoFixing(ctx); err != nil {
return nil, err
}
}
//if in.Cli {
// if err = c.doUpgradeCLI(ctx); err != nil {
// return nil, err
// }
//}
return
}
func (c cUp) doUpgradeVersion(ctx context.Context) (err error) {
mlog.Print(`start upgrading version...`)
var (
dir = gfile.Pwd()
temp string
path = gfile.Join(dir, "go.mod")
)
for {
if gfile.Exists(path) {
var packages []string
err = gfile.ReadLines(path, func(line string) error {
line = gstr.Trim(line)
if gstr.HasPrefix(line, gfPackage) {
pkg := gstr.Explode(" ", line)[0]
packages = append(packages, pkg)
}
return nil
})
if err != nil {
return
}
for _, pkg := range packages {
mlog.Printf(`upgrading %s`, pkg)
command := fmt.Sprintf(`go get -u %s@latest`, pkg)
if err = gproc.ShellRun(ctx, command); err != nil {
return
}
}
return
}
temp = gfile.Dir(dir)
if temp == "" || temp == dir {
return
}
dir = temp
path = gfile.Join(dir, "go.mod")
}
}
func (c cUp) doUpgradeCLI(ctx context.Context) (err error) {
mlog.Print(`start upgrading cli...`)
return
}
func (c cUp) doAutoFixing(ctx context.Context) (err error) {
mlog.Print(`start auto fixing...`)
err = cFix{}.doFix()
return
}

View File

@ -0,0 +1,89 @@
package cmd
import (
"context"
"fmt"
"github.com/gogf/gf/v2"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gbuild"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
var (
Version = cVersion{}
)
type cVersion struct {
g.Meta `name:"version" brief:"show version information of current binary"`
}
type cVersionInput struct {
g.Meta `name:"version"`
}
type cVersionOutput struct{}
func (c cVersion) Index(ctx context.Context, in cVersionInput) (*cVersionOutput, error) {
info := gbuild.Info()
if info.Git == "" {
info.Git = "none"
}
mlog.Printf(`GoFrame CLI Tool %s, https://goframe.org`, gf.VERSION)
gfVersion, err := c.getGFVersionOfCurrentProject()
if err != nil {
gfVersion = err.Error()
} else {
gfVersion = gfVersion + " in current go.mod"
}
mlog.Printf(`GoFrame Version: %s`, gfVersion)
mlog.Printf(`CLI Installed At: %s`, gfile.SelfPath())
if info.GoFrame == "" {
mlog.Print(`Current is a custom installed version, no installation information.`)
return nil, nil
}
mlog.Print(gstr.Trim(fmt.Sprintf(`
CLI Built Detail:
Go Version: %s
GF Version: %s
Git Commit: %s
Build Time: %s
`, info.Golang, info.GoFrame, info.Git, info.Time)))
return nil, nil
}
// getGFVersionOfCurrentProject checks and returns the GoFrame version current project using.
func (c cVersion) getGFVersionOfCurrentProject() (string, error) {
goModPath := gfile.Join(gfile.Pwd(), "go.mod")
if gfile.Exists(goModPath) {
lines := gstr.SplitAndTrim(gfile.GetContents(goModPath), "\n")
for _, line := range lines {
line = gstr.Trim(line)
// Version 1.
match, err := gregex.MatchString(`^github\.com/gogf/gf\s+(.+)$`, line)
if err != nil {
return "", err
}
if len(match) <= 1 {
// Version > 1.
match, err = gregex.MatchString(`^github\.com/gogf/gf/v\d\s+(.+)$`, line)
if err != nil {
return "", err
}
}
if len(match) > 1 {
return gstr.Trim(match[1]), nil
}
}
return "", gerror.New("cannot find goframe requirement in go.mod")
} else {
return "", gerror.New("cannot find go.mod")
}
}

View File

@ -0,0 +1,380 @@
package gendao
import (
"context"
"fmt"
"strings"
"github.com/gogf/gf/v2/container/garray"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gtime"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gtag"
"hotgo/internal/library/hggen/internal/utility/mlog"
)
const (
CGenDaoConfig = `gfcli.hggen.dao`
CGenDaoUsage = `gf hggen dao [OPTION]`
CGenDaoBrief = `automatically generate go files for dao/do/entity`
CGenDaoEg = `
gf hggen dao
gf hggen dao -l "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
gf hggen dao -p ./model -g user-center -t user,user_detail,user_login
gf hggen dao -r user_
`
CGenDaoAd = `
CONFIGURATION SUPPORT
Options are also supported by configuration file.
It's suggested using configuration file instead of command line arguments making producing.
The configuration node name is "gfcli.hggen.dao", which also supports multiple databases, for example(config.yaml):
gfcli:
hggen:
dao:
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/test"
tables: "order,products"
jsonCase: "CamelLower"
- link: "mysql:root:12345678@tcp(127.0.0.1:3306)/primary"
path: "./my-app"
prefix: "primary_"
tables: "user, userDetail"
`
CGenDaoBriefPath = `directory path for generated files`
CGenDaoBriefLink = `database configuration, the same as the ORM configuration of GoFrame`
CGenDaoBriefTables = `generate models only for given tables, multiple table names separated with ','`
CGenDaoBriefTablesEx = `generate models excluding given tables, multiple table names separated with ','`
CGenDaoBriefPrefix = `add prefix for all table of specified link/database tables`
CGenDaoBriefRemovePrefix = `remove specified prefix of the table, multiple prefix separated with ','`
CGenDaoBriefStdTime = `use time.Time from stdlib instead of gtime.Time for generated time/date fields of tables`
CGenDaoBriefWithTime = `add created time for auto produced go files`
CGenDaoBriefGJsonSupport = `use gJsonSupport to use *gjson.Json instead of string for generated json fields of tables`
CGenDaoBriefImportPrefix = `custom import prefix for generated go files`
CGenDaoBriefDaoPath = `directory path for storing generated dao files under path`
CGenDaoBriefDoPath = `directory path for storing generated do files under path`
CGenDaoBriefEntityPath = `directory path for storing generated entity files under path`
CGenDaoBriefOverwriteDao = `overwrite all dao files both inside/outside internal folder`
CGenDaoBriefModelFile = `custom file name for storing generated model content`
CGenDaoBriefModelFileForDao = `custom file name generating model for DAO operations like Where/Data. It's empty in default`
CGenDaoBriefDescriptionTag = `add comment to description tag for each field`
CGenDaoBriefNoJsonTag = `no json tag will be added for each field`
CGenDaoBriefNoModelComment = `no model comment will be added for each field`
CGenDaoBriefClear = `delete all generated go files that do not exist in database`
CGenDaoBriefGroup = `
specifying the configuration group name of database for generated ORM instance,
it's not necessary and the default value is "default"
`
CGenDaoBriefJsonCase = `
generated json tag case for model struct, cases are as follows:
| Case | Example |
|---------------- |--------------------|
| Camel | AnyKindOfString |
| CamelLower | anyKindOfString | default
| Snake | any_kind_of_string |
| SnakeScreaming | ANY_KIND_OF_STRING |
| SnakeFirstUpper | rgb_code_md5 |
| Kebab | any-kind-of-string |
| KebabScreaming | ANY-KIND-OF-STRING |
`
CGenDaoBriefTplDaoIndexPath = `template file path for dao index file`
CGenDaoBriefTplDaoInternalPath = `template file path for dao internal file`
CGenDaoBriefTplDaoDoPathPath = `template file path for dao do file`
CGenDaoBriefTplDaoEntityPath = `template file path for dao entity file`
tplVarTableName = `{TplTableName}`
tplVarTableNameCamelCase = `{TplTableNameCamelCase}`
tplVarTableNameCamelLowerCase = `{TplTableNameCamelLowerCase}`
tplVarPackageImports = `{TplPackageImports}`
tplVarImportPrefix = `{TplImportPrefix}`
tplVarStructDefine = `{TplStructDefine}`
tplVarColumnDefine = `{TplColumnDefine}`
tplVarColumnNames = `{TplColumnNames}`
tplVarGroupName = `{TplGroupName}`
tplVarDatetimeStr = `{TplDatetimeStr}`
tplVarCreatedAtDatetimeStr = `{TplCreatedAtDatetimeStr}`
)
var (
createdAt = gtime.Now()
)
func init() {
gtag.Sets(g.MapStrStr{
`CGenDaoConfig`: CGenDaoConfig,
`CGenDaoUsage`: CGenDaoUsage,
`CGenDaoBrief`: CGenDaoBrief,
`CGenDaoEg`: CGenDaoEg,
`CGenDaoAd`: CGenDaoAd,
`CGenDaoBriefPath`: CGenDaoBriefPath,
`CGenDaoBriefLink`: CGenDaoBriefLink,
`CGenDaoBriefTables`: CGenDaoBriefTables,
`CGenDaoBriefTablesEx`: CGenDaoBriefTablesEx,
`CGenDaoBriefPrefix`: CGenDaoBriefPrefix,
`CGenDaoBriefRemovePrefix`: CGenDaoBriefRemovePrefix,
`CGenDaoBriefStdTime`: CGenDaoBriefStdTime,
`CGenDaoBriefWithTime`: CGenDaoBriefWithTime,
`CGenDaoBriefDaoPath`: CGenDaoBriefDaoPath,
`CGenDaoBriefDoPath`: CGenDaoBriefDoPath,
`CGenDaoBriefEntityPath`: CGenDaoBriefEntityPath,
`CGenDaoBriefGJsonSupport`: CGenDaoBriefGJsonSupport,
`CGenDaoBriefImportPrefix`: CGenDaoBriefImportPrefix,
`CGenDaoBriefOverwriteDao`: CGenDaoBriefOverwriteDao,
`CGenDaoBriefModelFile`: CGenDaoBriefModelFile,
`CGenDaoBriefModelFileForDao`: CGenDaoBriefModelFileForDao,
`CGenDaoBriefDescriptionTag`: CGenDaoBriefDescriptionTag,
`CGenDaoBriefNoJsonTag`: CGenDaoBriefNoJsonTag,
`CGenDaoBriefNoModelComment`: CGenDaoBriefNoModelComment,
`CGenDaoBriefClear`: CGenDaoBriefClear,
`CGenDaoBriefGroup`: CGenDaoBriefGroup,
`CGenDaoBriefJsonCase`: CGenDaoBriefJsonCase,
`CGenDaoBriefTplDaoIndexPath`: CGenDaoBriefTplDaoIndexPath,
`CGenDaoBriefTplDaoInternalPath`: CGenDaoBriefTplDaoInternalPath,
`CGenDaoBriefTplDaoDoPathPath`: CGenDaoBriefTplDaoDoPathPath,
`CGenDaoBriefTplDaoEntityPath`: CGenDaoBriefTplDaoEntityPath,
})
}
type (
CGenDao struct{}
CGenDaoInput struct {
g.Meta `name:"dao" config:"{CGenDaoConfig}" usage:"{CGenDaoUsage}" brief:"{CGenDaoBrief}" eg:"{CGenDaoEg}" ad:"{CGenDaoAd}"`
Path string `name:"path" short:"p" brief:"{CGenDaoBriefPath}" d:"internal"`
Link string `name:"link" short:"l" brief:"{CGenDaoBriefLink}"`
Tables string `name:"tables" short:"t" brief:"{CGenDaoBriefTables}"`
TablesEx string `name:"tablesEx" short:"x" brief:"{CGenDaoBriefTablesEx}"`
Group string `name:"group" short:"g" brief:"{CGenDaoBriefGroup}" d:"default"`
Prefix string `name:"prefix" short:"f" brief:"{CGenDaoBriefPrefix}"`
RemovePrefix string `name:"removePrefix" short:"r" brief:"{CGenDaoBriefRemovePrefix}"`
JsonCase string `name:"jsonCase" short:"j" brief:"{CGenDaoBriefJsonCase}" d:"CamelLower"`
ImportPrefix string `name:"importPrefix" short:"i" brief:"{CGenDaoBriefImportPrefix}"`
DaoPath string `name:"daoPath" short:"d" brief:"{CGenDaoBriefDaoPath}" d:"dao"`
DoPath string `name:"doPath" short:"o" brief:"{CGenDaoBriefDoPath}" d:"model/do"`
EntityPath string `name:"entityPath" short:"e" brief:"{CGenDaoBriefEntityPath}" d:"model/entity"`
TplDaoIndexPath string `name:"tplDaoIndexPath" short:"t1" brief:"{CGenDaoBriefTplDaoIndexPath}"`
TplDaoInternalPath string `name:"tplDaoInternalPath" short:"t2" brief:"{CGenDaoBriefTplDaoInternalPath}"`
TplDaoDoPath string `name:"tplDaoDoPath" short:"t3" brief:"{CGenDaoBriefTplDaoDoPathPath}"`
TplDaoEntityPath string `name:"tplDaoEntityPath" short:"t4" brief:"{CGenDaoBriefTplDaoEntityPath}"`
StdTime bool `name:"stdTime" short:"s" brief:"{CGenDaoBriefStdTime}" orphan:"true"`
WithTime bool `name:"withTime" short:"w" brief:"{CGenDaoBriefWithTime}" orphan:"true"`
GJsonSupport bool `name:"gJsonSupport" short:"n" brief:"{CGenDaoBriefGJsonSupport}" orphan:"true"`
OverwriteDao bool `name:"overwriteDao" short:"v" brief:"{CGenDaoBriefOverwriteDao}" orphan:"true"`
DescriptionTag bool `name:"descriptionTag" short:"c" brief:"{CGenDaoBriefDescriptionTag}" orphan:"true"`
NoJsonTag bool `name:"noJsonTag" short:"k" brief:"{CGenDaoBriefNoJsonTag}" orphan:"true"`
NoModelComment bool `name:"noModelComment" short:"m" brief:"{CGenDaoBriefNoModelComment}" orphan:"true"`
Clear bool `name:"clear" short:"a" brief:"{CGenDaoBriefClear}" orphan:"true"`
}
CGenDaoOutput struct{}
CGenDaoInternalInput struct {
CGenDaoInput
DB gdb.DB
TableNames []string
NewTableNames []string
ModName string // Module name of current golang project, which is used for import purpose.
}
)
func (c CGenDao) Dao(ctx context.Context, in CGenDaoInput) (out *CGenDaoOutput, err error) {
g.Log().Warningf(ctx, "g.Cfg().Available(ctx):%v", g.Cfg().Available(ctx))
if g.Cfg().Available(ctx) {
v := g.Cfg().MustGet(ctx, CGenDaoConfig)
if v.IsSlice() {
for i := 0; i < len(v.Interfaces()); i++ {
doGenDaoForArray(ctx, i, in)
}
} else {
doGenDaoForArray(ctx, -1, in)
}
} else {
doGenDaoForArray(ctx, -1, in)
}
mlog.Print("done!")
return
}
func DoGenDaoForArray(ctx context.Context, in CGenDaoInput) {
doGenDaoForArray(ctx, -1, in)
}
// doGenDaoForArray implements the "hggen dao" command for configuration array.
func doGenDaoForArray(ctx context.Context, index int, in CGenDaoInput) {
var (
err error
db gdb.DB
modName string // Go module name, eg: github.com/gogf/gf.
)
if index >= 0 {
err = g.Cfg().MustGet(
ctx,
fmt.Sprintf(`%s.%d`, CGenDaoConfig, index),
).Scan(&in)
if err != nil {
mlog.Fatalf(`invalid configuration of "%s": %+v`, CGenDaoConfig, err)
}
}
if dirRealPath := gfile.RealPath(in.Path); dirRealPath == "" {
mlog.Fatalf(`path "%s" does not exist`, in.Path)
}
removePrefixArray := gstr.SplitAndTrim(in.RemovePrefix, ",")
if in.ImportPrefix == "" {
if !gfile.Exists("go.mod") {
mlog.Fatal("go.mod does not exist in current working directory")
}
var (
goModContent = gfile.GetContents("go.mod")
match, _ = gregex.MatchString(`^module\s+(.+)\s*`, goModContent)
)
if len(match) > 1 {
modName = gstr.Trim(match[1])
} else {
mlog.Fatal("module name does not found in go.mod")
}
}
// It uses user passed database configuration.
if in.Link != "" {
var tempGroup = gtime.TimestampNanoStr()
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
Link: in.Link,
})
if db, err = gdb.Instance(tempGroup); err != nil {
mlog.Fatalf(`database initialization failed: %+v`, err)
}
} else {
db = g.DB(in.Group)
}
if db == nil {
mlog.Fatal(`database initialization failed, may be invalid database configuration`)
}
var tableNames []string
if in.Tables != "" {
tableNames = gstr.SplitAndTrim(in.Tables, ",")
} else {
tableNames, err = db.Tables(context.TODO())
if err != nil {
mlog.Fatalf("fetching tables failed: %+v", err)
}
}
// Table excluding.
if in.TablesEx != "" {
array := garray.NewStrArrayFrom(tableNames)
for _, v := range gstr.SplitAndTrim(in.TablesEx, ",") {
array.RemoveValue(v)
}
tableNames = array.Slice()
}
// Generating dao & model go files one by one according to given table name.
newTableNames := make([]string, len(tableNames))
for i, tableName := range tableNames {
newTableName := tableName
for _, v := range removePrefixArray {
newTableName = gstr.TrimLeftStr(newTableName, v, 1)
}
newTableName = in.Prefix + newTableName
newTableNames[i] = newTableName
}
// Dao: index and internal.
generateDao(ctx, CGenDaoInternalInput{
CGenDaoInput: in,
DB: db,
TableNames: tableNames,
NewTableNames: newTableNames,
ModName: modName,
})
// Do.
generateDo(ctx, CGenDaoInternalInput{
CGenDaoInput: in,
DB: db,
TableNames: tableNames,
NewTableNames: newTableNames,
ModName: modName,
})
// Entity.
generateEntity(ctx, CGenDaoInternalInput{
CGenDaoInput: in,
DB: db,
TableNames: tableNames,
NewTableNames: newTableNames,
ModName: modName,
})
}
func getImportPartContent(source string, isDo bool) string {
var (
packageImportsArray = garray.NewStrArray()
)
if isDo {
packageImportsArray.Append(`"github.com/gogf/gf/v2/frame/g"`)
}
// Time package recognition.
if strings.Contains(source, "gtime.Time") {
packageImportsArray.Append(`"github.com/gogf/gf/v2/os/gtime"`)
} else if strings.Contains(source, "time.Time") {
packageImportsArray.Append(`"time"`)
}
// Json type.
if strings.Contains(source, "gjson.Json") {
packageImportsArray.Append(`"github.com/gogf/gf/v2/encoding/gjson"`)
}
// Generate and write content to golang file.
packageImportsStr := ""
if packageImportsArray.Len() > 0 {
packageImportsStr = fmt.Sprintf("import(\n%s\n)", packageImportsArray.Join("\n"))
}
return packageImportsStr
}
func replaceDefaultVar(in CGenDaoInternalInput, origin string) string {
var tplCreatedAtDatetimeStr string
var tplDatetimeStr string = createdAt.String()
if in.WithTime {
tplCreatedAtDatetimeStr = fmt.Sprintf(`Created at %s`, tplDatetimeStr)
}
return gstr.ReplaceByMap(origin, g.MapStrStr{
tplVarDatetimeStr: tplDatetimeStr,
tplVarCreatedAtDatetimeStr: tplCreatedAtDatetimeStr,
})
}
func sortFieldKeyForDao(fieldMap map[string]*gdb.TableField) []string {
names := make(map[int]string)
for _, field := range fieldMap {
names[field.Index] = field.Name
}
var (
i = 0
j = 0
result = make([]string, len(names))
)
for {
if len(names) == 0 {
break
}
if val, ok := names[i]; ok {
result[j] = val
j++
delete(names, i)
}
i++
}
return result
}
func getTemplateFromPathOrDefault(filePath string, def string) string {
if filePath != "" {
if contents := gfile.GetContents(filePath); contents != "" {
return contents
}
}
return def
}

View File

@ -0,0 +1,24 @@
package gendao
import (
"context"
"github.com/gogf/gf/v2/os/gfile"
"hotgo/internal/library/hggen/internal/utility/mlog"
"hotgo/internal/library/hggen/internal/utility/utils"
)
func doClear(ctx context.Context, dirPath string) {
files, err := gfile.ScanDirFile(dirPath, "*.go", true)
if err != nil {
mlog.Fatal(err)
}
for _, file := range files {
if utils.IsFileDoNotEdit(file) {
if err = gfile.Remove(file); err != nil {
mlog.Print(err)
}
}
}
}

View File

@ -0,0 +1,228 @@
package gendao
import (
"bytes"
"context"
"fmt"
"strings"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/olekukonko/tablewriter"
"hotgo/internal/library/hggen/internal/consts"
"hotgo/internal/library/hggen/internal/utility/mlog"
"hotgo/internal/library/hggen/internal/utility/utils"
)
func generateDao(ctx context.Context, in CGenDaoInternalInput) {
var (
dirPathDao = gfile.Join(in.Path, in.DaoPath)
dirPathDaoInternal = gfile.Join(dirPathDao, "internal")
)
if in.Clear {
doClear(ctx, dirPathDao)
}
for i := 0; i < len(in.TableNames); i++ {
generateDaoSingle(ctx, generateDaoSingleInput{
CGenDaoInternalInput: in,
TableName: in.TableNames[i],
NewTableName: in.NewTableNames[i],
DirPathDao: dirPathDao,
DirPathDaoInternal: dirPathDaoInternal,
})
}
}
type generateDaoSingleInput struct {
CGenDaoInternalInput
TableName string // TableName specifies the table name of the table.
NewTableName string // NewTableName specifies the prefix-stripped name of the table.
DirPathDao string
DirPathDaoInternal string
}
// generateDaoSingle generates the dao and model content of given table.
func generateDaoSingle(ctx context.Context, in generateDaoSingleInput) {
// Generating table data preparing.
fieldMap, err := in.DB.TableFields(ctx, in.TableName)
if err != nil {
mlog.Fatalf(`fetching tables fields failed for table "%s": %+v`, in.TableName, err)
}
var (
dirRealPath = gfile.RealPath(in.Path)
tableNameCamelCase = gstr.CaseCamel(in.NewTableName)
tableNameCamelLowerCase = gstr.CaseCamelLower(in.NewTableName)
tableNameSnakeCase = gstr.CaseSnake(in.NewTableName)
importPrefix = in.ImportPrefix
)
if importPrefix == "" {
if dirRealPath == "" {
dirRealPath = in.Path
importPrefix = dirRealPath
importPrefix = gstr.Trim(dirRealPath, "./")
} else {
importPrefix = gstr.Replace(dirRealPath, gfile.Pwd(), "")
}
importPrefix = gstr.Replace(importPrefix, gfile.Separator, "/")
importPrefix = gstr.Join(g.SliceStr{in.ModName, importPrefix, in.DaoPath}, "/")
importPrefix, _ = gregex.ReplaceString(`\/{2,}`, `/`, gstr.Trim(importPrefix, "/"))
} else {
importPrefix = gstr.Join(g.SliceStr{importPrefix, in.DaoPath}, "/")
}
fileName := gstr.Trim(tableNameSnakeCase, "-_.")
if len(fileName) > 5 && fileName[len(fileName)-5:] == "_test" {
// Add suffix to avoid the table name which contains "_test",
// which would make the go file a testing file.
fileName += "_table"
}
// dao - index
generateDaoIndex(generateDaoIndexInput{
generateDaoSingleInput: in,
TableNameCamelCase: tableNameCamelCase,
TableNameCamelLowerCase: tableNameCamelLowerCase,
ImportPrefix: importPrefix,
FileName: fileName,
})
// dao - internal
generateDaoInternal(generateDaoInternalInput{
generateDaoSingleInput: in,
TableNameCamelCase: tableNameCamelCase,
TableNameCamelLowerCase: tableNameCamelLowerCase,
ImportPrefix: importPrefix,
FileName: fileName,
FieldMap: fieldMap,
})
}
type generateDaoIndexInput struct {
generateDaoSingleInput
TableNameCamelCase string
TableNameCamelLowerCase string
ImportPrefix string
FileName string
}
func generateDaoIndex(in generateDaoIndexInput) {
path := gfile.Join(in.DirPathDao, in.FileName+".go")
if in.OverwriteDao || !gfile.Exists(path) {
indexContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent),
g.MapStrStr{
tplVarImportPrefix: in.ImportPrefix,
tplVarTableName: in.TableName,
tplVarTableNameCamelCase: in.TableNameCamelCase,
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
})
indexContent = replaceDefaultVar(in.CGenDaoInternalInput, indexContent)
if err := gfile.PutContents(path, strings.TrimSpace(indexContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
utils.GoFmt(path)
mlog.Print("generated:", path)
}
}
}
type generateDaoInternalInput struct {
generateDaoSingleInput
TableNameCamelCase string
TableNameCamelLowerCase string
ImportPrefix string
FileName string
FieldMap map[string]*gdb.TableField
}
func generateDaoInternal(in generateDaoInternalInput) {
path := gfile.Join(in.DirPathDaoInternal, in.FileName+".go")
modelContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
g.MapStrStr{
tplVarImportPrefix: in.ImportPrefix,
tplVarTableName: in.TableName,
tplVarGroupName: in.Group,
tplVarTableNameCamelCase: in.TableNameCamelCase,
tplVarTableNameCamelLowerCase: in.TableNameCamelLowerCase,
tplVarColumnDefine: gstr.Trim(generateColumnDefinitionForDao(in.FieldMap)),
tplVarColumnNames: gstr.Trim(generateColumnNamesForDao(in.FieldMap)),
})
modelContent = replaceDefaultVar(in.CGenDaoInternalInput, modelContent)
if err := gfile.PutContents(path, strings.TrimSpace(modelContent)); err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", path, err)
} else {
utils.GoFmt(path)
mlog.Print("generated:", path)
}
}
// generateColumnNamesForDao generates and returns the column names assignment content of column struct
// for specified table.
func generateColumnNamesForDao(fieldMap map[string]*gdb.TableField) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
field := fieldMap[name]
array[index] = []string{
" #" + gstr.CaseCamel(field.Name) + ":",
fmt.Sprintf(` #"%s",`, field.Name),
}
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
namesContent := buffer.String()
// Let's do this hack of table writer for indent!
namesContent = gstr.Replace(namesContent, " #", "")
buffer.Reset()
buffer.WriteString(namesContent)
return buffer.String()
}
// generateColumnDefinitionForDao generates and returns the column names definition for specified table.
func generateColumnDefinitionForDao(fieldMap map[string]*gdb.TableField) string {
var (
buffer = bytes.NewBuffer(nil)
array = make([][]string, len(fieldMap))
names = sortFieldKeyForDao(fieldMap)
)
for index, name := range names {
var (
field = fieldMap[name]
comment = gstr.Trim(gstr.ReplaceByArray(field.Comment, g.SliceStr{
"\n", " ",
"\r", " ",
}))
)
array[index] = []string{
" #" + gstr.CaseCamel(field.Name),
" # " + "string",
" #" + fmt.Sprintf(`// %s`, comment),
}
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
defineContent := buffer.String()
// Let's do this hack of table writer for indent!
defineContent = gstr.Replace(defineContent, " #", "")
buffer.Reset()
buffer.WriteString(defineContent)
return buffer.String()
}

View File

@ -0,0 +1,82 @@
package gendao
import (
"context"
"fmt"
"strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/library/hggen/internal/consts"
"hotgo/internal/library/hggen/internal/utility/mlog"
"hotgo/internal/library/hggen/internal/utility/utils"
)
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
var dirPathDo = gfile.Join(in.Path, in.DoPath)
if in.Clear {
doClear(ctx, dirPathDo)
}
in.NoJsonTag = true
in.DescriptionTag = false
in.NoModelComment = false
// Model content.
for i, tableName := range in.TableNames {
fieldMap, err := in.DB.TableFields(ctx, tableName)
if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", tableName, err)
}
var (
newTableName = in.NewTableNames[i]
doFilePath = gfile.Join(dirPathDo, gstr.CaseSnake(newTableName)+".go")
structDefinition = generateStructDefinition(ctx, generateStructDefinitionInput{
CGenDaoInternalInput: in,
TableName: tableName,
StructName: gstr.CaseCamel(newTableName),
FieldMap: fieldMap,
IsDo: true,
})
)
// replace all types to interface{}.
structDefinition, _ = gregex.ReplaceStringFuncMatch(
"([A-Z]\\w*?)\\s+([\\w\\*\\.]+?)\\s+(//)",
structDefinition,
func(match []string) string {
// If the type is already a pointer/slice/map, it does nothing.
if !gstr.HasPrefix(match[2], "*") && !gstr.HasPrefix(match[2], "[]") && !gstr.HasPrefix(match[2], "map") {
return fmt.Sprintf(`%s interface{} %s`, match[1], match[3])
}
return match[0]
},
)
modelContent := generateDoContent(
in,
tableName,
gstr.CaseCamel(newTableName),
structDefinition,
)
err = gfile.PutContents(doFilePath, strings.TrimSpace(modelContent))
if err != nil {
mlog.Fatalf(`writing content to "%s" failed: %v`, doFilePath, err)
} else {
utils.GoFmt(doFilePath)
mlog.Print("generated:", doFilePath)
}
}
}
func generateDoContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
doContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoDoPath, consts.TemplateGenDaoDoContent),
g.MapStrStr{
tplVarTableName: tableName,
tplVarPackageImports: getImportPartContent(structDefine, true),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
})
doContent = replaceDefaultVar(in, doContent)
return doContent
}

View File

@ -0,0 +1,64 @@
package gendao
import (
"context"
"strings"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/library/hggen/internal/consts"
"hotgo/internal/library/hggen/internal/utility/mlog"
"hotgo/internal/library/hggen/internal/utility/utils"
)
func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
var dirPathEntity = gfile.Join(in.Path, in.EntityPath)
if in.Clear {
doClear(ctx, dirPathEntity)
}
// Model content.
for i, tableName := range in.TableNames {
fieldMap, err := in.DB.TableFields(ctx, tableName)
if err != nil {
mlog.Fatalf("fetching tables fields failed for table '%s':\n%v", tableName, err)
}
var (
newTableName = in.NewTableNames[i]
entityFilePath = gfile.Join(dirPathEntity, gstr.CaseSnake(newTableName)+".go")
entityContent = generateEntityContent(
in,
newTableName,
gstr.CaseCamel(newTableName),
generateStructDefinition(ctx, generateStructDefinitionInput{
CGenDaoInternalInput: in,
TableName: tableName,
StructName: gstr.CaseCamel(newTableName),
FieldMap: fieldMap,
IsDo: false,
}),
)
)
err = gfile.PutContents(entityFilePath, strings.TrimSpace(entityContent))
if err != nil {
mlog.Fatalf("writing content to '%s' failed: %v", entityFilePath, err)
} else {
utils.GoFmt(entityFilePath)
mlog.Print("generated:", entityFilePath)
}
}
}
func generateEntityContent(in CGenDaoInternalInput, tableName, tableNameCamelCase, structDefine string) string {
entityContent := gstr.ReplaceByMap(
getTemplateFromPathOrDefault(in.TplDaoEntityPath, consts.TemplateGenDaoEntityContent),
g.MapStrStr{
tplVarTableName: tableName,
tplVarPackageImports: getImportPartContent(structDefine, false),
tplVarTableNameCamelCase: tableNameCamelCase,
tplVarStructDefine: structDefine,
})
entityContent = replaceDefaultVar(in, entityContent)
return entityContent
}

View File

@ -0,0 +1,153 @@
package gendao
import (
"bytes"
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/olekukonko/tablewriter"
)
type generateStructDefinitionInput struct {
CGenDaoInternalInput
TableName string // Table name.
StructName string // Struct name.
FieldMap map[string]*gdb.TableField // Table field map.
IsDo bool // Is generating DTO struct.
}
func generateStructDefinition(ctx context.Context, in generateStructDefinitionInput) string {
buffer := bytes.NewBuffer(nil)
array := make([][]string, len(in.FieldMap))
names := sortFieldKeyForDao(in.FieldMap)
for index, name := range names {
field := in.FieldMap[name]
array[index] = generateStructFieldDefinition(ctx, field, in)
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
stContent := buffer.String()
// Let's do this hack of table writer for indent!
stContent = gstr.Replace(stContent, " #", "")
stContent = gstr.Replace(stContent, "` ", "`")
stContent = gstr.Replace(stContent, "``", "")
buffer.Reset()
buffer.WriteString(fmt.Sprintf("type %s struct {\n", in.StructName))
if in.IsDo {
buffer.WriteString(fmt.Sprintf("g.Meta `orm:\"table:%s, do:true\"`\n", in.TableName))
}
buffer.WriteString(stContent)
buffer.WriteString("}")
return buffer.String()
}
// generateStructFieldForModel generates and returns the attribute definition for specified field.
func generateStructFieldDefinition(
ctx context.Context, field *gdb.TableField, in generateStructDefinitionInput,
) []string {
var (
err error
typeName string
jsonTag = getJsonTagFromCase(field.Name, in.JsonCase)
)
typeName, err = in.DB.CheckLocalTypeForField(ctx, field.Type, nil)
if err != nil {
panic(err)
}
switch typeName {
case gdb.LocalTypeDate, gdb.LocalTypeDatetime:
if in.StdTime {
typeName = "time.Time"
} else {
typeName = "*gtime.Time"
}
case gdb.LocalTypeInt64Bytes:
typeName = "int64"
case gdb.LocalTypeUint64Bytes:
typeName = "uint64"
// Special type handle.
case gdb.LocalTypeJson, gdb.LocalTypeJsonb:
if in.GJsonSupport {
typeName = "*gjson.Json"
} else {
typeName = "string"
}
}
var (
tagKey = "`"
result = []string{
" #" + gstr.CaseCamel(field.Name),
" #" + typeName,
}
descriptionTag = gstr.Replace(formatComment(field.Comment), `"`, `\"`)
)
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))
result = append(result, " #"+fmt.Sprintf(`description:"%s"`+tagKey, descriptionTag))
result = append(result, " #"+fmt.Sprintf(`// %s`, formatComment(field.Comment)))
for k, v := range result {
if in.NoJsonTag {
v, _ = gregex.ReplaceString(`json:".+"`, ``, v)
}
if !in.DescriptionTag {
v, _ = gregex.ReplaceString(`description:".*"`, ``, v)
}
if in.NoModelComment {
v, _ = gregex.ReplaceString(`//.+`, ``, v)
}
result[k] = v
}
return result
}
// formatComment formats the comment string to fit the golang code without any lines.
func formatComment(comment string) string {
comment = gstr.ReplaceByArray(comment, g.SliceStr{
"\n", " ",
"\r", " ",
})
comment = gstr.Replace(comment, `\n`, " ")
comment = gstr.Trim(comment)
return comment
}
// getJsonTagFromCase call gstr.Case* function to convert the s to specified case.
func getJsonTagFromCase(str, caseStr string) string {
switch gstr.ToLower(caseStr) {
case gstr.ToLower("Camel"):
return gstr.CaseCamel(str)
case gstr.ToLower("CamelLower"):
return gstr.CaseCamelLower(str)
case gstr.ToLower("Kebab"):
return gstr.CaseKebab(str)
case gstr.ToLower("KebabScreaming"):
return gstr.CaseKebabScreaming(str)
case gstr.ToLower("Snake"):
return gstr.CaseSnake(str)
case gstr.ToLower("SnakeFirstUpper"):
return gstr.CaseSnakeFirstUpper(str)
case gstr.ToLower("SnakeScreaming"):
return gstr.CaseSnakeScreaming(str)
}
return str
}

Some files were not shown because too many files have changed in this diff Show More