mirror of
https://github.com/bufanyun/hotgo.git
synced 2025-01-23 02:40:23 +08:00
发布v2.11.5版本,更新内容请查看:https://github.com/bufanyun/hotgo/blob/v2.0/docs/guide-zh-CN/start-update-log.md
This commit is contained in:
parent
40117c700d
commit
70e9f966c3
@ -6,7 +6,7 @@
|
||||
</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.4-green" alt="goframe">
|
||||
<img src="https://img.shields.io/badge/goframe-2.5-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">
|
||||
@ -68,7 +68,7 @@
|
||||
15. 代码生成:支持自动化生成前后端代码。CURD关联表、树表、消息队列、定时任务一键生成等。
|
||||
16. 插件应用:支持一键生成插件模板,每个插件之间开发隔离,拥有独立多应用入口、独立配置。完美支持多人协同开发、插件插拔不会对原系统产生影响等。
|
||||
17. 服务监控:监视当前系统CPU、内存、磁盘、网络、堆栈等相关信息。
|
||||
18. 附件管理:文件图片上传,支持本地、阿里云oss、腾讯云cos、ucloud对象存储、七牛云对象存储等多种上传驱动,后台一键切换配置,并集成了文件选择器。
|
||||
18. 附件管理:文件图片上传,支持本地、阿里云oss、腾讯云cos、ucloud对象存储、七牛云对象存储、minio等多种上传驱动,后台一键切换配置,并集成了文件选择器。
|
||||
19. TCP服务:基于gtcp的服务应用,支持长连接、断线重连、服务认证、路由分发、RPC消息、拦截器和数据绑定等。简化和规范了服务器开发流程。
|
||||
20. 消息队列:同时兼容 kafka、redis、rocketmq、磁盘队列,一键配置切换到场景适用的MQ。
|
||||
21. 通知公告:采用websocket实时推送在线用户最新通知、公告、私信消息。
|
||||
|
@ -31,7 +31,7 @@ gfcli:
|
||||
|
||||
- 以下方式任选其一即可
|
||||
|
||||
1、 make一键编译 (linux或mac环境推荐)
|
||||
1、 make一键编译 (确认已安装`make环境`)
|
||||
```shell
|
||||
cd server && make build
|
||||
```
|
||||
@ -46,16 +46,27 @@ cd ../web && yarn build # 切换到web项目下,
|
||||
echo "y" | gf build # 编译hotgo服务端
|
||||
|
||||
# 不出意外你已经编译好了hotgo可执行文件!
|
||||
```
|
||||
```
|
||||
|
||||
3、分服务编译
|
||||
3、分端编译 (多人开发时推荐)
|
||||
```shell
|
||||
# 编译服务端
|
||||
cd server # 切换到服务端目录下
|
||||
rm -rf ./resource/public/admin/ # 删除之前的web资源,如果开发环境没有这个目录可以忽略此步骤
|
||||
echo "y" | gf build # 编译hotgo服务端
|
||||
|
||||
待写。
|
||||
# 编译web端
|
||||
cd web
|
||||
yarn build
|
||||
|
||||
# web端编译完成后,将web/dist/*中的文件上传到`server`端线上运行目录:/resource/public/admin即可
|
||||
# 至此,web端和server端都可以独立覆盖更新
|
||||
```
|
||||
|
||||
|
||||
### 修改生产配置文件
|
||||
- 配置文件:server/manifest/config/config.yaml
|
||||
> 如关闭代码生成功能、修改数据库地址、缓存驱动、队列驱动、日志路径等
|
||||
> 如关闭debug、mode设为生产环境、修改数据库地址、缓存驱动、队列驱动、日志路径等
|
||||
|
||||
|
||||
|
||||
|
@ -13,6 +13,9 @@
|
||||
|
||||
线上或非本地运行时,请到 系统设置 -> 配置管理 -> 基本设置 -> 找到网站域名和websocket地址,改成你自己实际的地址,保存刷新页面即可
|
||||
|
||||
#### 2、web页面菜单切换后页面出现白屏
|
||||
|
||||
请参考:https://github.com/jekip/naive-ui-admin/issues/183
|
||||
|
||||
|
||||
### 二、数据库相关
|
||||
@ -29,7 +32,17 @@
|
||||
|
||||
> 报错信息:panic: possible config files "config" or "config.toml/yaml/yml/json/ini/xml/properties" not found in resource manager or following system searching paths:
|
||||
|
||||
这是因为系统没有找到配置文件,将配置文件 `manifest/config/config.yaml.bak` 复制后改为`manifest/config/config.yaml`
|
||||
系统没有找到配置文件,将配置文件 `manifest/config/config.yaml.bak` 复制后改为`manifest/config/config.yaml`
|
||||
|
||||
|
||||
#### 2、net.DialTimeout failed with network
|
||||
|
||||
> 报错信息:connect to 127.0.0.1:8099 error: net.DialTimeout failed with network "tcp", address "127.0.0.1:8099", timeout "10s": dial tcp
|
||||
|
||||
- http服务没有启动或正在启动
|
||||
- 通过一键启动所有服务运行时属正常情况,多服务启动时存在先后顺序问题,`tcpClient`比`tcpServer`先启动完成导致的,等`tcpServer`启动完成后会自动重连
|
||||
|
||||
|
||||
|
||||
|
||||
详细请参考 - [系统安装](start-installation.md)
|
||||
|
@ -11,6 +11,26 @@
|
||||
|
||||
> 如果升级(覆盖)代码后打开会出现 sql 报错, 请检查更新的数据库格式或自行调整
|
||||
|
||||
### v2.11.5
|
||||
updated 2023.11.25
|
||||
|
||||
- 增加`minio`上传驱动支持
|
||||
- 增加定时任务调度日志,增加同方法多任务支持
|
||||
- 增加gf运行模式控制,生产环境时隐藏开发相关菜单
|
||||
- 增加树形表格新增/修改自动维护上下级关系通用处理
|
||||
- 增加树形表格使用例子
|
||||
- 优化:gf版本升级到v2.5.7
|
||||
- 优化`websocket`默认路径配置
|
||||
- 优化预处理中间件错误码跟随
|
||||
- 优化插件静态目录为可选项
|
||||
- 修复升级gf版本后服务日志记录内容为空问题
|
||||
- 修复角色权限选择数据重复问题
|
||||
- 修复服务日志无日志内容问题
|
||||
- 修复用户批量删除可以删除超管问题
|
||||
- 修复代码生成时偶尔找不到主键索引问题
|
||||
- 修复树形选项组件在`BasicForm`无法使用问题
|
||||
- 修复表格批量删除重复传参问题
|
||||
- 修复文件缓存`GetOrSet`和`GetOrSetFunc`缓存过期不刷新问题
|
||||
|
||||
### v2.9.8
|
||||
updated 2023.10.21
|
||||
@ -19,8 +39,6 @@ updated 2023.10.21
|
||||
- 优化:优化代码生成表单滑动
|
||||
- 优化:优化字典列表编辑生效时机
|
||||
- 修复:修复日期组件默认值无效问题
|
||||
- 修复:修复配置参数`exceptLogin`命名
|
||||
|
||||
### v2.9.3
|
||||
updated 2023.10.08
|
||||
|
||||
|
@ -17,8 +17,8 @@
|
||||
type Cron interface {
|
||||
// GetName 获取任务名称
|
||||
GetName() string
|
||||
// Execute 执行一次任务
|
||||
Execute(ctx context.Context)
|
||||
// Execute 执行任务
|
||||
Execute(ctx context.Context, parser *Parser) (err error)
|
||||
}
|
||||
```
|
||||
|
||||
@ -54,11 +54,10 @@ func (c *cTest) GetName() string {
|
||||
}
|
||||
|
||||
// Execute 执行任务
|
||||
func (c *cTest) Execute(ctx context.Context) {
|
||||
cron.Logger().Infof(ctx, "cron test Execute:%v", time.Now())
|
||||
func (c *cTest) Execute(ctx context.Context, parser *cron.Parser) (err error) {
|
||||
parser.Logger.Infof(ctx, "cron test Execute:%v", time.Now()) // 记录任务调度日志
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
继续在后台系统设置-定时任务-添加任务,填写的任务名称需要和上面的名称保持一致,再进行简单的策略配置以后,一个后台可控的定时任务就添加好了!
|
||||
|
1
server/.gitignore
vendored
1
server/.gitignore
vendored
@ -26,6 +26,7 @@ storage/cert/ssl/server.key
|
||||
storage/cert/pay/alipay/
|
||||
storage/cert/pay/wxpay/
|
||||
temp/
|
||||
logs/
|
||||
main.exe
|
||||
main.exe~
|
||||
*.exe
|
||||
|
@ -12,7 +12,7 @@
|
||||
|
||||
### 安装
|
||||
|
||||
1、安装 HotGo (2.1.4及以上)
|
||||
1、安装 HotGo (2.11.4及以上)
|
||||
|
||||
项目介绍:https://github.com/bufanyun/hotgo
|
||||
|
||||
|
92
server/addons/hgexample/api/admin/treetable/treetable.go
Normal file
92
server/addons/hgexample/api/admin/treetable/treetable.go
Normal file
@ -0,0 +1,92 @@
|
||||
// Package treetable
|
||||
// @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 treetable
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"hotgo/addons/hgexample/model/input/sysin"
|
||||
"hotgo/internal/model/input/form"
|
||||
)
|
||||
|
||||
// ListReq 查询列表
|
||||
type ListReq struct {
|
||||
g.Meta `path:"/treeTable/list" method:"get" tags:"表格" summary:"获取表格列表"`
|
||||
sysin.TreeTableListInp
|
||||
}
|
||||
|
||||
type ListRes struct {
|
||||
form.PageRes
|
||||
List []*sysin.TreeTableListModel `json:"list" dc:"数据列表"`
|
||||
}
|
||||
|
||||
// ExportReq 导出列表
|
||||
type ExportReq struct {
|
||||
g.Meta `path:"/treeTable/export" method:"get" tags:"表格" summary:"导出表格列表"`
|
||||
sysin.TableListInp
|
||||
}
|
||||
|
||||
type ExportRes struct{}
|
||||
|
||||
// ViewReq 获取信息
|
||||
type ViewReq struct {
|
||||
g.Meta `path:"/treeTable/view" method:"get" tags:"表格" summary:"获取指定信息"`
|
||||
sysin.TableViewInp
|
||||
}
|
||||
|
||||
type ViewRes struct {
|
||||
*sysin.TableViewModel
|
||||
}
|
||||
|
||||
// EditReq 修改/新增
|
||||
type EditReq struct {
|
||||
g.Meta `path:"/treeTable/edit" method:"post" tags:"表格" summary:"修改/新增表格"`
|
||||
sysin.TableEditInp
|
||||
}
|
||||
|
||||
type EditRes struct{}
|
||||
|
||||
// DeleteReq 删除
|
||||
type DeleteReq struct {
|
||||
g.Meta `path:"/treeTable/delete" method:"post" tags:"表格" summary:"删除表格"`
|
||||
sysin.TableDeleteInp
|
||||
}
|
||||
|
||||
type DeleteRes struct{}
|
||||
|
||||
// MaxSortReq 最大排序
|
||||
type MaxSortReq struct {
|
||||
g.Meta `path:"/treeTable/maxSort" method:"get" tags:"表格" summary:"表格最大排序"`
|
||||
sysin.TableMaxSortInp
|
||||
}
|
||||
|
||||
type MaxSortRes struct {
|
||||
*sysin.TableMaxSortModel
|
||||
}
|
||||
|
||||
// StatusReq 更新状态
|
||||
type StatusReq struct {
|
||||
g.Meta `path:"/treeTable/status" method:"post" tags:"表格" summary:"更新表格状态"`
|
||||
sysin.TableStatusInp
|
||||
}
|
||||
|
||||
type StatusRes struct{}
|
||||
|
||||
// SwitchReq 更新开关状态
|
||||
type SwitchReq struct {
|
||||
g.Meta `path:"/treeTable/switch" method:"post" tags:"表格" summary:"更新表格状态"`
|
||||
sysin.TableSwitchInp
|
||||
}
|
||||
|
||||
type SwitchRes struct{}
|
||||
|
||||
// SelectReq 树形选项
|
||||
type SelectReq struct {
|
||||
g.Meta `path:"/treeTable/select" method:"get" tags:"表格" summary:"树形选项"`
|
||||
}
|
||||
|
||||
type SelectRes struct {
|
||||
List []*sysin.TableTree `json:"list" dc:"数据列表"`
|
||||
}
|
92
server/addons/hgexample/controller/admin/sys/tree_table.go
Normal file
92
server/addons/hgexample/controller/admin/sys/tree_table.go
Normal file
@ -0,0 +1,92 @@
|
||||
// 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
|
||||
package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/addons/hgexample/api/admin/treetable"
|
||||
"hotgo/addons/hgexample/service"
|
||||
)
|
||||
|
||||
var (
|
||||
TreeTable = cTreeTable{}
|
||||
)
|
||||
|
||||
type cTreeTable struct{}
|
||||
|
||||
// List 查看列表
|
||||
func (c *cTreeTable) List(ctx context.Context, req *treetable.ListReq) (res *treetable.ListRes, err error) {
|
||||
list, totalCount, err := service.SysTreeTable().List(ctx, &req.TreeTableListInp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res = new(treetable.ListRes)
|
||||
res.List = list
|
||||
res.PageRes.Pack(req, totalCount)
|
||||
return
|
||||
}
|
||||
|
||||
// Export 导出列表
|
||||
func (c *cTreeTable) Export(ctx context.Context, req *treetable.ExportReq) (res *treetable.ExportRes, err error) {
|
||||
err = service.SysTable().Export(ctx, &req.TableListInp)
|
||||
return
|
||||
}
|
||||
|
||||
// Edit 更新
|
||||
func (c *cTreeTable) Edit(ctx context.Context, req *treetable.EditReq) (res *treetable.EditRes, err error) {
|
||||
err = service.SysTreeTable().Edit(ctx, &req.TableEditInp)
|
||||
return
|
||||
}
|
||||
|
||||
// MaxSort 最大排序
|
||||
func (c *cTreeTable) MaxSort(ctx context.Context, req *treetable.MaxSortReq) (res *treetable.MaxSortRes, err error) {
|
||||
data, err := service.SysTable().MaxSort(ctx, &req.TableMaxSortInp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res = new(treetable.MaxSortRes)
|
||||
res.TableMaxSortModel = data
|
||||
return
|
||||
}
|
||||
|
||||
// View 获取指定信息
|
||||
func (c *cTreeTable) View(ctx context.Context, req *treetable.ViewReq) (res *treetable.ViewRes, err error) {
|
||||
data, err := service.SysTable().View(ctx, &req.TableViewInp)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
res = new(treetable.ViewRes)
|
||||
res.TableViewModel = data
|
||||
return
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
func (c *cTreeTable) Delete(ctx context.Context, req *treetable.DeleteReq) (res *treetable.DeleteRes, err error) {
|
||||
err = service.SysTreeTable().Delete(ctx, &req.TableDeleteInp)
|
||||
return
|
||||
}
|
||||
|
||||
// Status 更新状态
|
||||
func (c *cTreeTable) Status(ctx context.Context, req *treetable.StatusReq) (res *treetable.StatusRes, err error) {
|
||||
err = service.SysTable().Status(ctx, &req.TableStatusInp)
|
||||
return
|
||||
}
|
||||
|
||||
// Switch 更新开关状态
|
||||
func (c *cTreeTable) Switch(ctx context.Context, req *treetable.SwitchReq) (res *treetable.SwitchRes, err error) {
|
||||
err = service.SysTable().Switch(ctx, &req.TableSwitchInp)
|
||||
return
|
||||
}
|
||||
|
||||
// Select 树形选项
|
||||
func (c *cTreeTable) Select(ctx context.Context, _ *treetable.SelectReq) (res *treetable.SelectRes, err error) {
|
||||
res = new(treetable.SelectRes)
|
||||
res.List, err = service.SysTreeTable().Select(ctx)
|
||||
return
|
||||
}
|
@ -1,5 +1,5 @@
|
||||
// ==========================================================================
|
||||
// Code generated by GoFrame CLI tool. DO NOT EDIT.
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package logic
|
||||
|
186
server/addons/hgexample/logic/sys/tree_table.go
Normal file
186
server/addons/hgexample/logic/sys/tree_table.go
Normal file
@ -0,0 +1,186 @@
|
||||
// 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
|
||||
package sys
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"hotgo/addons/hgexample/model/input/sysin"
|
||||
"hotgo/addons/hgexample/service"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/hgorm"
|
||||
"hotgo/internal/library/hgorm/handler"
|
||||
"hotgo/internal/model/entity"
|
||||
)
|
||||
|
||||
type sSysTreeTable struct{}
|
||||
|
||||
func NewSysTreeTable() *sSysTreeTable {
|
||||
return &sSysTreeTable{}
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterSysTreeTable(NewSysTreeTable())
|
||||
}
|
||||
|
||||
// Model Orm模型
|
||||
func (s *sSysTreeTable) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
|
||||
return handler.Model(dao.AddonHgexampleTable.Ctx(ctx), option...)
|
||||
}
|
||||
|
||||
// List 获取列表
|
||||
func (s *sSysTreeTable) List(ctx context.Context, in *sysin.TreeTableListInp) (list []*sysin.TreeTableListModel, totalCount int, err error) {
|
||||
mod := s.Model(ctx)
|
||||
cols := dao.AddonHgexampleTable.Columns()
|
||||
|
||||
if in.Title != "" {
|
||||
mod = mod.WhereLike(cols.Title, "%"+in.Title+"%")
|
||||
}
|
||||
|
||||
if in.Content != "" {
|
||||
mod = mod.WhereLike(cols.Content, "%"+in.Content+"%")
|
||||
}
|
||||
|
||||
if in.Status > 0 {
|
||||
mod = mod.Where(cols.Status, in.Status)
|
||||
}
|
||||
|
||||
if in.Switch > 0 {
|
||||
mod = mod.Where(cols.Switch, in.Switch)
|
||||
}
|
||||
|
||||
if in.Pid > 0 {
|
||||
mod = mod.Where(cols.Pid, in.Pid)
|
||||
}
|
||||
|
||||
if len(in.Price) > 0 {
|
||||
if in.Price[0] > 0 && in.Price[1] > 0 {
|
||||
mod = mod.WhereBetween(cols.Price, in.Price[0], in.Price[1])
|
||||
} else if in.Price[0] > 0 && in.Price[1] == 0 {
|
||||
mod = mod.WhereGTE(cols.Price, in.Price[0])
|
||||
} else if in.Price[0] == 0 && in.Price[1] > 0 {
|
||||
mod = mod.WhereLTE(cols.Price, in.Price[1])
|
||||
}
|
||||
}
|
||||
|
||||
if in.ActivityAt != nil {
|
||||
mod = mod.Where(cols.ActivityAt, in.ActivityAt)
|
||||
}
|
||||
|
||||
if len(in.CreatedAt) == 2 {
|
||||
mod = mod.WhereBetween(cols.CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
|
||||
}
|
||||
|
||||
if !in.Flag.IsNil() {
|
||||
mod = mod.Where(fmt.Sprintf(`JSON_CONTAINS(%s,'%v')`, cols.Flag, in.Flag))
|
||||
}
|
||||
|
||||
if !in.Hobby.IsNil() {
|
||||
mod = mod.Where(fmt.Sprintf(`JSON_CONTAINS(%s,'%v')`, cols.Hobby, in.Hobby))
|
||||
}
|
||||
|
||||
totalCount, err = mod.Clone().Count(1)
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "获取表格数据行失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
|
||||
if totalCount == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
if err = mod.Fields(sysin.TableListModel{}).Page(in.Page, in.PerPage).Handler(handler.Sorter(in)).Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, "获取表格列表失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Edit 修改/新增
|
||||
func (s *sSysTreeTable) Edit(ctx context.Context, in *sysin.TableEditInp) (err error) {
|
||||
cols := dao.AddonHgexampleTable.Columns()
|
||||
if err = hgorm.IsUnique(ctx, &dao.AddonHgexampleTable, g.Map{cols.Qq: in.Qq}, "QQ号码已存在,请换一个", in.Id); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
in.Pid, in.Level, in.Tree, err = hgorm.AutoUpdateTree(ctx, &dao.AddonHgexampleTable, in.Id, in.Pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if in.Id > 0 {
|
||||
in.UpdatedBy = contexts.GetUserId(ctx)
|
||||
if _, err = s.Model(ctx).WherePri(in.Id).Data(in).Update(); err != nil {
|
||||
err = gerror.Wrap(err, "修改表格失败,请稍后重试!")
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
in.CreatedBy = contexts.GetUserId(ctx)
|
||||
if _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).Data(in).Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增表格失败,请稍后重试!")
|
||||
return err
|
||||
}
|
||||
}
|
||||
return
|
||||
})
|
||||
}
|
||||
|
||||
// Delete 删除
|
||||
func (s *sSysTreeTable) Delete(ctx context.Context, in *sysin.TableDeleteInp) (err error) {
|
||||
count, err := dao.AdminMenu.Ctx(ctx).Where("pid", in.Id).Count()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
return gerror.New("请先删除该表格下的所有下级!")
|
||||
}
|
||||
|
||||
if _, err = s.Model(ctx).WherePri(in.Id).Delete(); err != nil {
|
||||
err = gerror.Wrap(err, "删除表格失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// Select 关系树选项列表
|
||||
func (s *sSysTreeTable) Select(ctx context.Context) (list []*sysin.TableTree, err error) {
|
||||
var models []*entity.AddonHgexampleTable
|
||||
if err = dao.AddonHgexampleTable.Ctx(ctx).Order("pid asc,id asc,sort asc").Scan(&models); err != nil {
|
||||
err = gerror.Wrap(err, "获取关系树选项列表失败!")
|
||||
return
|
||||
}
|
||||
|
||||
list = s.treeList(0, models)
|
||||
return
|
||||
}
|
||||
|
||||
// treeList 树状列表
|
||||
func (s *sSysTreeTable) treeList(pid int64, nodes []*entity.AddonHgexampleTable) (list []*sysin.TableTree) {
|
||||
list = make([]*sysin.TableTree, 0)
|
||||
for _, v := range nodes {
|
||||
if v.Pid == pid {
|
||||
item := new(sysin.TableTree)
|
||||
item.AddonHgexampleTable = *v
|
||||
item.Label = v.Title
|
||||
item.Value = v.Id
|
||||
item.Key = v.Id
|
||||
|
||||
child := s.treeList(v.Id, nodes)
|
||||
if len(child) > 0 {
|
||||
item.Children = child
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
47
server/addons/hgexample/model/input/sysin/tree_table.go
Normal file
47
server/addons/hgexample/model/input/sysin/tree_table.go
Normal file
@ -0,0 +1,47 @@
|
||||
// Package sysin
|
||||
// @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 sysin
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/form"
|
||||
)
|
||||
|
||||
// TreeTableListInp 获取列表
|
||||
type TreeTableListInp struct {
|
||||
form.PageReq
|
||||
form.Sorters
|
||||
Id int64 `json:"id" description:""`
|
||||
Flag *gjson.Json `json:"flag" description:"标签"`
|
||||
Title string `json:"title" description:"标题"`
|
||||
Content string `json:"content" description:"内容"`
|
||||
Price []float64 `json:"price" description:"价格"`
|
||||
ActivityAt *gtime.Time `json:"activityAt" description:"活动时间"`
|
||||
Switch int `json:"switch" description:"开关"`
|
||||
Hobby *gjson.Json `json:"hobby" description:"爱好"`
|
||||
Status int `json:"status" description:"状态"`
|
||||
CreatedAt []*gtime.Time `json:"createdAt" description:"创建时间"`
|
||||
Pid int64 `json:"pid" description:"上级ID"`
|
||||
}
|
||||
|
||||
type TreeTableListModel struct {
|
||||
entity.AddonHgexampleTable
|
||||
TableCategoryName string `json:"TableCategoryName" description:"分类名称"`
|
||||
TableCategoryDescription string `json:"TableCategoryDescription" description:"分类描述"`
|
||||
TableCategoryRemark string `json:"TableCategoryRemark" description:"分类备注"`
|
||||
SysProvincesTitle string `json:"sysProvincesTitle" description:""`
|
||||
}
|
||||
|
||||
// TableTree 树
|
||||
type TableTree struct {
|
||||
entity.AddonHgexampleTable
|
||||
Key int64 `json:"key" dc:"key"`
|
||||
Label string `json:"label" dc:"标签"`
|
||||
Value int64 `json:"value" dc:"键值"`
|
||||
Children []*TableTree `json:"children"`
|
||||
}
|
@ -1 +1 @@
|
||||
Hello!这是创建插件 [功能案例] 时默认生成的一个静态目录文件,用于测试,当你看到这个提示时,说明已经联调成功啦!
|
||||
Hello!这是创建插件 [功能案例] 时默认生成的一个静态目录文件,用于测试,当你看到这个提示时,说明已经联调成功啦!
|
||||
|
@ -26,6 +26,7 @@ func Admin(ctx context.Context, group *ghttp.RouterGroup) {
|
||||
group.Bind(
|
||||
sys.Config,
|
||||
sys.Table,
|
||||
sys.TreeTable,
|
||||
)
|
||||
})
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
// ================================================================================
|
||||
// Code generated by GoFrame CLI tool. DO NOT EDIT.
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
@ -16,30 +16,56 @@ import (
|
||||
|
||||
type (
|
||||
ISysConfig interface {
|
||||
// GetBasic 获取基础配置
|
||||
GetBasic(ctx context.Context) (conf *model.BasicConfig, err error)
|
||||
// GetConfigByGroup 获取指定分组配置
|
||||
GetConfigByGroup(ctx context.Context, in *sysin.GetConfigInp) (res *sysin.GetConfigModel, err error)
|
||||
// UpdateConfigByGroup 更新指定分组的配置
|
||||
UpdateConfigByGroup(ctx context.Context, in *sysin.UpdateConfigInp) error
|
||||
}
|
||||
ISysIndex interface {
|
||||
// Test 测试
|
||||
Test(ctx context.Context, in *sysin.IndexTestInp) (res *sysin.IndexTestModel, err error)
|
||||
}
|
||||
ISysTable interface {
|
||||
// Model Orm模型
|
||||
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
|
||||
// List 获取列表
|
||||
List(ctx context.Context, in *sysin.TableListInp) (list []*sysin.TableListModel, totalCount int, err error)
|
||||
// Export 导出
|
||||
Export(ctx context.Context, in *sysin.TableListInp) (err error)
|
||||
// Edit 修改/新增
|
||||
Edit(ctx context.Context, in *sysin.TableEditInp) (err error)
|
||||
// Delete 删除
|
||||
Delete(ctx context.Context, in *sysin.TableDeleteInp) (err error)
|
||||
// Status 更新状态
|
||||
Status(ctx context.Context, in *sysin.TableStatusInp) (err error)
|
||||
// Switch 更新开关状态
|
||||
Switch(ctx context.Context, in *sysin.TableSwitchInp) (err error)
|
||||
// MaxSort 最大排序
|
||||
MaxSort(ctx context.Context, in *sysin.TableMaxSortInp) (res *sysin.TableMaxSortModel, err error)
|
||||
// View 获取指定信息
|
||||
View(ctx context.Context, in *sysin.TableViewInp) (res *sysin.TableViewModel, err error)
|
||||
}
|
||||
ISysTreeTable interface {
|
||||
// Model Orm模型
|
||||
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
|
||||
// List 获取列表
|
||||
List(ctx context.Context, in *sysin.TreeTableListInp) (list []*sysin.TreeTableListModel, totalCount int, err error)
|
||||
// Edit 修改/新增
|
||||
Edit(ctx context.Context, in *sysin.TableEditInp) (err error)
|
||||
// Delete 删除
|
||||
Delete(ctx context.Context, in *sysin.TableDeleteInp) (err error)
|
||||
// Select 关系树选项列表
|
||||
Select(ctx context.Context) (list []*sysin.TableTree, err error)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localSysConfig ISysConfig
|
||||
localSysIndex ISysIndex
|
||||
localSysTable ISysTable
|
||||
localSysConfig ISysConfig
|
||||
localSysIndex ISysIndex
|
||||
localSysTable ISysTable
|
||||
localSysTreeTable ISysTreeTable
|
||||
)
|
||||
|
||||
func SysConfig() ISysConfig {
|
||||
@ -74,3 +100,14 @@ func SysTable() ISysTable {
|
||||
func RegisterSysTable(i ISysTable) {
|
||||
localSysTable = i
|
||||
}
|
||||
|
||||
func SysTreeTable() ISysTreeTable {
|
||||
if localSysTreeTable == nil {
|
||||
panic("implement not found for interface ISysTreeTable, forgot register?")
|
||||
}
|
||||
return localSysTreeTable
|
||||
}
|
||||
|
||||
func RegisterSysTreeTable(i ISysTreeTable) {
|
||||
localSysTreeTable = i
|
||||
}
|
||||
|
@ -67,6 +67,7 @@ type SiteConfigRes struct {
|
||||
Version string `json:"version" dc:"系统版本"`
|
||||
WsAddr string `json:"wsAddr" dc:"客户端websocket地址"`
|
||||
Domain string `json:"domain" dc:"对外域名"`
|
||||
Mode string `json:"mode" dc:"运行模式"`
|
||||
}
|
||||
|
||||
// SiteLoginConfigReq 获取登录配置
|
||||
|
@ -81,3 +81,13 @@ type OnlineExecReq struct {
|
||||
type OnlineExecRes struct {
|
||||
*sysin.OnlineExecModel
|
||||
}
|
||||
|
||||
// DispatchLogReq 调度日志
|
||||
type DispatchLogReq struct {
|
||||
g.Meta `path:"/cron/dispatchLog" method:"post" tags:"定时任务" summary:"调度日志"`
|
||||
sysin.DispatchLogInp
|
||||
}
|
||||
|
||||
type DispatchLogRes struct {
|
||||
*sysin.DispatchLogModel
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// @Copyright Copyright (c) 2023 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
// @AutoGenerate Version 2.9.3
|
||||
// @AutoGenerate Version 2.11.5
|
||||
package curddemo
|
||||
|
||||
import (
|
||||
|
@ -45,3 +45,13 @@ type CronOnlineExecReq struct {
|
||||
type CronOnlineExecRes struct {
|
||||
tcp.ServerRes
|
||||
}
|
||||
|
||||
// CronDispatchLogReq 调度日志
|
||||
type CronDispatchLogReq struct {
|
||||
*sysin.DispatchLogInp
|
||||
}
|
||||
|
||||
type CronDispatchLogRes struct {
|
||||
tcp.ServerRes
|
||||
*sysin.DispatchLogModel
|
||||
}
|
||||
|
@ -13,13 +13,14 @@ require (
|
||||
github.com/casbin/casbin/v2 v2.55.0
|
||||
github.com/forgoer/openssl v1.4.0
|
||||
github.com/go-pay/gopay v1.5.91
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.5
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.5
|
||||
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.5
|
||||
github.com/gogf/gf/v2 v2.5.5
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.7
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.7
|
||||
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.7
|
||||
github.com/gogf/gf/v2 v2.5.7
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/gorilla/websocket v1.5.1
|
||||
github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794
|
||||
github.com/minio/minio-go/v7 v7.0.63
|
||||
github.com/minio/selfupdate v0.6.0
|
||||
github.com/mojocn/base64Captcha v1.3.5
|
||||
github.com/olekukonko/tablewriter v0.0.5
|
||||
@ -28,10 +29,10 @@ require (
|
||||
github.com/silenceper/wechat/v2 v2.1.4
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.633
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.633
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.41
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.45
|
||||
github.com/ufilesdk-dev/ufile-gosdk v1.0.3
|
||||
github.com/xuri/excelize/v2 v2.6.0
|
||||
go.opentelemetry.io/otel v1.19.0
|
||||
go.opentelemetry.io/otel v1.21.0
|
||||
golang.org/x/mod v0.9.0
|
||||
golang.org/x/tools v0.7.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
@ -54,14 +55,15 @@ require (
|
||||
github.com/clbanning/mxj/v2 v2.7.0 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/eapache/go-resiliency v1.2.0 // indirect
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 // indirect
|
||||
github.com/eapache/queue v1.1.0 // indirect
|
||||
github.com/emirpasic/gods v1.12.0 // indirect
|
||||
github.com/fatih/color v1.15.0 // indirect
|
||||
github.com/fatih/color v1.16.0 // indirect
|
||||
github.com/fatih/structs v1.1.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/go-logr/logr v1.2.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-logr/logr v1.3.0 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||
github.com/go-redis/redis/v8 v8.11.5 // indirect
|
||||
@ -72,7 +74,7 @@ require (
|
||||
github.com/google/btree v1.1.2 // indirect
|
||||
github.com/google/go-querystring v1.0.0 // indirect
|
||||
github.com/google/uuid v1.3.0 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 // indirect
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/go-uuid v1.0.2 // indirect
|
||||
@ -82,27 +84,31 @@ require (
|
||||
github.com/jcmturner/gokrb5/v8 v8.4.2 // indirect
|
||||
github.com/jcmturner/rpc/v2 v2.0.3 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.15.6 // indirect
|
||||
github.com/klauspost/compress v1.17.2 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
||||
github.com/magiconair/properties v1.8.7 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
github.com/minio/sha256-simd v1.0.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.4.3 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/mozillazg/go-httpheader v0.2.1 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.14 // indirect
|
||||
github.com/pierrec/lz4/v4 v4.1.18 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 // indirect
|
||||
github.com/redis/go-redis/v9 v9.2.1 // indirect
|
||||
github.com/redis/go-redis/v9 v9.3.0 // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.1 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/rs/xid v1.5.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.4 // indirect
|
||||
github.com/sirupsen/logrus v1.9.0 // indirect
|
||||
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||
github.com/spf13/cast v1.4.1 // indirect
|
||||
github.com/tidwall/gjson v1.14.1 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
@ -114,17 +120,17 @@ require (
|
||||
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.19.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.21.0 // indirect
|
||||
go.uber.org/atomic v1.7.0 // indirect
|
||||
golang.org/x/crypto v0.14.0 // indirect
|
||||
golang.org/x/crypto v0.15.0 // indirect
|
||||
golang.org/x/image v0.1.0 // indirect
|
||||
golang.org/x/net v0.17.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sync v0.1.0 // indirect
|
||||
golang.org/x/sys v0.13.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/sys v0.14.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
|
||||
gopkg.in/ini.v1 v1.56.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
stathat.com/c/consistent v1.0.0 // indirect
|
||||
)
|
||||
|
110
server/go.sum
110
server/go.sum
@ -111,8 +111,11 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||
github.com/eapache/go-resiliency v1.2.0 h1:v7g92e/KSN71Rq7vSThKaWIq68fL4YHvWyiUKorFR1Q=
|
||||
github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
|
||||
github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21 h1:YEetp8/yCZMuEPMUDHG0CW/brkkEp8mzqk2+ODEitlw=
|
||||
@ -125,8 +128,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/fatih/color v1.15.0 h1:kOqh6YHBtK8aywxGerMG2Eq3H6Qgoqeo13Bk2Mv/nBs=
|
||||
github.com/fatih/color v1.15.0/go.mod h1:0h5ZqXfHYED7Bhv2ZJamyIOUej9KtShiJESRwBDUSsw=
|
||||
github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM=
|
||||
github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE=
|
||||
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
|
||||
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
|
||||
github.com/forgoer/openssl v1.4.0 h1:rPMnQ92OKuBsKnfY/GmUDunnP72Cy+zviAompWMdC9U=
|
||||
@ -135,8 +138,8 @@ github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8
|
||||
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=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||
@ -147,8 +150,8 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
|
||||
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
|
||||
github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
|
||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||
@ -167,14 +170,14 @@ github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrt
|
||||
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
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.5.5 h1:P1dJmEhyEVVkSXbeP8ge2jxA2lZrch2cZCSOxgTT0X8=
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.5/go.mod h1:R6tDeHWP3kpApZtOrVbj/tP7dtwcFHmhFFqnIlQh+yU=
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.5 h1:c8cv5EQdGHFYAms+7DCHg5p1LLrP2au1eMmfPcuB79o=
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.5/go.mod h1:2aENeWXI1LRl1cmGmByEn12FlfC2t5PchYvNUTHRIJs=
|
||||
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.5 h1:T9ZQoCqJJq6dIPaTMSuftjtXR7rs3crpPrXjCG+3xZg=
|
||||
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.5/go.mod h1:9Xw3ULCwXc7EO0ZpXAEq7ghJm6O0jc3J/fOLBCzeiZU=
|
||||
github.com/gogf/gf/v2 v2.5.5 h1:av3xMltrJiZWs4lW5KUTTDh45qg3wUV33W5OebE+pYo=
|
||||
github.com/gogf/gf/v2 v2.5.5/go.mod h1:17K/gBYrp0bHGC3XYC7bSPoywmZ6MrZHrZakTfh4eIQ=
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.7 h1:S6r4QJSoqmOv/Vqhu/gHt4if4dHrNyaQIUbjWc4W7sg=
|
||||
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.5.7/go.mod h1:1/X4iVHxtSHjOMGYvnmFMTdk5zLLhQ6PEkslKTBcTSI=
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.7 h1:HgOudyYp8F6iVC6YgbqKhPMKgxQJj4MO8VBdJEMPTpk=
|
||||
github.com/gogf/gf/contrib/nosql/redis/v2 v2.5.7/go.mod h1:jiRz86SerTb+z4KD4LtxgVw3IEcsWRBnL40FvIAg/sY=
|
||||
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.7 h1:ipIYW9q+Olkg9s86WpdPQ+wTFi1v6rsTiYAZ2ekqxH8=
|
||||
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.5.7/go.mod h1:KhUqGtEifCUd9pI274UkgSCMByof3aq2nW9GJRbwcOk=
|
||||
github.com/gogf/gf/v2 v2.5.7 h1:h+JSoD6z3d2q0uGszvtahrSm4DiM2ECyNjyTwKIo8wE=
|
||||
github.com/gogf/gf/v2 v2.5.7/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
|
||||
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
@ -225,8 +228,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||
@ -252,10 +255,10 @@ github.com/gopherjs/gopherjs v0.0.0-20200217142428-fce0ec30dd00/go.mod h1:wJfORR
|
||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
|
||||
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
github.com/grokify/html-strip-tags-go v0.0.1 h1:0fThFwLbW7P/kOiTBs03FsJSV9RM2M/Q/MOnCQxKMo0=
|
||||
github.com/grokify/html-strip-tags-go v0.0.1/go.mod h1:2Su6romC5/1VXOQMaWL2yb618ARB8iVo6/DR99A6d78=
|
||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0 h1:03UrQLjAny8xci+R+qjCce/MYnpNXCtgzltlQbOBae4=
|
||||
github.com/grokify/html-strip-tags-go v0.1.0/go.mod h1:ZdzgfHEzAfz9X6Xe5eBLVblWIxXfYSQ40S/VKrAOGpc=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
|
||||
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
|
||||
github.com/hashicorp/errwrap v1.0.0 h1:hLrqtEDnRye3+sgx6z4qVLNuviH3MR5aQ0ykNJa/UYA=
|
||||
@ -297,8 +300,12 @@ github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8
|
||||
github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794 h1:dWJxw+KQOMeVcoyxqG9I5fppPld1hh1FG8ngv0fKNsQ=
|
||||
github.com/kayon/iploc v0.0.0-20200312105652-bda3e968a794/go.mod h1:IwrOeG3O3K9vVXmcVvc9T0XLabw67QePi5pKQt5U+Kw=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY=
|
||||
github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU=
|
||||
github.com/klauspost/compress v1.17.2 h1:RlWWUY/Dr4fL8qk9YG7DTZ7PDgME2V4csBXA8L/ixi4=
|
||||
github.com/klauspost/compress v1.17.2/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
@ -324,8 +331,14 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/minio/md5-simd v1.1.2 h1:Gdi1DZK69+ZVMoNHRXJyNcxrMA4dSxoYHZSQbirFg34=
|
||||
github.com/minio/md5-simd v1.1.2/go.mod h1:MzdKDxYpY2BT9XQFocsiZf/NKVtR7nkE4RoEpN+20RM=
|
||||
github.com/minio/minio-go/v7 v7.0.63 h1:GbZ2oCvaUdgT5640WJOpyDhhDxvknAJU2/T3yurwcbQ=
|
||||
github.com/minio/minio-go/v7 v7.0.63/go.mod h1:Q6X7Qjb7WMhvG65qKf4gUgA5XaiSox74kR1uAEjxRS4=
|
||||
github.com/minio/selfupdate v0.6.0 h1:i76PgT0K5xO9+hjzKcacQtO7+MjJ4JKA8Ak8XQ9DDwU=
|
||||
github.com/minio/selfupdate v0.6.0/go.mod h1:bO02GTIPCMQFTEvE5h4DjYB58bCoZ35XLeBf0buTDdM=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
|
||||
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||
@ -361,8 +374,9 @@ github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1y
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
|
||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
|
||||
github.com/pierrec/lz4/v4 v4.1.14 h1:+fL8AQEZtz/ijeNnpduH0bROTu0O3NZAlPjQxGn8LwE=
|
||||
github.com/pierrec/lz4/v4 v4.1.14/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
@ -396,8 +410,8 @@ github.com/qiniu/go-sdk/v7 v7.14.0/go.mod h1:btsaOc8CA3hdVloULfFdDgDc+g4f3TDZEFs
|
||||
github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/redis/go-redis/v9 v9.2.1 h1:WlYJg71ODF0dVspZZCpYmoF1+U1Jjk9Rwd7pq6QmlCg=
|
||||
github.com/redis/go-redis/v9 v9.2.1/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/redis/go-redis/v9 v9.3.0 h1:RiVDjmig62jIWp7Kk4XVLs0hzV6pI3PyTnnL0cnn0u0=
|
||||
github.com/redis/go-redis/v9 v9.3.0/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1 h1:RfrALnSNXzmXLbGct/P2b4xkFz4e8Gmj/0Vj9M9xC1o=
|
||||
@ -409,6 +423,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shirou/gopsutil/v3 v3.23.3 h1:Syt5vVZXUDXPEXpIBt5ziWsJ4LdSAAxF4l/xZeQgSEE=
|
||||
github.com/shirou/gopsutil/v3 v3.23.3/go.mod h1:lSBNN6t3+D6W5e5nXTxc8KIMMVxAcS+6IJlffjRRlMU=
|
||||
@ -424,8 +440,9 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
|
||||
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/assertions v1.1.0 h1:MkTeG1DMwsrdH7QtLXy5W+fUxWq+vmb6cLmyJ7aRtF0=
|
||||
github.com/smartystreets/assertions v1.1.0/go.mod h1:tcbTF8ujkAEcZ8TElKY+i30BzYlVhC/LOxJk7iOWnoo=
|
||||
@ -450,14 +467,14 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.194/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.563/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.633 h1:Yj8s35IjbgaHp4Ic9BZLVGWdN2gXBMtwYi1JJ+qYbrc=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.633/go.mod h1:7sCQWVkxcsR38nffDW057DRGk8mUjK1Ing/EFOK8s8Y=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.194/go.mod h1:yrBKWhChnDqNz1xuXdSbWXG56XawEq0G5j1lg4VwBD4=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/kms v1.0.563/go.mod h1:uom4Nvi9W+Qkom0exYiJ9VWJjXwyxtPYTkKkaLMlfE0=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.633 h1:rtgRqgZNwDD665V02y2WBtZdVc/OmMNta3CAWgcGiS8=
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.633/go.mod h1:9q29WcGkZ7R0uQjoY10Tzb8A18C2cNggbq2ZC2HRXZE=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.41 h1:iU0Li/Np78H4SBna0ECQoF3mpgi6ImLXU+doGzPFXGc=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.41/go.mod h1:4dCEtLHGh8QPxHEkgq+nFaky7yZxQuYwgSJM87icDaw=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.45 h1:5/ZGOv846tP6+2X7w//8QjLgH2KcUK+HciFbfjWquFU=
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.45/go.mod h1:DH9US8nB+AJXqwu/AMOrCFN1COv3dpytXuJWHgdg7kE=
|
||||
github.com/tidwall/gjson v1.2.1/go.mod h1:c/nTNbUr0E0OrXEhq1pwa8iEgc2DOt4ZZqAt1HtCkPA=
|
||||
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
|
||||
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
@ -499,16 +516,16 @@ go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
|
||||
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
|
||||
go.opentelemetry.io/otel v1.19.0 h1:MuS/TNf4/j4IXsZuJegVzI1cwut7Qc00344rgH7p8bs=
|
||||
go.opentelemetry.io/otel v1.19.0/go.mod h1:i0QyjOq3UPoTzff0PJB2N66fb4S0+rSbSB15/oyH9fY=
|
||||
go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc=
|
||||
go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo=
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0 h1:D7UpUy2Xc2wsi1Ras6V40q806WM07rqoCWzXu7Sqy+4=
|
||||
go.opentelemetry.io/otel/exporters/jaeger v1.17.0/go.mod h1:nPCqOnEH9rNLKqH/+rrUjiMzHJdV1BlpKcTwRTyKkKI=
|
||||
go.opentelemetry.io/otel/metric v1.19.0 h1:aTzpGtV0ar9wlV4Sna9sdJyII5jTVJEvKETPiOKwvpE=
|
||||
go.opentelemetry.io/otel/metric v1.19.0/go.mod h1:L5rUsV9kM1IxCj1MmSdS+JQAcVm319EUrDVLrt7jqt8=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o=
|
||||
go.opentelemetry.io/otel/sdk v1.19.0/go.mod h1:NedEbbS4w3C6zElbLdPJKOpJQOrGUJ+GfzpjUvI0v1A=
|
||||
go.opentelemetry.io/otel/trace v1.19.0 h1:DFVQmlVbfVeOuBRrwdtaehRrWiL1JoVs9CPIQ1Dzxpg=
|
||||
go.opentelemetry.io/otel/trace v1.19.0/go.mod h1:mfaSyvGyEJEI0nyV2I4qhNQnbBOUUmYZpYojqMnX2vo=
|
||||
go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4=
|
||||
go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0 h1:FTt8qirL1EysG6sTQRZ5TokkU8d0ugCj8htOgThZXQ8=
|
||||
go.opentelemetry.io/otel/sdk v1.21.0/go.mod h1:Nna6Yv7PWTdgJHVRD9hIYywQBRx7pbox6nwBnZIxl/E=
|
||||
go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc=
|
||||
go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ=
|
||||
go.uber.org/atomic v1.5.1/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
|
||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
||||
@ -528,8 +545,8 @@ golang.org/x/crypto v0.0.0-20211209193657-4570a0811e8b/go.mod h1:IxCIyHEi3zRg3s0
|
||||
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220408190544-5352b0902921/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc=
|
||||
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@ -607,8 +624,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
|
||||
golang.org/x/net v0.0.0-20220407224826-aac1ed45d8e3/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220520000938-2e3eb7b945c2/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM=
|
||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
@ -686,11 +703,11 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE=
|
||||
golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
@ -702,8 +719,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 h1:/5xXl8Y5W96D+TtHSlonuFqGHIWVuyCkGJLwGh9JJFs=
|
||||
@ -846,8 +863,9 @@ gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
|
||||
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
|
||||
gopkg.in/ini.v1 v1.56.0 h1:DPMeDvGTM54DXbPkVIZsp19fp/I2K7zwA/itHYHKo8Y=
|
||||
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
@ -36,7 +36,9 @@ var (
|
||||
---------------------------------------------------------------------------------
|
||||
工具
|
||||
>> 释放casbin权限,用于清理无效的权限设置 [go run main.go tools -m=casbin -a1=refresh]
|
||||
|
||||
---------------------------------------------------------------------------------
|
||||
升级更新
|
||||
>> 修复菜单关系树 [go run main.go up -m=fix -a1=menuTree]
|
||||
---------------------------------------------------------------------------------
|
||||
更多
|
||||
github地址:https://github.com/bufanyun/hotgo
|
||||
@ -76,7 +78,7 @@ var (
|
||||
)
|
||||
|
||||
func init() {
|
||||
if err := Main.AddCommand(All, Http, Queue, Cron, Auth, Tools, Help); err != nil {
|
||||
if err := Main.AddCommand(All, Http, Queue, Cron, Auth, Tools, Up, Help); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"github.com/gogf/gf/v2/util/gmode"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/addons"
|
||||
"hotgo/internal/library/casbin"
|
||||
@ -79,7 +80,9 @@ var (
|
||||
casbin.InitEnforcer(ctx)
|
||||
|
||||
// 初始化生成代码配置
|
||||
hggen.InIt(ctx)
|
||||
if !gmode.IsProduct() {
|
||||
hggen.InIt(ctx)
|
||||
}
|
||||
|
||||
// 启动tcp服务
|
||||
service.TCPServer().Start(ctx)
|
||||
|
65
server/internal/cmd/up.go
Normal file
65
server/internal/cmd/up.go
Normal file
@ -0,0 +1,65 @@
|
||||
// Package cmd
|
||||
// @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 cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcmd"
|
||||
"hotgo/internal/cmd/upgrade/fix"
|
||||
)
|
||||
|
||||
var (
|
||||
Up = &gcmd.Command{
|
||||
Name: "up",
|
||||
Brief: "处理hotgo版本升级更新带来的兼容问题",
|
||||
Description: ``,
|
||||
Func: func(ctx context.Context, parser *gcmd.Parser) (err error) {
|
||||
args := parser.GetOptAll()
|
||||
g.Log().Debugf(ctx, "up args:%v", args)
|
||||
if len(args) == 0 {
|
||||
err = gerror.New("up args cannot be empty.")
|
||||
return
|
||||
}
|
||||
|
||||
method, ok := args["m"]
|
||||
if !ok {
|
||||
err = gerror.New("up method cannot be empty.")
|
||||
return
|
||||
}
|
||||
|
||||
switch method {
|
||||
case "fix":
|
||||
err = handleUpgradeFix(ctx, args)
|
||||
default:
|
||||
err = gerror.Newf("up method[%v] does not exist", method)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
g.Log().Info(ctx, "up exec successful!")
|
||||
}
|
||||
return
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// handleUpgradeFix 处理修复脚本
|
||||
func handleUpgradeFix(ctx context.Context, args map[string]string) (err error) {
|
||||
a1, ok := args["a1"]
|
||||
if !ok {
|
||||
err = gerror.New("fix args cannot be empty.")
|
||||
return
|
||||
}
|
||||
|
||||
switch a1 {
|
||||
case "menuTree":
|
||||
fix.UpdateAdminMenuTree(ctx)
|
||||
default:
|
||||
err = gerror.Newf("fix a1 is invalid, a1:%v", a1)
|
||||
}
|
||||
return
|
||||
}
|
48
server/internal/cmd/upgrade/fix/admin_menu_tree.go
Normal file
48
server/internal/cmd/upgrade/fix/admin_menu_tree.go
Normal file
@ -0,0 +1,48 @@
|
||||
// Package fix
|
||||
// @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 fix
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/hgorm"
|
||||
"hotgo/internal/model/entity"
|
||||
)
|
||||
|
||||
// UpdateAdminMenuTree 更新菜单关系树
|
||||
// 根据树等级从上到下依次检查,将无效的关系树进行修复更新
|
||||
func UpdateAdminMenuTree(ctx context.Context) {
|
||||
var list []*entity.AdminMenu
|
||||
err := dao.AdminMenu.Ctx(ctx).OrderAsc("level").Scan(&list)
|
||||
if err != nil {
|
||||
g.Log().Fatal(ctx, err)
|
||||
}
|
||||
|
||||
genUpdateData := func(v *entity.AdminMenu) g.Map {
|
||||
update := g.Map{"updated_at": gtime.Now()}
|
||||
if v.Pid <= 0 {
|
||||
update["level"] = 1
|
||||
update["tree"] = ""
|
||||
return update
|
||||
}
|
||||
|
||||
// 生成下级关系树
|
||||
update["pid"], update["level"], update["tree"], err = hgorm.GenSubTree(ctx, &dao.AdminMenu, v.Pid)
|
||||
return update
|
||||
}
|
||||
|
||||
for _, v := range list {
|
||||
update := genUpdateData(v)
|
||||
if v.Level == update["level"] && v.Tree == update["tree"] {
|
||||
continue
|
||||
}
|
||||
if _, err = dao.AdminMenu.Ctx(ctx).WherePri(v.Id).Data(genUpdateData(v)).Update(); err != nil {
|
||||
g.Log().Fatal(ctx, err)
|
||||
}
|
||||
}
|
||||
}
|
@ -10,5 +10,6 @@ type CtxKey string
|
||||
// ContextKey 上下文
|
||||
const (
|
||||
ContextHTTPKey CtxKey = "httpContext" // http上下文变量名称
|
||||
ContextKeyCronArgs CtxKey = "cronArgs" // 定时任务参数上下文变量名称
|
||||
ContextKeyCronArgs CtxKey = "cronArgs" // 定时任务参数
|
||||
ContextKeyCronSn CtxKey = "cronSn" // 定时任务序列号
|
||||
)
|
||||
|
@ -12,4 +12,5 @@ const (
|
||||
UploadDriveCos = "cos" // 腾讯云cos
|
||||
UploadDriveOss = "oss" // 阿里云oss
|
||||
UploadDriveQiNiu = "qiniu" // 七牛云对象存储
|
||||
UploadDriveMinio = "minio" // minio
|
||||
)
|
||||
|
@ -7,5 +7,5 @@ package consts
|
||||
|
||||
// VersionApp HotGo版本
|
||||
const (
|
||||
VersionApp = "2.9.8"
|
||||
VersionApp = "2.11.5"
|
||||
)
|
||||
|
@ -8,9 +8,11 @@ package common
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/gmode"
|
||||
"hotgo/api/admin/common"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/captcha"
|
||||
@ -35,6 +37,7 @@ func (c *cSite) Config(ctx context.Context, _ *common.SiteConfigReq) (res *commo
|
||||
Version: consts.VersionApp,
|
||||
WsAddr: c.getWsAddr(ctx, request),
|
||||
Domain: c.getDomain(ctx, request),
|
||||
Mode: gmode.Mode(),
|
||||
}
|
||||
return
|
||||
}
|
||||
@ -43,7 +46,7 @@ func (c *cSite) getWsAddr(ctx context.Context, request *ghttp.Request) string {
|
||||
// 如果是本地IP访问,则认为是调试模式,走实际请求地址,否则走配置中的地址
|
||||
ip := ghttp.RequestFromCtx(ctx).GetHeader("hostname")
|
||||
if validate.IsLocalIPAddr(ip) {
|
||||
return "ws://" + ip + ":" + gstr.StrEx(request.Host, ":") + "/socket"
|
||||
return "ws://" + ip + ":" + gstr.StrEx(request.Host, ":") + g.Cfg().MustGet(ctx, "router.websocket.prefix").String()
|
||||
}
|
||||
|
||||
basic, err := service.SysConfig().GetBasic(ctx)
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"hotgo/api/admin/cron"
|
||||
"hotgo/api/servmsg"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"hotgo/internal/service"
|
||||
)
|
||||
|
||||
@ -63,9 +64,13 @@ func (c *cCron) List(ctx context.Context, req *cron.ListReq) (res *cron.ListRes,
|
||||
return
|
||||
}
|
||||
|
||||
// Status 更新部门状态
|
||||
// Status 更新状态
|
||||
func (c *cCron) Status(ctx context.Context, req *cron.StatusReq) (res *cron.StatusRes, err error) {
|
||||
err = service.SysCron().Status(ctx, &req.CronStatusInp)
|
||||
if req.Id <= 0 {
|
||||
return nil, gerror.New("定时任务ID不能为空")
|
||||
}
|
||||
|
||||
err = service.TCPServer().CronStatus(ctx, &servmsg.CronStatusReq{CronStatusInp: &req.CronStatusInp})
|
||||
return
|
||||
}
|
||||
|
||||
@ -78,3 +83,15 @@ func (c *cCron) OnlineExec(ctx context.Context, req *cron.OnlineExecReq) (res *c
|
||||
err = service.TCPServer().CronOnlineExec(ctx, &servmsg.CronOnlineExecReq{OnlineExecInp: &req.OnlineExecInp})
|
||||
return
|
||||
}
|
||||
|
||||
// DispatchLog 调度日志
|
||||
func (c *cCron) DispatchLog(ctx context.Context, req *cron.DispatchLogReq) (res *cron.DispatchLogRes, err error) {
|
||||
if req.Id <= 0 {
|
||||
return nil, gerror.New("定时任务ID不能为空")
|
||||
}
|
||||
|
||||
res = new(cron.DispatchLogRes)
|
||||
res.DispatchLogModel = new(sysin.DispatchLogModel)
|
||||
res.Log, err = service.TCPServer().DispatchLog(ctx, &servmsg.CronDispatchLogReq{DispatchLogInp: &req.DispatchLogInp})
|
||||
return
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
// @Copyright Copyright (c) 2023 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
// @AutoGenerate Version 2.9.3
|
||||
// @AutoGenerate Version 2.11.5
|
||||
package sys
|
||||
|
||||
import (
|
||||
|
@ -31,14 +31,15 @@ func (c *cCloseOrder) GetName() string {
|
||||
}
|
||||
|
||||
// Execute 执行任务
|
||||
func (c *cCloseOrder) Execute(ctx context.Context) {
|
||||
_, err := service.AdminOrder().Model(ctx).
|
||||
func (c *cCloseOrder) Execute(ctx context.Context, parser *cron.Parser) (err error) {
|
||||
_, err = service.AdminOrder().Model(ctx).
|
||||
Where(dao.AdminOrder.Columns().Status, consts.OrderStatusNotPay).
|
||||
WhereLTE(dao.AdminOrder.Columns().CreatedAt, gtime.Now().AddDate(0, 0, -1)).
|
||||
Data(g.Map{
|
||||
dao.AdminOrder.Columns().Status: consts.OrderStatusClose,
|
||||
}).Update()
|
||||
if err != nil {
|
||||
cron.Logger().Warning(ctx, "cron CloseOrder Execute err:%+v", err)
|
||||
parser.Logger.Warning(ctx, "cron CloseOrder Execute err:%+v", err)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ func (c *cTest) GetName() string {
|
||||
}
|
||||
|
||||
// Execute 执行任务
|
||||
func (c *cTest) Execute(ctx context.Context) {
|
||||
cron.Logger().Infof(ctx, "cron test Execute:%v", time.Now())
|
||||
func (c *cTest) Execute(ctx context.Context, parser *cron.Parser) (err error) {
|
||||
parser.Logger.Infof(ctx, "cron test Execute:%v", time.Now())
|
||||
return
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ package crons
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/consts"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"hotgo/internal/library/cron"
|
||||
"time"
|
||||
)
|
||||
@ -28,22 +28,18 @@ func (c *cTest2) GetName() string {
|
||||
}
|
||||
|
||||
// Execute 执行任务
|
||||
func (c *cTest2) Execute(ctx context.Context) {
|
||||
args, ok := ctx.Value(consts.ContextKeyCronArgs).([]string)
|
||||
if !ok {
|
||||
cron.Logger().Warning(ctx, "参数解析失败!")
|
||||
return
|
||||
}
|
||||
if len(args) != 3 {
|
||||
cron.Logger().Warning(ctx, "test2 传入参数不正确!")
|
||||
func (c *cTest2) Execute(ctx context.Context, parser *cron.Parser) (err error) {
|
||||
if len(parser.Args) != 3 {
|
||||
err = gerror.New("传入参数不正确!")
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
name = args[0]
|
||||
age = args[1]
|
||||
msg = args[2]
|
||||
name = parser.Args[0]
|
||||
age = parser.Args[1]
|
||||
msg = parser.Args[2]
|
||||
)
|
||||
|
||||
cron.Logger().Infof(ctx, "cron test2 Execute:%v, name:%v, age:%v, msg:%v", time.Now(), name, age, msg)
|
||||
parser.Logger.Infof(ctx, "cron test2 Execute:%v, name:%v, age:%v, msg:%v", time.Now(), name, age, msg)
|
||||
return
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ type AdminMenuDao struct {
|
||||
type AdminMenuColumns struct {
|
||||
Id string // 菜单ID
|
||||
Pid string // 父菜单ID
|
||||
Level string // 关系树等级
|
||||
Tree string // 关系树
|
||||
Title string // 菜单名称
|
||||
Name string // 名称编码
|
||||
Path string // 路由地址
|
||||
@ -39,19 +41,19 @@ type AdminMenuColumns struct {
|
||||
KeepAlive string // 缓存该路由
|
||||
Hidden string // 是否隐藏
|
||||
Affix string // 是否固定
|
||||
Level string // 关系树等级
|
||||
Tree string // 关系树
|
||||
Sort string // 排序
|
||||
Remark string // 备注
|
||||
Status string // 菜单状态
|
||||
CreatedAt string // 创建时间
|
||||
UpdatedAt string // 更新时间
|
||||
CreatedAt string // 创建时间
|
||||
}
|
||||
|
||||
// adminMenuColumns holds the columns for table hg_admin_menu.
|
||||
var adminMenuColumns = AdminMenuColumns{
|
||||
Id: "id",
|
||||
Pid: "pid",
|
||||
Level: "level",
|
||||
Tree: "tree",
|
||||
Title: "title",
|
||||
Name: "name",
|
||||
Path: "path",
|
||||
@ -69,13 +71,11 @@ var adminMenuColumns = AdminMenuColumns{
|
||||
KeepAlive: "keep_alive",
|
||||
Hidden: "hidden",
|
||||
Affix: "affix",
|
||||
Level: "level",
|
||||
Tree: "tree",
|
||||
Sort: "sort",
|
||||
Remark: "remark",
|
||||
Status: "status",
|
||||
CreatedAt: "created_at",
|
||||
UpdatedAt: "updated_at",
|
||||
CreatedAt: "created_at",
|
||||
}
|
||||
|
||||
// NewAdminMenuDao creates and returns a new DAO object for table data access.
|
||||
|
@ -22,9 +22,10 @@ type SysCronDao struct {
|
||||
type SysCronColumns struct {
|
||||
Id string // 任务ID
|
||||
GroupId string // 分组ID
|
||||
Name string // 任务名称
|
||||
Title string // 任务标题
|
||||
Name string // 任务方法
|
||||
Params string // 函数参数
|
||||
Pattern string // 定时表达式
|
||||
Pattern string // 表达式
|
||||
Policy string // 策略
|
||||
Count string // 执行次数
|
||||
Sort string // 排序
|
||||
@ -38,6 +39,7 @@ type SysCronColumns struct {
|
||||
var sysCronColumns = SysCronColumns{
|
||||
Id: "id",
|
||||
GroupId: "group_id",
|
||||
Title: "title",
|
||||
Name: "name",
|
||||
Params: "params",
|
||||
Pattern: "pattern",
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/contrib/trace/jaeger/v2"
|
||||
"github.com/gogf/gf/v2"
|
||||
"github.com/gogf/gf/v2/container/gvar"
|
||||
"github.com/gogf/gf/v2/encoding/gjson"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
@ -17,6 +18,7 @@ import (
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gmode"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/cache"
|
||||
"hotgo/internal/library/queue"
|
||||
@ -24,13 +26,17 @@ import (
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/charset"
|
||||
"hotgo/utility/simple"
|
||||
"hotgo/utility/validate"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func Init(ctx context.Context) {
|
||||
// 设置gf运行模式
|
||||
SetGFMode(ctx)
|
||||
|
||||
// 设置服务日志处理
|
||||
g.Log().SetHandlers(LoggingServeLogHandler)
|
||||
glog.SetDefaultHandler(LoggingServeLogHandler)
|
||||
|
||||
// 默认上海时区
|
||||
if err := gtime.SetTimeZone("Asia/Shanghai"); err != nil {
|
||||
@ -69,6 +75,12 @@ func LoggingServeLogHandler(ctx context.Context, in *glog.HandlerInput) {
|
||||
}
|
||||
}()
|
||||
|
||||
// web服务日志不做记录,因为会导致重复记录
|
||||
r := g.RequestFromCtx(ctx)
|
||||
if r != nil && r.Server != nil && in.Logger.GetConfig().Path == r.Server.Logger().GetConfig().Path {
|
||||
return
|
||||
}
|
||||
|
||||
conf, err := service.SysConfig().GetLoadServeLog(ctx)
|
||||
if err != nil {
|
||||
return
|
||||
@ -90,10 +102,14 @@ func LoggingServeLogHandler(ctx context.Context, in *glog.HandlerInput) {
|
||||
in.Stack = in.Logger.GetStack()
|
||||
}
|
||||
|
||||
if len(in.Content) == 0 {
|
||||
in.Content = gstr.StrLimit(gvar.New(in.Values).String(), consts.MaxServeLogContentLen)
|
||||
}
|
||||
|
||||
var data entity.SysServeLog
|
||||
data.TraceId = gctx.CtxId(ctx)
|
||||
data.LevelFormat = in.LevelFormat
|
||||
data.Content = gstr.StrLimit(in.Content, consts.MaxServeLogContentLen)
|
||||
data.Content = in.Content
|
||||
data.Stack = gjson.New(charset.ParseStack(in.Stack))
|
||||
data.Line = strings.TrimRight(in.CallerPath, ":")
|
||||
data.TriggerNs = in.Time.UnixNano()
|
||||
@ -135,3 +151,18 @@ func InitTrace(ctx context.Context) {
|
||||
g.Log().Debug(ctx, "jaeger closed ..")
|
||||
})
|
||||
}
|
||||
|
||||
// SetGFMode 设置gf运行模式
|
||||
func SetGFMode(ctx context.Context) {
|
||||
mode := g.Cfg().MustGet(ctx, "hotgo.mode").String()
|
||||
if len(mode) == 0 {
|
||||
mode = gmode.NOT_SET
|
||||
}
|
||||
|
||||
var modes = []string{gmode.DEVELOP, gmode.TESTING, gmode.STAGING, gmode.PRODUCT}
|
||||
|
||||
// 如果是有效的运行模式,就进行设置
|
||||
if validate.InSlice(modes, mode) {
|
||||
gmode.Set(mode)
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/gres"
|
||||
"github.com/gogf/gf/v2/os/gview"
|
||||
"hotgo/internal/model/input/form"
|
||||
"sort"
|
||||
@ -157,6 +158,12 @@ func AddStaticPath(ctx context.Context, server *ghttp.Server, p ...string) {
|
||||
for _, module := range filterInstalled() {
|
||||
name := module.GetSkeleton().Name
|
||||
prefix, path := StaticPath(name, basePath)
|
||||
if !gres.Contains(path) {
|
||||
if _, err := gfile.Search(path); err != nil {
|
||||
g.Log().Warningf(ctx, `AddStaticPath failed: %v`, err)
|
||||
continue
|
||||
}
|
||||
}
|
||||
server.AddStaticPath(prefix, path)
|
||||
}
|
||||
}
|
||||
|
18
server/internal/library/cache/file/file.go
vendored
18
server/internal/library/cache/file/file.go
vendored
@ -36,6 +36,10 @@ type (
|
||||
|
||||
const perm = 0o666
|
||||
|
||||
var (
|
||||
CacheExpiredErr = errors.New("cache expired")
|
||||
)
|
||||
|
||||
// NewAdapterFile creates and returns a new memory cache object.
|
||||
func NewAdapterFile(dir string) gcache.Adapter {
|
||||
return &AdapterFile{
|
||||
@ -77,7 +81,7 @@ func (c *AdapterFile) Get(ctx context.Context, key interface{}) (*gvar.Var, erro
|
||||
|
||||
func (c *AdapterFile) GetOrSet(ctx context.Context, key interface{}, value interface{}, duration time.Duration) (result *gvar.Var, err error) {
|
||||
result, err = c.Get(ctx, key)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, CacheExpiredErr) {
|
||||
return nil, err
|
||||
}
|
||||
if result.IsNil() {
|
||||
@ -88,7 +92,7 @@ func (c *AdapterFile) GetOrSet(ctx context.Context, key interface{}, value inter
|
||||
|
||||
func (c *AdapterFile) GetOrSetFunc(ctx context.Context, key interface{}, f gcache.Func, duration time.Duration) (result *gvar.Var, err error) {
|
||||
v, err := c.Get(ctx, key)
|
||||
if err != nil {
|
||||
if err != nil && !errors.Is(err, CacheExpiredErr) {
|
||||
return nil, err
|
||||
}
|
||||
if v.IsNil() {
|
||||
@ -160,7 +164,6 @@ func (c *AdapterFile) UpdateExpire(ctx context.Context, key interface{}, duratio
|
||||
return
|
||||
}
|
||||
err = c.Set(ctx, fileKey, v.Val(), duration)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
@ -173,7 +176,6 @@ func (c *AdapterFile) GetExpire(ctx context.Context, key interface{}) (time.Dura
|
||||
if content.Duration <= time.Now().Unix() {
|
||||
return -1, nil
|
||||
}
|
||||
|
||||
return time.Duration(time.Now().Unix()-content.Duration) * time.Second, nil
|
||||
}
|
||||
|
||||
@ -202,7 +204,6 @@ func (c *AdapterFile) createName(key string) string {
|
||||
h := sha256.New()
|
||||
_, _ = h.Write([]byte(key))
|
||||
hash := hex.EncodeToString(h.Sum(nil))
|
||||
|
||||
return filepath.Join(c.dir, fmt.Sprintf("%s.cache", hash))
|
||||
}
|
||||
|
||||
@ -228,9 +229,8 @@ func (c *AdapterFile) read(key string) (*fileContent, error) {
|
||||
|
||||
if content.Duration <= time.Now().Unix() {
|
||||
_ = c.Delete(key)
|
||||
return nil, errors.New("cache expired")
|
||||
return nil, CacheExpiredErr
|
||||
}
|
||||
|
||||
return content, nil
|
||||
}
|
||||
|
||||
@ -246,7 +246,6 @@ func (c *AdapterFile) Delete(key string) error {
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return os.Remove(c.createName(key))
|
||||
}
|
||||
|
||||
@ -270,7 +269,6 @@ func (c *AdapterFile) Fetch(key string) (interface{}, error) {
|
||||
if content == nil {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
return content.Data, nil
|
||||
}
|
||||
|
||||
@ -282,7 +280,6 @@ func (c *AdapterFile) FetchMulti(keys []string) map[string]interface{} {
|
||||
result[key] = value
|
||||
}
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
@ -302,7 +299,6 @@ func (c *AdapterFile) Flush() error {
|
||||
for _, name := range names {
|
||||
_ = os.Remove(filepath.Join(c.dir, name))
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -6,36 +6,55 @@
|
||||
package cron
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gcron"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/utility/simple"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var crons = &cronManager{
|
||||
tasks: make(map[string]*TaskItem),
|
||||
tasks: make(map[string]*TaskItem),
|
||||
loggers: make(map[string]*glog.Logger),
|
||||
}
|
||||
|
||||
// Cron 定时任务接口
|
||||
type Cron interface {
|
||||
// GetName 获取任务名称
|
||||
GetName() string
|
||||
// Execute 执行一次任务
|
||||
Execute(ctx context.Context)
|
||||
// Execute 执行任务
|
||||
Execute(ctx context.Context, parser *Parser) (err error)
|
||||
}
|
||||
|
||||
// Parser 任务执行参数
|
||||
type Parser struct {
|
||||
Args []string // 任务参数
|
||||
Logger *glog.Logger // 日志管理实例
|
||||
}
|
||||
|
||||
// Log 任务调度日志
|
||||
type Log struct {
|
||||
FileName string `json:"fileName" dc:"文件名称"`
|
||||
SizeFormat string `json:"sizeFormat" dc:"文件大小"`
|
||||
Contents string `json:"contents" dc:"文件内容"`
|
||||
}
|
||||
|
||||
// consumerManager 任务管理者
|
||||
type cronManager struct {
|
||||
tasks map[string]*TaskItem
|
||||
tasks map[string]*TaskItem
|
||||
loggers map[string]*glog.Logger
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
@ -62,7 +81,8 @@ func Register(c Cron) {
|
||||
Logger().Debugf(gctx.GetInitCtx(), "cron.Register name:%v duplicate registration.", name)
|
||||
return
|
||||
}
|
||||
crons.tasks[name] = &TaskItem{Name: c.GetName(), Fun: c.Execute}
|
||||
|
||||
crons.tasks[name] = &TaskItem{Name: c.GetName(), Fun: GenExecuteFun(c.Execute)}
|
||||
}
|
||||
|
||||
// StopALL 停止所有任务
|
||||
@ -88,27 +108,29 @@ func StartALL(sysCron []*entity.SysCron) (err error) {
|
||||
return gerror.Newf("该任务没有加入任务列表:%v", cron.Name)
|
||||
}
|
||||
|
||||
sn := GenCronSn(cron)
|
||||
|
||||
// 没有则添加
|
||||
if gcron.Search(cron.Name) == nil {
|
||||
if gcron.Search(sn) == nil {
|
||||
var (
|
||||
t *gcron.Entry
|
||||
ctx = context.WithValue(gctx.New(), consts.ContextKeyCronArgs, strings.Split(cron.Params, consts.CronSplitStr))
|
||||
ctx = GenCronCtx(cron)
|
||||
)
|
||||
switch cron.Policy {
|
||||
case consts.CronPolicySame:
|
||||
t, err = gcron.Add(ctx, cron.Pattern, f.Fun, cron.Name)
|
||||
t, err = gcron.Add(ctx, cron.Pattern, f.Fun, sn)
|
||||
|
||||
case consts.CronPolicySingle:
|
||||
t, err = gcron.AddSingleton(ctx, cron.Pattern, f.Fun, cron.Name)
|
||||
t, err = gcron.AddSingleton(ctx, cron.Pattern, f.Fun, sn)
|
||||
|
||||
case consts.CronPolicyOnce:
|
||||
t, err = gcron.AddOnce(ctx, cron.Pattern, f.Fun, cron.Name)
|
||||
t, err = gcron.AddOnce(ctx, cron.Pattern, f.Fun, sn)
|
||||
|
||||
case consts.CronPolicyTimes:
|
||||
if f.Count <= 0 {
|
||||
f.Count = 1
|
||||
}
|
||||
t, err = gcron.AddTimes(ctx, cron.Pattern, int(cron.Count), f.Fun, cron.Name)
|
||||
t, err = gcron.AddTimes(ctx, cron.Pattern, int(cron.Count), f.Fun, sn)
|
||||
|
||||
default:
|
||||
return gerror.Newf("使用无效的策略, cron.Policy=%v", cron.Policy)
|
||||
@ -122,7 +144,7 @@ func StartALL(sysCron []*entity.SysCron) (err error) {
|
||||
}
|
||||
}
|
||||
|
||||
gcron.Start(cron.Name)
|
||||
gcron.Start(sn)
|
||||
|
||||
// 执行完毕,单次和多次执行的任务更新状态
|
||||
if cron.Policy == consts.CronPolicyOnce || cron.Policy == consts.CronPolicyTimes {
|
||||
@ -144,14 +166,14 @@ func RefreshStatus(sysCron *entity.SysCron) (err error) {
|
||||
}
|
||||
|
||||
if sysCron.Status == consts.StatusEnabled {
|
||||
return Start(sysCron)
|
||||
return ResetStart(sysCron)
|
||||
}
|
||||
return Stop(sysCron)
|
||||
}
|
||||
|
||||
// Stop 停止单个任务
|
||||
func Stop(sysCron *entity.SysCron) (err error) {
|
||||
cr := gcron.Search(sysCron.Name)
|
||||
cr := gcron.Search(GenCronSn(sysCron))
|
||||
if cr == nil {
|
||||
return
|
||||
}
|
||||
@ -159,6 +181,17 @@ func Stop(sysCron *entity.SysCron) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
// ResetStart 重置任务
|
||||
func ResetStart(sysCron *entity.SysCron) (err error) {
|
||||
if err = Stop(sysCron); err != nil {
|
||||
return
|
||||
}
|
||||
if err = Delete(sysCron); err != nil {
|
||||
return
|
||||
}
|
||||
return Start(sysCron)
|
||||
}
|
||||
|
||||
// Once 立即执行一次某个任务
|
||||
func Once(ctx context.Context, sysCron *entity.SysCron) error {
|
||||
crons.RLock()
|
||||
@ -167,7 +200,7 @@ func Once(ctx context.Context, sysCron *entity.SysCron) error {
|
||||
for _, v := range crons.tasks {
|
||||
if v.Name == sysCron.Name {
|
||||
simple.SafeGo(ctx, func(ctx context.Context) {
|
||||
v.Fun(ctx)
|
||||
v.Fun(GenCronCtx(sysCron))
|
||||
})
|
||||
return nil
|
||||
}
|
||||
@ -182,7 +215,7 @@ func Delete(sysCron *entity.SysCron) (err error) {
|
||||
}
|
||||
|
||||
for _, v := range gcron.Entries() {
|
||||
if v.Name == sysCron.Name {
|
||||
if v.Name == GenCronSn(sysCron) {
|
||||
gcron.Remove(v.Name)
|
||||
}
|
||||
}
|
||||
@ -195,10 +228,86 @@ func Start(sysCron *entity.SysCron) (err error) {
|
||||
return
|
||||
}
|
||||
|
||||
c := gcron.Search(sysCron.Name)
|
||||
c := gcron.Search(GenCronSn(sysCron))
|
||||
if c != nil {
|
||||
c.Start()
|
||||
return
|
||||
}
|
||||
return StartALL([]*entity.SysCron{sysCron})
|
||||
}
|
||||
|
||||
// DispatchLog 查看指定任务的调度日志
|
||||
func DispatchLog(sysCron *entity.SysCron) (log *Log, err error) {
|
||||
path := fmt.Sprintf("%v/%v", Logger().GetConfig().Path, GenCronSn(sysCron))
|
||||
file, err := FindLastModifiedFile(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(file) == 0 || !gfile.IsFile(file) {
|
||||
err = gerror.New("未找到日志!")
|
||||
return
|
||||
}
|
||||
|
||||
log = new(Log)
|
||||
log.FileName = file
|
||||
log.SizeFormat = gfile.SizeFormat(file)
|
||||
|
||||
if gfile.Size(file) > 1024*50 {
|
||||
log.Contents, err = ReadLastLines(file, 100)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
log.Contents = gfile.GetContents(file)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func ReadLastLines(filename string, lineCount int) (string, error) {
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
scanner := bufio.NewScanner(file)
|
||||
|
||||
lines := make([]string, 0, lineCount)
|
||||
for scanner.Scan() {
|
||||
lines = append(lines, scanner.Text())
|
||||
if len(lines) > lineCount {
|
||||
lines = lines[1:]
|
||||
}
|
||||
}
|
||||
|
||||
if err = scanner.Err(); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
result := strings.Join(lines, "\n")
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func FindLastModifiedFile(dirPath string) (string, error) {
|
||||
if !gfile.Exists(dirPath) {
|
||||
return "", gerror.New("该任务暂未产生日志!")
|
||||
}
|
||||
|
||||
files, err := gfile.ScanDir(dirPath, "*.log", true)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
var lastModifiedFile string
|
||||
var lastModifiedTime int64 = 0
|
||||
|
||||
for _, file := range files {
|
||||
modTime := gfile.MTimestamp(file)
|
||||
if modTime > lastModifiedTime {
|
||||
lastModifiedTime = modTime
|
||||
lastModifiedFile = file
|
||||
}
|
||||
}
|
||||
return lastModifiedFile, nil
|
||||
}
|
||||
|
86
server/internal/library/cron/cron_gen.go
Normal file
86
server/internal/library/cron/cron_gen.go
Normal file
@ -0,0 +1,86 @@
|
||||
// Package cron
|
||||
// @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 cron
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gctx"
|
||||
"github.com/gogf/gf/v2/os/glog"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/model/entity"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GenCronSn 生成任务序列号
|
||||
func GenCronSn(sysCron *entity.SysCron) string {
|
||||
return fmt.Sprintf("%s@%d", sysCron.Name, sysCron.Id)
|
||||
}
|
||||
|
||||
// GenCronCtx 生成任务上下文
|
||||
func GenCronCtx(sysCron *entity.SysCron) (ctx context.Context) {
|
||||
ctx = context.WithValue(gctx.New(), consts.ContextKeyCronArgs, strings.Split(sysCron.Params, consts.CronSplitStr))
|
||||
ctx = context.WithValue(ctx, consts.ContextKeyCronSn, GenCronSn(sysCron))
|
||||
return ctx
|
||||
}
|
||||
|
||||
func GenLoggerByCtx(ctx context.Context) *glog.Logger {
|
||||
sn, ok := ctx.Value(consts.ContextKeyCronSn).(string)
|
||||
if !ok {
|
||||
Logger().Panic(ctx, "获取定时任务序列号失败!")
|
||||
}
|
||||
|
||||
logger, ok := crons.loggers[sn]
|
||||
if ok {
|
||||
return logger
|
||||
}
|
||||
|
||||
logger = glog.New()
|
||||
if err := logger.SetConfig(Logger().GetConfig()); err != nil {
|
||||
Logger().Panic(ctx, err)
|
||||
}
|
||||
|
||||
logger.SetFlags(glog.F_TIME_STD | glog.F_FILE_SHORT)
|
||||
// 设置子路径
|
||||
if err := logger.SetPath(fmt.Sprintf("%v/%v", logger.GetPath(), sn)); err != nil {
|
||||
Logger().Panic(ctx, err)
|
||||
}
|
||||
|
||||
crons.Lock()
|
||||
defer crons.Unlock()
|
||||
crons.loggers[sn] = logger
|
||||
return logger
|
||||
}
|
||||
|
||||
// GenExecuteFun 生成执行过程
|
||||
func GenExecuteFun(fun func(ctx context.Context, parser *Parser) (err error)) func(ctx context.Context) {
|
||||
return func(ctx context.Context) {
|
||||
args, ok := ctx.Value(consts.ContextKeyCronArgs).([]string)
|
||||
if !ok {
|
||||
Logger().Panic(ctx, "执行定时任务时,参数解析失败!")
|
||||
return
|
||||
}
|
||||
parser := new(Parser)
|
||||
parser.Args = args
|
||||
parser.Logger = GenLoggerByCtx(ctx)
|
||||
|
||||
st := gtime.Now()
|
||||
err := g.Try(ctx, func(ctx context.Context) {
|
||||
if err := fun(ctx, parser); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
})
|
||||
|
||||
milliseconds := gtime.Now().Sub(st).Milliseconds() // 执行耗时
|
||||
if err != nil {
|
||||
parser.Logger.Errorf(ctx, "execute failed, took %vms, err:%+v", milliseconds, err)
|
||||
return
|
||||
}
|
||||
parser.Logger.Infof(ctx, "execute success, took %vms.", milliseconds)
|
||||
}
|
||||
}
|
@ -55,6 +55,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
|
||||
_, err = Version.Index(ctx, cVersionInput{})
|
||||
return
|
||||
}
|
||||
|
||||
answer := "n"
|
||||
// No argument or option, do installation checks.
|
||||
if data, isInstalled := service.Install.IsInstalled(); !isInstalled {
|
||||
@ -71,6 +72,7 @@ func (c cGF) Index(ctx context.Context, in cGFInput) (out *cGFOutput, err error)
|
||||
gcmd.Scan("press `Enter` to exit...")
|
||||
return
|
||||
}
|
||||
|
||||
// Print help content.
|
||||
gcmd.CommandFromCtx(ctx).Print()
|
||||
return
|
||||
|
@ -159,7 +159,7 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
||||
if gfile.Exists("main.go") {
|
||||
file = "main.go"
|
||||
} else {
|
||||
mlog.Fatal("build file path cannot be empty")
|
||||
mlog.Fatal("build file path is empty or main.go not found in current working directory")
|
||||
}
|
||||
}
|
||||
if in.Name == "" {
|
||||
@ -254,17 +254,23 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
||||
continue
|
||||
}
|
||||
if len(customSystems) == 0 && len(customArches) == 0 {
|
||||
// Single binary building, output the binary to current working folder.
|
||||
// For example:
|
||||
// `gf build`
|
||||
// `gf build -o main.exe`
|
||||
if runtime.GOOS == "windows" {
|
||||
ext = ".exe"
|
||||
}
|
||||
// Single binary building, output the binary to current working folder.
|
||||
output := ""
|
||||
var outputPath string
|
||||
if len(in.Output) > 0 {
|
||||
output = "-o " + in.Output + ext
|
||||
outputPath = "-o " + in.Output
|
||||
} else {
|
||||
output = "-o " + in.Name + ext
|
||||
outputPath = "-o " + in.Name + ext
|
||||
}
|
||||
cmd = fmt.Sprintf(`go build %s -ldflags "%s" %s %s`, output, ldFlags, in.Extra, file)
|
||||
cmd = fmt.Sprintf(
|
||||
`go build %s -ldflags "%s" %s %s`,
|
||||
outputPath, ldFlags, in.Extra, file,
|
||||
)
|
||||
} else {
|
||||
// Cross-building, output the compiled binary to specified path.
|
||||
if system == "windows" {
|
||||
@ -272,11 +278,22 @@ func (c cBuild) Index(ctx context.Context, in cBuildInput) (out *cBuildOutput, e
|
||||
}
|
||||
genv.MustSet("GOOS", system)
|
||||
genv.MustSet("GOARCH", arch)
|
||||
|
||||
var outputPath string
|
||||
if len(in.Output) > 0 {
|
||||
outputPath = "-o " + in.Output
|
||||
} else {
|
||||
outputPath = fmt.Sprintf(
|
||||
"-o %s/%s/%s%s",
|
||||
in.Path, system+"_"+arch, in.Name, ext,
|
||||
)
|
||||
}
|
||||
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,
|
||||
`go build %s -ldflags "%s" %s%s`,
|
||||
outputPath, ldFlags, in.Extra, file,
|
||||
)
|
||||
}
|
||||
mlog.Debug(fmt.Sprintf("build for GOOS=%s GOARCH=%s", system, arch))
|
||||
mlog.Debug(cmd)
|
||||
// It's not necessary printing the complete command string.
|
||||
cmdShow, _ := gregex.ReplaceString(`\s+(-ldflags ".+?")\s+`, " ", cmd)
|
||||
|
@ -7,14 +7,19 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"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/os/gproc"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
|
||||
@ -25,6 +30,10 @@ var (
|
||||
Version = cVersion{}
|
||||
)
|
||||
|
||||
const (
|
||||
defaultIndent = "{{indent}}"
|
||||
)
|
||||
|
||||
type cVersion struct {
|
||||
g.Meta `name:"version" brief:"show version information of current binary"`
|
||||
}
|
||||
@ -36,34 +45,90 @@ type cVersionInput struct {
|
||||
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()
|
||||
detailBuffer := &detailBuffer{}
|
||||
detailBuffer.WriteString(fmt.Sprintf("%s", gf.VERSION))
|
||||
|
||||
detailBuffer.appendLine(0, "Welcome to GoFrame!")
|
||||
|
||||
detailBuffer.appendLine(0, "Env Detail:")
|
||||
goVersion, ok := getGoVersion()
|
||||
if ok {
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Go Version: %s", goVersion))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", getGoFrameVersion(2)))
|
||||
} 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
|
||||
v, err := c.getGFVersionOfCurrentProject()
|
||||
if err == nil {
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", v))
|
||||
} else {
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("GF Version(go.mod): %s", err.Error()))
|
||||
}
|
||||
}
|
||||
|
||||
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)))
|
||||
detailBuffer.appendLine(0, "CLI Detail:")
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Installed At: %s", gfile.SelfPath()))
|
||||
info := gbuild.Info()
|
||||
if info.GoFrame == "" {
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Go Version: %s", runtime.Version()))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built GF Version: %s", gf.VERSION))
|
||||
} else {
|
||||
if info.Git == "" {
|
||||
info.Git = "none"
|
||||
}
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Go Version: %s", info.Golang))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built GF Version: %s", info.GoFrame))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Git Commit: %s", info.Git))
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Built Time: %s", info.Time))
|
||||
}
|
||||
|
||||
detailBuffer.appendLine(0, "Others Detail:")
|
||||
detailBuffer.appendLine(1, "Docs: https://goframe.org")
|
||||
detailBuffer.appendLine(1, fmt.Sprintf("Now : %s", time.Now().Format(time.RFC3339)))
|
||||
|
||||
mlog.Print(detailBuffer.replaceAllIndent(" "))
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// detailBuffer is a buffer for detail information.
|
||||
type detailBuffer struct {
|
||||
bytes.Buffer
|
||||
}
|
||||
|
||||
// appendLine appends a line to the buffer with given indent level.
|
||||
func (d *detailBuffer) appendLine(indentLevel int, line string) {
|
||||
d.WriteString(fmt.Sprintf("\n%s%s", strings.Repeat(defaultIndent, indentLevel), line))
|
||||
}
|
||||
|
||||
// replaceAllIndent replaces the tab with given indent string and prints the buffer content.
|
||||
func (d *detailBuffer) replaceAllIndent(indentStr string) string {
|
||||
return strings.ReplaceAll(d.String(), defaultIndent, indentStr)
|
||||
}
|
||||
|
||||
// getGoFrameVersion returns the goframe version of current project using.
|
||||
func getGoFrameVersion(indentLevel int) (gfVersion string) {
|
||||
pkgInfo, err := gproc.ShellExec(context.Background(), `go list -f "{{if (not .Main)}}{{.Path}}@{{.Version}}{{end}}" -m all`)
|
||||
if err != nil {
|
||||
return "cannot find go.mod"
|
||||
}
|
||||
pkgList := gstr.Split(pkgInfo, "\n")
|
||||
for _, v := range pkgList {
|
||||
if strings.HasPrefix(v, "github.com/gogf/gf") {
|
||||
gfVersion += fmt.Sprintf("\n%s%s", strings.Repeat(defaultIndent, indentLevel), v)
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// getGoVersion returns the go version
|
||||
func getGoVersion() (goVersion string, ok bool) {
|
||||
goVersion, err := gproc.ShellExec(context.Background(), "go version")
|
||||
if err != nil {
|
||||
return "", false
|
||||
}
|
||||
goVersion = gstr.TrimLeftStr(goVersion, "go version ")
|
||||
goVersion = gstr.TrimRightStr(goVersion, "\n")
|
||||
return goVersion, true
|
||||
}
|
||||
|
||||
// getGFVersionOfCurrentProject checks and returns the GoFrame version current project using.
|
||||
func (c cVersion) getGFVersionOfCurrentProject() (string, error) {
|
||||
goModPath := gfile.Join(gfile.Pwd(), "go.mod")
|
||||
|
@ -0,0 +1,11 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package cmd
|
||||
|
||||
import "context"
|
||||
|
||||
var ctx = context.Background()
|
@ -0,0 +1,85 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
"github.com/gogf/gf/v2/util/guid"
|
||||
"github.com/gogf/gf/v2/util/gutil"
|
||||
"hotgo/internal/library/hggen/internal/cmd/genctrl"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Gen_Ctrl_Default(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
path = gfile.Temp(guid.S())
|
||||
apiFolder = gtest.DataPath("genctrl", "api")
|
||||
in = genctrl.CGenCtrlInput{
|
||||
SrcFolder: apiFolder,
|
||||
DstFolder: path,
|
||||
WatchFile: "",
|
||||
SdkPath: "",
|
||||
SdkStdVersion: false,
|
||||
SdkNoV1: false,
|
||||
Clear: false,
|
||||
Merge: false,
|
||||
}
|
||||
)
|
||||
err := gutil.FillStructWithDefault(&in)
|
||||
t.AssertNil(err)
|
||||
|
||||
err = gfile.Mkdir(path)
|
||||
t.AssertNil(err)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
_, err = genctrl.CGenCtrl{}.Ctrl(ctx, in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// apiInterface file
|
||||
var (
|
||||
genApi = apiFolder + filepath.FromSlash("/article/article.go")
|
||||
genApiExpect = apiFolder + filepath.FromSlash("/article/article_expect.go")
|
||||
)
|
||||
defer gfile.Remove(genApi)
|
||||
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
|
||||
|
||||
// files
|
||||
files, err := gfile.ScanDir(path, "*.go", true)
|
||||
t.AssertNil(err)
|
||||
t.Assert(files, []string{
|
||||
path + filepath.FromSlash("/article/article.go"),
|
||||
path + filepath.FromSlash("/article/article_new.go"),
|
||||
path + filepath.FromSlash("/article/article_v1_create.go"),
|
||||
path + filepath.FromSlash("/article/article_v1_get_list.go"),
|
||||
path + filepath.FromSlash("/article/article_v1_get_one.go"),
|
||||
path + filepath.FromSlash("/article/article_v1_update.go"),
|
||||
path + filepath.FromSlash("/article/article_v2_create.go"),
|
||||
path + filepath.FromSlash("/article/article_v2_update.go"),
|
||||
})
|
||||
|
||||
// content
|
||||
testPath := gtest.DataPath("genctrl", "controller")
|
||||
expectFiles := []string{
|
||||
testPath + filepath.FromSlash("/article/article.go"),
|
||||
testPath + filepath.FromSlash("/article/article_new.go"),
|
||||
testPath + filepath.FromSlash("/article/article_v1_create.go"),
|
||||
testPath + filepath.FromSlash("/article/article_v1_get_list.go"),
|
||||
testPath + filepath.FromSlash("/article/article_v1_get_one.go"),
|
||||
testPath + filepath.FromSlash("/article/article_v1_update.go"),
|
||||
testPath + filepath.FromSlash("/article/article_v2_create.go"),
|
||||
testPath + filepath.FromSlash("/article/article_v2_update.go"),
|
||||
}
|
||||
for i := range files {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
})
|
||||
}
|
@ -7,8 +7,8 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
@ -20,8 +20,6 @@ import (
|
||||
"hotgo/internal/library/hggen/internal/cmd/gendao"
|
||||
)
|
||||
|
||||
var ctx = context.Background()
|
||||
|
||||
func dropTableWithDb(db gdb.DB, table string) {
|
||||
dropTableStmt := fmt.Sprintf("DROP TABLE IF EXISTS `%s`", table)
|
||||
if _, err := db.Exec(ctx, dropTableStmt); err != nil {
|
||||
@ -105,18 +103,18 @@ func Test_Gen_Dao_Default(t *testing.T) {
|
||||
files, err := gfile.ScanDir(path, "*.go", true)
|
||||
t.AssertNil(err)
|
||||
t.Assert(files, []string{
|
||||
path + "/dao/internal/table_user.go",
|
||||
path + "/dao/table_user.go",
|
||||
path + "/model/do/table_user.go",
|
||||
path + "/model/entity/table_user.go",
|
||||
filepath.FromSlash(path + "/dao/internal/table_user.go"),
|
||||
filepath.FromSlash(path + "/dao/table_user.go"),
|
||||
filepath.FromSlash(path + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(path + "/model/entity/table_user.go"),
|
||||
})
|
||||
// content
|
||||
testPath := gtest.DataPath("gendao", "generated_user")
|
||||
expectFiles := []string{
|
||||
testPath + "/dao/internal/table_user.go",
|
||||
testPath + "/dao/table_user.go",
|
||||
testPath + "/model/do/table_user.go",
|
||||
testPath + "/model/entity/table_user.go",
|
||||
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/dao/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||
}
|
||||
for i, _ := range files {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
@ -209,18 +207,18 @@ func Test_Gen_Dao_TypeMapping(t *testing.T) {
|
||||
files, err := gfile.ScanDir(path, "*.go", true)
|
||||
t.AssertNil(err)
|
||||
t.Assert(files, []string{
|
||||
path + "/dao/internal/table_user.go",
|
||||
path + "/dao/table_user.go",
|
||||
path + "/model/do/table_user.go",
|
||||
path + "/model/entity/table_user.go",
|
||||
filepath.FromSlash(path + "/dao/internal/table_user.go"),
|
||||
filepath.FromSlash(path + "/dao/table_user.go"),
|
||||
filepath.FromSlash(path + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(path + "/model/entity/table_user.go"),
|
||||
})
|
||||
// content
|
||||
testPath := gtest.DataPath("gendao", "generated_user_type_mapping")
|
||||
expectFiles := []string{
|
||||
testPath + "/dao/internal/table_user.go",
|
||||
testPath + "/dao/table_user.go",
|
||||
testPath + "/model/do/table_user.go",
|
||||
testPath + "/model/entity/table_user.go",
|
||||
filepath.FromSlash(testPath + "/dao/internal/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/dao/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/do/table_user.go"),
|
||||
filepath.FromSlash(testPath + "/model/entity/table_user.go"),
|
||||
}
|
||||
for i, _ := range files {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
@ -0,0 +1,72 @@
|
||||
// Copyright GoFrame gf Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/gogf/gf/v2/test/gtest"
|
||||
"github.com/gogf/gf/v2/util/guid"
|
||||
"github.com/gogf/gf/v2/util/gutil"
|
||||
"hotgo/internal/library/hggen/internal/cmd/genservice"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_Gen_Service_Default(t *testing.T) {
|
||||
gtest.C(t, func(t *gtest.T) {
|
||||
var (
|
||||
path = gfile.Temp(guid.S())
|
||||
dstFolder = path + filepath.FromSlash("/service")
|
||||
apiFolder = gtest.DataPath("genservice", "logic")
|
||||
in = genservice.CGenServiceInput{
|
||||
SrcFolder: apiFolder,
|
||||
DstFolder: dstFolder,
|
||||
DstFileNameCase: "Snake",
|
||||
WatchFile: "",
|
||||
StPattern: "",
|
||||
Packages: nil,
|
||||
ImportPrefix: "",
|
||||
Clear: false,
|
||||
}
|
||||
)
|
||||
err := gutil.FillStructWithDefault(&in)
|
||||
t.AssertNil(err)
|
||||
|
||||
err = gfile.Mkdir(path)
|
||||
t.AssertNil(err)
|
||||
defer gfile.Remove(path)
|
||||
|
||||
_, err = genservice.CGenService{}.Service(ctx, in)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// logic file
|
||||
var (
|
||||
genApi = apiFolder + filepath.FromSlash("/logic.go")
|
||||
genApiExpect = apiFolder + filepath.FromSlash("/logic_expect.go")
|
||||
)
|
||||
defer gfile.Remove(genApi)
|
||||
t.Assert(gfile.GetContents(genApi), gfile.GetContents(genApiExpect))
|
||||
|
||||
// files
|
||||
files, err := gfile.ScanDir(dstFolder, "*.go", true)
|
||||
t.AssertNil(err)
|
||||
t.Assert(files, []string{
|
||||
dstFolder + filepath.FromSlash("/article.go"),
|
||||
})
|
||||
|
||||
// contents
|
||||
testPath := gtest.DataPath("genservice", "service")
|
||||
expectFiles := []string{
|
||||
testPath + filepath.FromSlash("/article.go"),
|
||||
}
|
||||
for i := range files {
|
||||
t.Assert(gfile.GetContents(files[i]), gfile.GetContents(expectFiles[i]))
|
||||
}
|
||||
})
|
||||
}
|
@ -38,7 +38,7 @@ gf gen ctrl
|
||||
)
|
||||
|
||||
const (
|
||||
PatternApiDefinition = `type\s+(\w+)Req\s+struct\s+{([\s\S]+?)}`
|
||||
PatternApiDefinition = `type[\s\(]+(\w+)Req\s+struct\s+{([\s\S]+?)}`
|
||||
PatternCtrlDefinition = `func\s+\(.+?\)\s+\w+\(.+?\*(\w+)\.(\w+)Req\)\s+\(.+?\*(\w+)\.(\w+)Res,\s+\w+\s+error\)\s+{`
|
||||
)
|
||||
|
||||
|
@ -8,6 +8,7 @@ package genctrl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -64,8 +65,8 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
|
||||
dstModuleFolderPath, module, version, importPath string,
|
||||
) (err error) {
|
||||
var (
|
||||
moduleFilePath = gfile.Join(dstModuleFolderPath, module+".go")
|
||||
moduleFilePathNew = gfile.Join(dstModuleFolderPath, module+"_new.go")
|
||||
moduleFilePath = filepath.FromSlash(gfile.Join(dstModuleFolderPath, module+".go"))
|
||||
moduleFilePathNew = filepath.FromSlash(gfile.Join(dstModuleFolderPath, module+"_new.go"))
|
||||
ctrlName = fmt.Sprintf(`Controller%s`, gstr.UcFirst(version))
|
||||
interfaceName = fmt.Sprintf(`%s.I%s%s`, module, gstr.CaseCamel(module), gstr.UcFirst(version))
|
||||
newFuncName = fmt.Sprintf(`New%s`, gstr.UcFirst(version))
|
||||
@ -107,7 +108,7 @@ func (c *controllerGenerator) doGenerateCtrlNewByModuleAndVersion(
|
||||
"{NewFuncName}": newFuncName,
|
||||
"{InterfaceName}": interfaceName,
|
||||
})
|
||||
err = gfile.PutContentsAppend(moduleFilePathNew, gstr.TrimLeft(content))
|
||||
err = gfile.PutContentsAppend(moduleFilePathNew, content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -119,9 +120,9 @@ func (c *controllerGenerator) doGenerateCtrlItem(dstModuleFolderPath string, ite
|
||||
var (
|
||||
methodNameSnake = gstr.CaseSnake(item.MethodName)
|
||||
ctrlName = fmt.Sprintf(`Controller%s`, gstr.UcFirst(item.Version))
|
||||
methodFilePath = gfile.Join(dstModuleFolderPath, fmt.Sprintf(
|
||||
methodFilePath = filepath.FromSlash(gfile.Join(dstModuleFolderPath, fmt.Sprintf(
|
||||
`%s_%s_%s.go`, item.Module, item.Version, methodNameSnake,
|
||||
))
|
||||
)))
|
||||
)
|
||||
var content string
|
||||
|
||||
|
@ -8,6 +8,7 @@ package genctrl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gmap"
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
@ -39,18 +40,17 @@ func (c *apiInterfaceGenerator) Generate(apiModuleFolderPath string, apiModuleAp
|
||||
|
||||
func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module string, items []apiItem) (err error) {
|
||||
var (
|
||||
moduleFilePath = gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.go`, module))
|
||||
moduleFilePath = filepath.FromSlash(gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.go`, module)))
|
||||
importPathMap = gmap.NewListMap()
|
||||
importPaths []string
|
||||
)
|
||||
// if there's already exist file that with the same but not auto generated go file,
|
||||
// it uses another file name.
|
||||
if !utils.IsFileDoNotEdit(moduleFilePath) {
|
||||
moduleFilePath = gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.if.go`, module))
|
||||
moduleFilePath = filepath.FromSlash(gfile.Join(apiModuleFolderPath, fmt.Sprintf(`%s.if.go`, module)))
|
||||
}
|
||||
// all import paths.
|
||||
importPathMap.Set("\t"+`"context"`, 1)
|
||||
importPathMap.Set("\t"+``, 1)
|
||||
importPathMap.Set("\t"+`"context"`+"\n", 1)
|
||||
for _, item := range items {
|
||||
importPathMap.Set(fmt.Sprintf("\t"+`"%s"`, item.Import), 1)
|
||||
}
|
||||
@ -91,7 +91,7 @@ func (c *apiInterfaceGenerator) doGenerate(apiModuleFolderPath string, module st
|
||||
interfaceDefinition += "\n\n"
|
||||
}
|
||||
interfaceContent = gstr.TrimLeft(gstr.ReplaceByMap(interfaceContent, g.MapStrStr{
|
||||
"{Interfaces}": interfaceDefinition,
|
||||
"{Interfaces}": gstr.TrimRightStr(interfaceDefinition, "\n", 2),
|
||||
}))
|
||||
err = gfile.PutContents(moduleFilePath, interfaceContent)
|
||||
mlog.Printf(`generated: %s`, moduleFilePath)
|
||||
|
@ -8,6 +8,7 @@ package genctrl
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gogf/gf/v2/container/gset"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -54,7 +55,7 @@ func (c *apiSdkGenerator) Generate(apiModuleApiItems []apiItem, sdkFolderPath st
|
||||
func (c *apiSdkGenerator) doGenerateSdkPkgFile(sdkFolderPath string) (err error) {
|
||||
var (
|
||||
pkgName = gfile.Basename(sdkFolderPath)
|
||||
pkgFilePath = gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.go`, pkgName))
|
||||
pkgFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.go`, pkgName)))
|
||||
fileContent string
|
||||
)
|
||||
if gfile.Exists(pkgFilePath) {
|
||||
@ -79,7 +80,7 @@ func (c *apiSdkGenerator) doGenerateSdkIClient(
|
||||
funcName = gstr.CaseCamel(module) + gstr.UcFirst(version)
|
||||
interfaceName = fmt.Sprintf(`I%s`, funcName)
|
||||
moduleImportPath = gstr.Replace(fmt.Sprintf(`"%s"`, gfile.Dir(versionImportPath)), "\\", "/", -1)
|
||||
iClientFilePath = gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.iclient.go`, pkgName))
|
||||
iClientFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(`%s.iclient.go`, pkgName)))
|
||||
interfaceFuncDefinition = fmt.Sprintf(
|
||||
`%s() %s.%s`,
|
||||
gstr.CaseCamel(module)+gstr.UcFirst(version), module, interfaceName,
|
||||
@ -145,9 +146,9 @@ func (c *apiSdkGenerator) doGenerateSdkImplementer(
|
||||
moduleImportPath = gstr.Replace(gfile.Dir(versionImportPath), "\\", "/", -1)
|
||||
versionPrefix = ""
|
||||
implementerName = moduleNameCamel + gstr.UcFirst(version)
|
||||
implementerFilePath = gfile.Join(sdkFolderPath, fmt.Sprintf(
|
||||
implementerFilePath = filepath.FromSlash(gfile.Join(sdkFolderPath, fmt.Sprintf(
|
||||
`%s_%s_%s.go`, pkgName, moduleNameSnake, version,
|
||||
))
|
||||
)))
|
||||
)
|
||||
if sdkNoV1 && version == "v1" {
|
||||
implementerName = moduleNameCamel
|
||||
|
@ -9,9 +9,10 @@ package gendao
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"golang.org/x/mod/modfile"
|
||||
"strings"
|
||||
|
||||
"golang.org/x/mod/modfile"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
@ -106,7 +107,7 @@ type generateDaoIndexInput struct {
|
||||
}
|
||||
|
||||
func generateDaoIndex(in generateDaoIndexInput) {
|
||||
path := gfile.Join(in.DirPathDao, in.FileName+".go")
|
||||
path := filepath.FromSlash(gfile.Join(in.DirPathDao, in.FileName+".go"))
|
||||
if in.OverwriteDao || !gfile.Exists(path) {
|
||||
indexContent := gstr.ReplaceByMap(
|
||||
getTemplateFromPathOrDefault(in.TplDaoIndexPath, consts.TemplateGenDaoIndexContent),
|
||||
@ -136,7 +137,7 @@ type generateDaoInternalInput struct {
|
||||
}
|
||||
|
||||
func generateDaoInternal(in generateDaoInternalInput) {
|
||||
path := gfile.Join(in.DirPathDaoInternal, in.FileName+".go")
|
||||
path := filepath.FromSlash(gfile.Join(in.DirPathDaoInternal, in.FileName+".go"))
|
||||
modelContent := gstr.ReplaceByMap(
|
||||
getTemplateFromPathOrDefault(in.TplDaoInternalPath, consts.TemplateGenDaoInternalContent),
|
||||
g.MapStrStr{
|
||||
|
@ -9,6 +9,7 @@ package gendao
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -22,7 +23,7 @@ import (
|
||||
)
|
||||
|
||||
func generateDo(ctx context.Context, in CGenDaoInternalInput) {
|
||||
var dirPathDo = gfile.Join(in.Path, in.DoPath)
|
||||
var dirPathDo = filepath.FromSlash(gfile.Join(in.Path, in.DoPath))
|
||||
if in.Clear {
|
||||
doClear(ctx, dirPathDo, false)
|
||||
}
|
||||
|
@ -8,6 +8,7 @@ package gendao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
@ -33,7 +34,7 @@ func generateEntity(ctx context.Context, in CGenDaoInternalInput) {
|
||||
|
||||
var (
|
||||
newTableName = in.NewTableNames[i]
|
||||
entityFilePath = gfile.Join(dirPathEntity, gstr.CaseSnake(newTableName)+".go")
|
||||
entityFilePath = filepath.FromSlash(gfile.Join(dirPathEntity, gstr.CaseSnake(newTableName)+".go"))
|
||||
structDefinition, appendImports = generateStructDefinition(ctx, generateStructDefinitionInput{
|
||||
CGenDaoInternalInput: in,
|
||||
TableName: tableName,
|
||||
|
@ -10,9 +10,10 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/olekukonko/tablewriter"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/text/gregex"
|
||||
@ -70,7 +71,7 @@ func generateStructFieldDefinition(
|
||||
err error
|
||||
localTypeName gdb.LocalType
|
||||
localTypeNameStr string
|
||||
jsonTag = getJsonTagFromCase(field.Name, in.JsonCase)
|
||||
jsonTag = gstr.CaseConvert(field.Name, gstr.CaseTypeMatch(in.JsonCase))
|
||||
)
|
||||
|
||||
if in.TypeMapping != nil && len(in.TypeMapping) > 0 {
|
||||
@ -158,30 +159,3 @@ func formatComment(comment string) string {
|
||||
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
|
||||
}
|
||||
|
@ -19,9 +19,10 @@ import (
|
||||
const pkgLoadMode = 0xffffff
|
||||
|
||||
type EnumsParser struct {
|
||||
enums []EnumItem
|
||||
parsedPkg map[string]struct{}
|
||||
prefixes []string
|
||||
enums []EnumItem
|
||||
parsedPkg map[string]struct{}
|
||||
prefixes []string
|
||||
standardPackages map[string]struct{}
|
||||
}
|
||||
|
||||
type EnumItem struct {
|
||||
@ -31,23 +32,12 @@ type EnumItem struct {
|
||||
Type string // Pkg.ID + TypeName
|
||||
}
|
||||
|
||||
var standardPackages = make(map[string]struct{})
|
||||
|
||||
//func init() {
|
||||
// stdPackages, err := packages.Load(nil, "std")
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// for _, p := range stdPackages {
|
||||
// standardPackages[p.ID] = struct{}{}
|
||||
// }
|
||||
//}
|
||||
|
||||
func NewEnumsParser(prefixes []string) *EnumsParser {
|
||||
return &EnumsParser{
|
||||
enums: make([]EnumItem, 0),
|
||||
parsedPkg: make(map[string]struct{}),
|
||||
prefixes: prefixes,
|
||||
enums: make([]EnumItem, 0),
|
||||
parsedPkg: make(map[string]struct{}),
|
||||
prefixes: prefixes,
|
||||
standardPackages: getStandardPackages(),
|
||||
}
|
||||
}
|
||||
|
||||
@ -59,7 +49,7 @@ func (p *EnumsParser) ParsePackages(pkgs []*packages.Package) {
|
||||
|
||||
func (p *EnumsParser) ParsePackage(pkg *packages.Package) {
|
||||
// Ignore std packages.
|
||||
if _, ok := standardPackages[pkg.ID]; ok {
|
||||
if _, ok := p.standardPackages[pkg.ID]; ok {
|
||||
return
|
||||
}
|
||||
// Ignore pared packages.
|
||||
@ -144,3 +134,15 @@ func (p *EnumsParser) Export() string {
|
||||
}
|
||||
return gjson.MustEncodeString(typeEnumMap)
|
||||
}
|
||||
|
||||
func getStandardPackages() map[string]struct{} {
|
||||
standardPackages := make(map[string]struct{})
|
||||
stdPackages, err := packages.Load(nil, "std")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
for _, p := range stdPackages {
|
||||
standardPackages[p.ID] = struct{}{}
|
||||
}
|
||||
return standardPackages
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/olekukonko/tablewriter"
|
||||
@ -197,7 +198,7 @@ func doGenPbEntityForArray(ctx context.Context, index int, in CGenPbEntityInput)
|
||||
if len(match) == 3 {
|
||||
gdb.AddConfigNode(tempGroup, gdb.ConfigNode{
|
||||
Type: gstr.Trim(match[1]),
|
||||
Link: gstr.Trim(match[2]),
|
||||
Link: in.Link,
|
||||
})
|
||||
db, _ = gdb.Instance(tempGroup)
|
||||
}
|
||||
@ -246,7 +247,7 @@ func generatePbEntityContentFile(ctx context.Context, in CGenPbEntityInternalInp
|
||||
tableNameSnakeCase = gstr.CaseSnake(newTableName)
|
||||
entityMessageDefine = generateEntityMessageDefinition(tableNameCamelCase, fieldMap, in)
|
||||
fileName = gstr.Trim(tableNameSnakeCase, "-_.")
|
||||
path = gfile.Join(in.Path, fileName+".proto")
|
||||
path = filepath.FromSlash(gfile.Join(in.Path, fileName+".proto"))
|
||||
)
|
||||
if gstr.Contains(entityMessageDefine, "google.protobuf.Timestamp") {
|
||||
imports = `import "google/protobuf/timestamp.proto";`
|
||||
|
@ -9,6 +9,7 @@ package genservice
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/gogf/gf/v2/container/garray"
|
||||
"github.com/gogf/gf/v2/container/gmap"
|
||||
@ -93,10 +94,10 @@ const (
|
||||
)
|
||||
|
||||
func (c CGenService) Service(ctx context.Context, in CGenServiceInput) (out *CGenServiceOutput, err error) {
|
||||
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `\/`)
|
||||
in.SrcFolder = gstr.Replace(in.SrcFolder, "\\", "/")
|
||||
in.WatchFile = gstr.TrimRight(in.WatchFile, `\/`)
|
||||
in.WatchFile = gstr.Replace(in.WatchFile, "\\", "/")
|
||||
in.SrcFolder = filepath.ToSlash(in.SrcFolder)
|
||||
in.SrcFolder = gstr.TrimRight(in.SrcFolder, `/`)
|
||||
in.WatchFile = filepath.ToSlash(in.WatchFile)
|
||||
in.WatchFile = gstr.TrimRight(in.WatchFile, `/`)
|
||||
|
||||
// Watch file handling.
|
||||
if in.WatchFile != "" {
|
||||
|
@ -194,28 +194,9 @@ func (c CGenService) generateInitializationFile(in CGenServiceInput, importSrcPa
|
||||
}
|
||||
|
||||
// getDstFileNameCase call gstr.Case* function to convert the s to specified case.
|
||||
func (c CGenService) getDstFileNameCase(str, caseStr string) string {
|
||||
switch gstr.ToLower(caseStr) {
|
||||
case gstr.ToLower("Lower"):
|
||||
return gstr.ToLower(str)
|
||||
|
||||
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("SnakeFirstUpper"):
|
||||
return gstr.CaseSnakeFirstUpper(str)
|
||||
|
||||
case gstr.ToLower("SnakeScreaming"):
|
||||
return gstr.CaseSnakeScreaming(str)
|
||||
func (c CGenService) getDstFileNameCase(str, caseStr string) (newStr string) {
|
||||
if newStr := gstr.CaseConvert(str, gstr.CaseTypeMatch(caseStr)); newStr != str {
|
||||
return newStr
|
||||
}
|
||||
return gstr.CaseSnake(str)
|
||||
}
|
||||
|
24
server/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/article_expect.go
vendored
Normal file
24
server/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/article_expect.go
vendored
Normal file
@ -0,0 +1,24 @@
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v2"
|
||||
)
|
||||
|
||||
type IArticleV1 interface {
|
||||
Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error)
|
||||
Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error)
|
||||
GetList(ctx context.Context, req *v1.GetListReq) (res *v1.GetListRes, err error)
|
||||
GetOne(ctx context.Context, req *v1.GetOneReq) (res *v1.GetOneRes, err error)
|
||||
}
|
||||
|
||||
type IArticleV2 interface {
|
||||
Create(ctx context.Context, req *v2.CreateReq) (res *v2.CreateRes, err error)
|
||||
Update(ctx context.Context, req *v2.UpdateReq) (res *v2.UpdateRes, err error)
|
||||
}
|
27
server/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1/edit.go
vendored
Normal file
27
server/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1/edit.go
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package v1
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type (
|
||||
CreateReq struct {
|
||||
g.Meta `path:"/article/create" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
}
|
||||
|
||||
CreateRes struct{}
|
||||
)
|
||||
|
||||
type (
|
||||
UpdateReq struct {
|
||||
g.Meta `path:"/article/update" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
}
|
||||
|
||||
UpdateRes struct{}
|
||||
)
|
25
server/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1/get.go
vendored
Normal file
25
server/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1/get.go
vendored
Normal file
@ -0,0 +1,25 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package v1
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type GetListReq struct {
|
||||
g.Meta `path:"/article/list" method:"get" tags:"ArticleService"`
|
||||
}
|
||||
|
||||
type GetListRes struct {
|
||||
list []struct{}
|
||||
}
|
||||
|
||||
type GetOneReq struct {
|
||||
g.Meta `path:"/article/one" method:"get" tags:"ArticleService"`
|
||||
}
|
||||
|
||||
type GetOneRes struct {
|
||||
one struct{}
|
||||
}
|
23
server/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v2/edit.go
vendored
Normal file
23
server/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v2/edit.go
vendored
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package v2
|
||||
|
||||
import "github.com/gogf/gf/v2/frame/g"
|
||||
|
||||
type CreateReq struct {
|
||||
g.Meta `path:"/article/create" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
}
|
||||
|
||||
type CreateRes struct{}
|
||||
|
||||
type UpdateReq struct {
|
||||
g.Meta `path:"/article/update" method:"post" tags:"ArticleService"`
|
||||
Title string `v:"required"`
|
||||
}
|
||||
|
||||
type UpdateRes struct{}
|
5
server/internal/library/hggen/internal/cmd/testdata/genctrl/controller/article/article.go
vendored
Normal file
5
server/internal/library/hggen/internal/cmd/testdata/genctrl/controller/article/article.go
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package article
|
21
server/internal/library/hggen/internal/cmd/testdata/genctrl/controller/article/article_new.go
vendored
Normal file
21
server/internal/library/hggen/internal/cmd/testdata/genctrl/controller/article/article_new.go
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
// =================================================================================
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package article
|
||||
|
||||
import (
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article"
|
||||
)
|
||||
|
||||
type ControllerV1 struct{}
|
||||
|
||||
func NewV1() article.IArticleV1 {
|
||||
return &ControllerV1{}
|
||||
}
|
||||
|
||||
type ControllerV2 struct{}
|
||||
|
||||
func NewV2() article.IArticleV2 {
|
||||
return &ControllerV2{}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Create(ctx context.Context, req *v1.CreateReq) (res *v1.CreateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) GetList(ctx context.Context, req *v1.GetListReq) (res *v1.GetListRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) GetOne(ctx context.Context, req *v1.GetOneReq) (res *v1.GetOneRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v1"
|
||||
)
|
||||
|
||||
func (c *ControllerV1) Update(ctx context.Context, req *v1.UpdateReq) (res *v1.UpdateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v2"
|
||||
)
|
||||
|
||||
func (c *ControllerV2) Create(ctx context.Context, req *v2.CreateReq) (res *v2.CreateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genctrl/api/article/v2"
|
||||
)
|
||||
|
||||
func (c *ControllerV2) Update(ctx context.Context, req *v2.UpdateReq) (res *v2.UpdateRes, err error) {
|
||||
return nil, gerror.NewCode(gcode.CodeNotImplemented)
|
||||
}
|
33
server/internal/library/hggen/internal/cmd/testdata/genservice/logic/article/article.go
vendored
Normal file
33
server/internal/library/hggen/internal/cmd/testdata/genservice/logic/article/article.go
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the MIT License.
|
||||
// If a copy of the MIT was not distributed with this file,
|
||||
// You can obtain one at https://github.com/gogf/gf.
|
||||
|
||||
package article
|
||||
|
||||
import (
|
||||
"context"
|
||||
"hotgo/internal/library/hggen/internal/cmd/testdata/genservice/service"
|
||||
)
|
||||
|
||||
type sArticle struct {
|
||||
}
|
||||
|
||||
func init() {
|
||||
service.RegisterArticle(&sArticle{})
|
||||
}
|
||||
|
||||
// Get article details
|
||||
func (s *sArticle) Get(ctx context.Context, id uint) (info struct{}, err error) {
|
||||
return struct{}{}, err
|
||||
}
|
||||
|
||||
// Create
|
||||
/**
|
||||
* create an article.
|
||||
* @author oldme
|
||||
*/
|
||||
func (s *sArticle) Create(ctx context.Context, info struct{}) (id uint, err error) {
|
||||
return id, err
|
||||
}
|
9
server/internal/library/hggen/internal/cmd/testdata/genservice/logic/logic_expect.go
vendored
Normal file
9
server/internal/library/hggen/internal/cmd/testdata/genservice/logic/logic_expect.go
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
// ==========================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// ==========================================================================
|
||||
|
||||
package logic
|
||||
|
||||
import (
|
||||
_ "hotgo/internal/library/hggen/internal/cmd/testdata/genservice/logic/article"
|
||||
)
|
38
server/internal/library/hggen/internal/cmd/testdata/genservice/service/article.go
vendored
Normal file
38
server/internal/library/hggen/internal/cmd/testdata/genservice/service/article.go
vendored
Normal file
@ -0,0 +1,38 @@
|
||||
// ================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// You can delete these comments if you wish manually maintain this interface file.
|
||||
// ================================================================================
|
||||
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type (
|
||||
IArticle interface {
|
||||
// Get article details
|
||||
Get(ctx context.Context, id uint) (info struct{}, err error)
|
||||
// Create
|
||||
/**
|
||||
* create an article.
|
||||
* @author oldme
|
||||
*/
|
||||
Create(ctx context.Context, info struct{}) (id uint, err error)
|
||||
}
|
||||
)
|
||||
|
||||
var (
|
||||
localArticle IArticle
|
||||
)
|
||||
|
||||
func Article() IArticle {
|
||||
if localArticle == nil {
|
||||
panic("implement not found for interface IArticle, forgot register?")
|
||||
}
|
||||
return localArticle
|
||||
}
|
||||
|
||||
func RegisterArticle(i IArticle) {
|
||||
localArticle = i
|
||||
}
|
@ -12,12 +12,11 @@ const TemplateGenCtrlControllerEmpty = `
|
||||
// =================================================================================
|
||||
|
||||
package {Module}
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerNewEmpty = `
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish.
|
||||
// =================================================================================
|
||||
|
||||
package {Module}
|
||||
@ -25,7 +24,6 @@ package {Module}
|
||||
import (
|
||||
{ImportPath}
|
||||
)
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerNewFunc = `
|
||||
@ -34,7 +32,6 @@ type {CtrlName} struct{}
|
||||
func {NewFuncName}() {InterfaceName} {
|
||||
return &{CtrlName}{}
|
||||
}
|
||||
|
||||
`
|
||||
|
||||
const TemplateGenCtrlControllerMethodFunc = `
|
||||
@ -63,7 +60,7 @@ func (c *{CtrlName}) {MethodName}(ctx context.Context, req *{Version}.{MethodNam
|
||||
|
||||
const TemplateGenCtrlApiInterface = `
|
||||
// =================================================================================
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
|
||||
// =================================================================================
|
||||
|
||||
package {Module}
|
||||
|
@ -118,7 +118,7 @@ func GetImportPath(filePath string) string {
|
||||
func GetModPath() string {
|
||||
var (
|
||||
oldDir = gfile.Pwd()
|
||||
newDir = gfile.Dir(oldDir)
|
||||
newDir = oldDir
|
||||
goModName = "go.mod"
|
||||
goModPath string
|
||||
)
|
||||
@ -127,11 +127,11 @@ func GetModPath() string {
|
||||
if gfile.Exists(goModPath) {
|
||||
return goModPath
|
||||
}
|
||||
oldDir = newDir
|
||||
newDir = gfile.Dir(oldDir)
|
||||
if newDir == oldDir {
|
||||
break
|
||||
}
|
||||
oldDir = newDir
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
@ -9,7 +9,6 @@ import (
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/model/input/sysin"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// 默认表单组件映射 Ts -> 表单组件
|
||||
@ -119,7 +118,7 @@ func setDefault(field *sysin.GenCodesColumnListModel) {
|
||||
field.Required = true
|
||||
}
|
||||
|
||||
if strings.Contains(field.Index, consts.GenCodesIndexUNI) {
|
||||
if IsIndexUNI(field.Index) {
|
||||
field.Unique = true
|
||||
}
|
||||
|
||||
@ -136,7 +135,7 @@ func setDefault(field *sysin.GenCodesColumnListModel) {
|
||||
func setDefaultEdit(field *sysin.GenCodesColumnListModel) {
|
||||
field.IsEdit = true
|
||||
|
||||
if field.Index == consts.GenCodesIndexPK {
|
||||
if IsIndexPK(field.Index) {
|
||||
field.IsEdit = false
|
||||
return
|
||||
}
|
||||
@ -258,7 +257,7 @@ func setDefaultExport(field *sysin.GenCodesColumnListModel) {
|
||||
func setDefaultQuery(field *sysin.GenCodesColumnListModel) {
|
||||
field.IsQuery = false
|
||||
|
||||
if field.Index == consts.GenCodesIndexPK {
|
||||
if IsIndexPK(field.Index) {
|
||||
field.IsQuery = true
|
||||
return
|
||||
}
|
||||
|
@ -11,7 +11,6 @@ import (
|
||||
"fmt"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"hotgo/internal/consts"
|
||||
)
|
||||
|
||||
func (l *gCurd) webEditTplData(ctx context.Context, in *CurdPreviewInput) (data g.Map, err error) {
|
||||
@ -28,7 +27,7 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
|
||||
continue
|
||||
}
|
||||
|
||||
if field.Index == consts.GenCodesIndexPK {
|
||||
if IsIndexPK(field.Index) {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ func (l *gCurd) getPkField(in *CurdPreviewInput) *sysin.GenCodesColumnListModel
|
||||
panic("getPkField masterFields uninitialized.")
|
||||
}
|
||||
for _, field := range in.masterFields {
|
||||
if field.Index == consts.GenCodesIndexPK {
|
||||
if IsIndexPK(field.Index) {
|
||||
return field
|
||||
}
|
||||
}
|
||||
@ -165,3 +165,13 @@ func GetModName(ctx context.Context) (modName string, err error) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// IsIndexPK 是否是主键
|
||||
func IsIndexPK(index string) bool {
|
||||
return gstr.ToUpper(index) == gstr.ToUpper(consts.GenCodesIndexPK)
|
||||
}
|
||||
|
||||
// IsIndexUNI 是否是唯一索引
|
||||
func IsIndexUNI(index string) bool {
|
||||
return gstr.ToUpper(index) == gstr.ToUpper(consts.GenCodesIndexUNI)
|
||||
}
|
||||
|
@ -14,7 +14,6 @@ import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"hotgo/utility/convert"
|
||||
"hotgo/utility/tree"
|
||||
)
|
||||
|
||||
type daoInstance interface {
|
||||
@ -117,6 +116,23 @@ func GetPkField(ctx context.Context, dao daoInstance) (string, error) {
|
||||
return "", gerror.New("no primary key")
|
||||
}
|
||||
|
||||
// GetFieldsToSlice 获取dao实例中的所有字段
|
||||
func GetFieldsToSlice(ctx context.Context, dao daoInstance) ([]string, error) {
|
||||
fields, err := dao.Ctx(ctx).TableFields(dao.Table())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(fields) == 0 {
|
||||
return nil, gerror.New("field not found")
|
||||
}
|
||||
|
||||
var keys []string
|
||||
for _, field := range fields {
|
||||
keys = append(keys, field.Name)
|
||||
}
|
||||
return keys, nil
|
||||
}
|
||||
|
||||
// IsUnique 是否唯一
|
||||
func IsUnique(ctx context.Context, dao daoInstance, where g.Map, message string, pkId ...interface{}) error {
|
||||
if len(where) == 0 {
|
||||
@ -148,40 +164,3 @@ func IsUnique(ctx context.Context, dao daoInstance, where g.Map, message string,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// GenSubTree 生成下级关系树
|
||||
func GenSubTree(ctx context.Context, dao daoInstance, oldPid int64) (newPid int64, newLevel int, subTree string, err error) {
|
||||
// 顶级树
|
||||
if oldPid <= 0 {
|
||||
return 0, 1, "", nil
|
||||
}
|
||||
|
||||
field, err := GetPkField(ctx, dao)
|
||||
if err != nil {
|
||||
return 0, 0, "", err
|
||||
}
|
||||
|
||||
models, err := dao.Ctx(ctx).Where(field, oldPid).One()
|
||||
if err != nil {
|
||||
return 0, 0, "", err
|
||||
}
|
||||
|
||||
if models.IsEmpty() {
|
||||
return 0, 0, "", gerror.New("上级信息不存在")
|
||||
}
|
||||
|
||||
level, ok := models["level"]
|
||||
if !ok {
|
||||
return 0, 0, "", gerror.New("表中必须包含`level`字段")
|
||||
}
|
||||
|
||||
supTree, ok := models["tree"]
|
||||
if !ok {
|
||||
return 0, 0, "", gerror.New("表中必须包含`tree`字段")
|
||||
}
|
||||
|
||||
newPid = oldPid
|
||||
newLevel = level.Int() + 1
|
||||
subTree = tree.GenLabel(supTree.String(), oldPid)
|
||||
return
|
||||
}
|
||||
|
146
server/internal/library/hgorm/dao_tree.go
Normal file
146
server/internal/library/hgorm/dao_tree.go
Normal file
@ -0,0 +1,146 @@
|
||||
// Package hgorm
|
||||
// @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 hgorm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"hotgo/internal/model"
|
||||
"hotgo/utility/tree"
|
||||
"hotgo/utility/validate"
|
||||
)
|
||||
|
||||
// GenSubTree 生成下级关系树
|
||||
func GenSubTree(ctx context.Context, dao daoInstance, oldPid int64) (newPid int64, newLevel int, subTree string, err error) {
|
||||
if err = CheckTreeTable(ctx, dao); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if oldPid <= 0 {
|
||||
return 0, 1, "", nil
|
||||
}
|
||||
|
||||
var models *model.DefaultTree
|
||||
if err = dao.Ctx(ctx).WherePri(oldPid).Scan(&models); err != nil {
|
||||
return 0, 0, "", err
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
return 0, 0, "", gerror.New("上级信息不存在")
|
||||
}
|
||||
|
||||
newPid = oldPid
|
||||
newLevel = models.Level + 1
|
||||
subTree = tree.GenLabel(models.Tree, oldPid)
|
||||
return
|
||||
}
|
||||
|
||||
// CheckTreeTable 检查树表
|
||||
func CheckTreeTable(ctx context.Context, dao daoInstance) (err error) {
|
||||
fields, err := GetFieldsToSlice(ctx, dao)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !validate.InSlice(fields, "pid") {
|
||||
return gerror.New("树表必须包含`pid`字段")
|
||||
}
|
||||
|
||||
if !validate.InSlice(fields, "level") {
|
||||
return gerror.New("树表必须包含`level`字段")
|
||||
}
|
||||
|
||||
if !validate.InSlice(fields, "tree") {
|
||||
return gerror.New("树表必须包含`tree`字段")
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AutoUpdateTree 自动更新关系树
|
||||
func AutoUpdateTree(ctx context.Context, dao daoInstance, id, pid int64) (newPid int64, newLevel int, newTree string, err error) {
|
||||
if err = CheckTreeTable(ctx, dao); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if pid <= 0 {
|
||||
newPid = 0
|
||||
newLevel = 1
|
||||
newTree = ""
|
||||
} else {
|
||||
var pd *model.DefaultTree
|
||||
if err = dao.Ctx(ctx).WherePri(pid).Scan(&pd); err != nil {
|
||||
return 0, 0, "", err
|
||||
}
|
||||
|
||||
if pd == nil {
|
||||
return 0, 0, "", gerror.New("未查询到树表上级信息,请检查!")
|
||||
}
|
||||
|
||||
if id > 0 && validate.InSlice(tree.GetIds(pd.Tree), id) {
|
||||
return 0, 0, "", gerror.New("上级不能设为自己当前的子级!")
|
||||
}
|
||||
|
||||
newPid = pid
|
||||
newLevel = pd.Level + 1
|
||||
newTree = tree.GenLabel(pd.Tree, pid)
|
||||
}
|
||||
|
||||
if id > 0 {
|
||||
if pid == id {
|
||||
return 0, 0, "", gerror.New("上级不能是自己!")
|
||||
}
|
||||
|
||||
var models *model.DefaultTree
|
||||
if err = dao.Ctx(ctx).WherePri(id).Scan(&models); err != nil {
|
||||
return 0, 0, "", err
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
return 0, 0, "", gerror.New("树表信息不存在,请检查!")
|
||||
}
|
||||
|
||||
// 上级发生变化时,遍历修改其所有的下级关系树
|
||||
if models.Pid != pid {
|
||||
if err = updateChildrenTree(ctx, dao, models.Id, newLevel, newTree); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// updateChildrenTree 更新下级关系树
|
||||
func updateChildrenTree(ctx context.Context, dao daoInstance, pid int64, pLevel int, pTree string) (err error) {
|
||||
var list []*model.DefaultTree
|
||||
if err = dao.Ctx(ctx).Where("pid", pid).Scan(&list); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if len(list) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
newLevel := pLevel + 1
|
||||
newTree := tree.GenLabel(pTree, pid)
|
||||
|
||||
var updateIds []int64
|
||||
for _, v := range list {
|
||||
updateIds = append(updateIds, v.Id)
|
||||
if err = updateChildrenTree(ctx, dao, v.Id, newLevel, newTree); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if len(updateIds) > 0 {
|
||||
update := g.Map{
|
||||
"level": newLevel,
|
||||
"tree": newTree,
|
||||
}
|
||||
_, err = dao.Ctx(ctx).WhereIn("id", updateIds).Data(update).Update()
|
||||
}
|
||||
return
|
||||
}
|
@ -104,7 +104,7 @@ func Sorter(in ISorter) func(m *gdb.Model) *gdb.Model {
|
||||
// 不存在排序条件,默认使用主表主键做降序排序
|
||||
var pk string
|
||||
for name, field := range fields {
|
||||
if gstr.ContainsI(field.Key, consts.GenCodesIndexPK) {
|
||||
if gstr.ContainsI(gstr.ToUpper(field.Key), gstr.ToUpper(consts.GenCodesIndexPK)) {
|
||||
pk = name
|
||||
break
|
||||
}
|
||||
|
@ -48,6 +48,10 @@ type Conn struct {
|
||||
|
||||
var idCounter int64
|
||||
|
||||
var pkgOption = gtcp.PkgOption{
|
||||
MaxDataSize: 0x7FFFFFFF,
|
||||
}
|
||||
|
||||
func NewConn(conn *gtcp.Conn, logger *glog.Logger, msgParser *MsgParser) *Conn {
|
||||
tcpConn := new(Conn)
|
||||
tcpConn.CID = atomic.AddInt64(&idCounter, 1)
|
||||
@ -66,6 +70,7 @@ func NewConn(conn *gtcp.Conn, logger *glog.Logger, msgParser *MsgParser) *Conn {
|
||||
break
|
||||
}
|
||||
if err := conn.SendPkg(b); err != nil {
|
||||
logger.Errorf(gctx.New(), "SendPkg err:%+v", err)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
@ -50,6 +50,8 @@ func New(name ...string) UploadDrive {
|
||||
drive = &OssDrive{}
|
||||
case consts.UploadDriveQiNiu:
|
||||
drive = &QiNiuDrive{}
|
||||
case consts.UploadDriveMinio:
|
||||
drive = &MinioDrive{}
|
||||
default:
|
||||
panic(fmt.Sprintf("暂不支持的存储驱动:%v", driveType))
|
||||
}
|
||||
@ -82,6 +84,11 @@ func DoUpload(ctx context.Context, typ string, file *ghttp.UploadFile) (result *
|
||||
err = gerror.Newf("图片大小不能超过%vMB", config.ImageSize)
|
||||
return
|
||||
}
|
||||
|
||||
if len(config.ImageType) > 0 && !validate.InSlice(strings.Split(config.ImageType, `,`), meta.Ext) {
|
||||
err = gerror.New("上传图片类型未经允许")
|
||||
return
|
||||
}
|
||||
case KindDoc:
|
||||
if !IsDocType(meta.Ext) {
|
||||
err = gerror.New("上传的文件不是文档")
|
||||
@ -110,6 +117,11 @@ func DoUpload(ctx context.Context, typ string, file *ghttp.UploadFile) (result *
|
||||
err = gerror.Newf("文件大小不能超过%vMB", config.FileSize)
|
||||
return
|
||||
}
|
||||
|
||||
if len(config.FileType) > 0 && !validate.InSlice(strings.Split(config.FileType, `,`), meta.Ext) {
|
||||
err = gerror.New("上传文件类型未经允许")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
result, err = hasFile(ctx, meta.Md5)
|
||||
@ -148,6 +160,8 @@ func LastUrl(ctx context.Context, fullPath, drive string) string {
|
||||
return config.OssBucketURL + "/" + fullPath
|
||||
case consts.UploadDriveQiNiu:
|
||||
return config.QiNiuDomain + "/" + fullPath
|
||||
case consts.UploadDriveMinio:
|
||||
return fmt.Sprintf("%s/%s/%s", config.MinioDomain, config.MinioBucket, fullPath)
|
||||
default:
|
||||
return fullPath
|
||||
}
|
||||
|
64
server/internal/library/storager/upload_minio.go
Normal file
64
server/internal/library/storager/upload_minio.go
Normal file
@ -0,0 +1,64 @@
|
||||
// Package storager
|
||||
// @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 storager
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/os/gfile"
|
||||
"github.com/minio/minio-go/v7"
|
||||
"github.com/minio/minio-go/v7/pkg/credentials"
|
||||
"github.com/minio/minio-go/v7/pkg/s3utils"
|
||||
"mime"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// MinioDrive minio对象存储驱动
|
||||
type MinioDrive struct {
|
||||
}
|
||||
|
||||
// Upload 上传到minio对象存储
|
||||
func (d *MinioDrive) Upload(ctx context.Context, file *ghttp.UploadFile) (fullPath string, err error) {
|
||||
if config.MinioPath == "" {
|
||||
err = gerror.New("minio存储驱动必须配置存储路径!")
|
||||
return
|
||||
}
|
||||
|
||||
client, err := minio.New(config.MinioEndpoint, &minio.Options{
|
||||
Creds: credentials.NewStaticV4(config.MinioAccessKey, config.MinioSecretKey, ""),
|
||||
Secure: config.MinioUseSSL == 1,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if err = s3utils.CheckValidBucketName(config.MinioBucket); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
fullPath = GenFullPath(config.MinioPath, gfile.Ext(file.Filename))
|
||||
if err = s3utils.CheckValidObjectName(fullPath); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
reader, err := file.Open()
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer reader.Close()
|
||||
|
||||
opts := minio.PutObjectOptions{
|
||||
ContentType: mime.TypeByExtension(filepath.Ext(file.Filename)),
|
||||
}
|
||||
if opts.ContentType == "" {
|
||||
opts.ContentType = "application/octet-stream"
|
||||
}
|
||||
|
||||
_, err = client.PutObject(ctx, config.MinioBucket, fullPath, reader, file.Size, opts)
|
||||
return
|
||||
}
|
@ -15,7 +15,6 @@ import (
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/grand"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
@ -403,28 +402,39 @@ func (s *sAdminMember) VerifyUnique(ctx context.Context, in *adminin.VerifyUniqu
|
||||
|
||||
// Delete 删除用户
|
||||
func (s *sAdminMember) Delete(ctx context.Context, in *adminin.MemberDeleteInp) (err error) {
|
||||
if s.VerifySuperId(ctx, gconv.Int64(in.Id)) {
|
||||
err = gerror.New("超管账号禁止删除!")
|
||||
return
|
||||
}
|
||||
|
||||
memberId := contexts.GetUserId(ctx)
|
||||
if memberId <= 0 {
|
||||
err = gerror.New("获取用户信息失败!")
|
||||
return
|
||||
}
|
||||
|
||||
var models *entity.AdminMember
|
||||
if err = s.FilterAuthModel(ctx, memberId).WherePri(in.Id).Scan(&models); err != nil {
|
||||
var list []*entity.AdminMember
|
||||
if err = s.FilterAuthModel(ctx, memberId).WherePri(in.Id).Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, "获取用户信息失败,请稍后重试!")
|
||||
return
|
||||
}
|
||||
|
||||
if models == nil {
|
||||
if len(list) == 0 {
|
||||
err = gerror.New("需要删除的用户不存在或已删除!")
|
||||
return
|
||||
}
|
||||
|
||||
for _, v := range list {
|
||||
if s.VerifySuperId(ctx, v.Id) {
|
||||
err = gerror.New("超管账号禁止删除!")
|
||||
return
|
||||
}
|
||||
count, err := dao.AdminMember.Ctx(ctx).Where("pid", v.Id).Count()
|
||||
if err != nil {
|
||||
err = gerror.Wrap(err, "删除用户检查失败,请稍后重试!")
|
||||
return err
|
||||
}
|
||||
if count > 0 {
|
||||
err = gerror.Newf("用户[%v]存在下级,请先删除TA的下级用户!", v.Id)
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
|
||||
if _, err = s.FilterAuthModel(ctx, memberId).WherePri(in.Id).Delete(); err != nil {
|
||||
err = gerror.Wrap(err, "删除用户失败,请稍后重试!")
|
||||
@ -434,6 +444,9 @@ func (s *sAdminMember) Delete(ctx context.Context, in *adminin.MemberDeleteInp)
|
||||
if _, err = dao.AdminMemberPost.Ctx(ctx).Where("member_id", in.Id).Delete(); err != nil {
|
||||
err = gerror.Wrap(err, "删除用户岗位失败,请稍后重试!")
|
||||
}
|
||||
|
||||
// 这里如果需要,可以加入更多删除用户的相关处理
|
||||
// ...
|
||||
return
|
||||
})
|
||||
}
|
||||
@ -603,6 +616,14 @@ func (s *sAdminMember) List(ctx context.Context, in *adminin.MemberListInp) (lis
|
||||
mod = mod.Where(cols.RoleId, in.RoleId)
|
||||
}
|
||||
|
||||
if in.Id > 0 {
|
||||
mod = mod.Where(cols.Id, in.Id)
|
||||
}
|
||||
|
||||
if in.Pid > 0 {
|
||||
mod = mod.Where(cols.Pid, in.Pid)
|
||||
}
|
||||
|
||||
if len(in.CreatedAt) == 2 {
|
||||
mod = mod.WhereBetween(cols.CreatedAt, gtime.New(in.CreatedAt[0]), gtime.New(in.CreatedAt[1]))
|
||||
}
|
||||
|
@ -7,22 +7,23 @@ package admin
|
||||
|
||||
import (
|
||||
"context"
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/frame/g"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
"github.com/gogf/gf/v2/text/gstr"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"github.com/gogf/gf/v2/util/gmode"
|
||||
"hotgo/api/admin/role"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/dao"
|
||||
"hotgo/internal/library/casbin"
|
||||
"hotgo/internal/library/contexts"
|
||||
"hotgo/internal/library/hgorm"
|
||||
"hotgo/internal/model/do"
|
||||
"hotgo/internal/model/entity"
|
||||
"hotgo/internal/model/input/adminin"
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/convert"
|
||||
"hotgo/utility/validate"
|
||||
)
|
||||
|
||||
type sAdminMenu struct{}
|
||||
@ -91,44 +92,25 @@ func (s *sAdminMenu) Edit(ctx context.Context, in *adminin.MenuEditInp) (err err
|
||||
return
|
||||
}
|
||||
|
||||
var pd *do.AdminMenu
|
||||
|
||||
// 维护菜单等级
|
||||
if in.Pid == 0 {
|
||||
in.Level = 1
|
||||
} else {
|
||||
if err = dao.AdminMenu.Ctx(ctx).Where("id", in.Pid).Scan(&pd); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
in.Pid, in.Level, in.Tree, err = hgorm.AutoUpdateTree(ctx, &dao.AdminMenu, in.Id, in.Pid)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if pd == nil {
|
||||
return gerror.New("上级菜单信息错误")
|
||||
}
|
||||
in.Level = gconv.Int(pd.Level) + 1
|
||||
}
|
||||
|
||||
// 修改
|
||||
in.UpdatedAt = gtime.Now()
|
||||
if in.Id > 0 {
|
||||
if in.Pid == in.Id {
|
||||
return gerror.New("上级菜单不能是当前菜单")
|
||||
}
|
||||
|
||||
if _, err = dao.AdminMenu.Ctx(ctx).Where("id", in.Id).Data(in).Update(); err != nil {
|
||||
err = gerror.Wrap(err, "修改菜单失败!")
|
||||
return err
|
||||
if in.Id > 0 {
|
||||
if _, err = dao.AdminMenu.Ctx(ctx).Where("id", in.Id).Data(in).Update(); err != nil {
|
||||
err = gerror.Wrap(err, "修改菜单失败!")
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if _, err = dao.AdminMenu.Ctx(ctx).Data(in).Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增菜单失败!")
|
||||
return err
|
||||
}
|
||||
}
|
||||
return casbin.Refresh(ctx)
|
||||
}
|
||||
|
||||
// 新增
|
||||
in.CreatedAt = gtime.Now()
|
||||
|
||||
if _, err = dao.AdminMenu.Ctx(ctx).Data(in).Insert(); err != nil {
|
||||
err = gerror.Wrap(err, "新增菜单失败!")
|
||||
return err
|
||||
}
|
||||
return casbin.Refresh(ctx)
|
||||
})
|
||||
}
|
||||
|
||||
// List 获取菜单列表
|
||||
@ -215,6 +197,18 @@ func (s *sAdminMenu) GetMenuList(ctx context.Context, memberId int64) (res *role
|
||||
return
|
||||
}
|
||||
|
||||
// 生产环境下隐藏一些菜单
|
||||
if gmode.IsProduct() {
|
||||
newMenus := make([]*adminin.MenuRouteSummary, 0)
|
||||
devMenus := []string{"Develops", "doc"} // 如果你还有其他需要在生产环境隐藏的菜单,将菜单别名加入即可
|
||||
for _, menu := range allMenus {
|
||||
if !validate.InSlice(devMenus, menu.Name) {
|
||||
newMenus = append(newMenus, menu)
|
||||
}
|
||||
}
|
||||
allMenus = newMenus
|
||||
}
|
||||
|
||||
for _, v := range allMenus {
|
||||
treeMap[gconv.String(v.Pid)] = append(treeMap[gconv.String(v.Pid)], v)
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ func (s *sHook) accessLog(r *ghttp.Request) {
|
||||
}
|
||||
|
||||
contexts.SetDataMap(ctx, g.Map{
|
||||
"request.takeUpTime": gtime.TimestampMilli() - r.EnterTime,
|
||||
"request.takeUpTime": gtime.Now().Sub(gtime.New(r.EnterTime)).Milliseconds(),
|
||||
// ...
|
||||
})
|
||||
|
||||
|
@ -63,12 +63,18 @@ func (s *sMiddleware) Ctx(r *ghttp.Request) {
|
||||
r.SetCtx(ctx)
|
||||
}
|
||||
|
||||
data := g.Map{
|
||||
"request.body": gjson.New(r.GetBodyString()),
|
||||
}
|
||||
|
||||
contexts.Init(r, &model.Context{
|
||||
Data: make(g.Map),
|
||||
Data: data,
|
||||
Module: getModule(r.URL.Path),
|
||||
})
|
||||
|
||||
contexts.SetData(r.Context(), "request.body", gjson.New(r.GetBodyString()))
|
||||
if len(r.Cookie.GetSessionId()) == 0 {
|
||||
r.Cookie.SetSessionId(gctx.CtxId(r.Context()))
|
||||
}
|
||||
r.Middleware.Next()
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
package middleware
|
||||
|
||||
import (
|
||||
"github.com/gogf/gf/v2/errors/gcode"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/net/ghttp"
|
||||
"github.com/gogf/gf/v2/util/gconv"
|
||||
"hotgo/internal/library/response"
|
||||
@ -68,7 +68,8 @@ func (s *sMiddleware) PreFilter(r *ghttp.Request) {
|
||||
|
||||
// 先验证基本校验规则
|
||||
if err := r.Parse(inputObject.Interface()); err != nil {
|
||||
response.JsonExit(r, gcode.CodeInvalidRequest.Code(), err.Error())
|
||||
resp := gerror.Code(err)
|
||||
response.JsonExit(r, resp.Code(), gerror.Current(err).Error(), resp.Detail())
|
||||
return
|
||||
}
|
||||
|
||||
@ -80,7 +81,8 @@ func (s *sMiddleware) PreFilter(r *ghttp.Request) {
|
||||
|
||||
// 执行预处理
|
||||
if err := validate.PreFilter(r.Context(), inputObject.Interface()); err != nil {
|
||||
response.JsonExit(r, gcode.CodeInvalidParameter.Code(), err.Error())
|
||||
resp := gerror.Code(err)
|
||||
response.JsonExit(r, resp.Code(), gerror.Current(err).Error(), resp.Detail())
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -87,8 +87,10 @@ func parseResponse(r *ghttp.Request) (code int, message string, resp interface{}
|
||||
code = gerror.Code(err).Code()
|
||||
|
||||
// 记录异常日志
|
||||
// 如果你想对错误做不同的处理,可以通过定义不同的错误码来区分
|
||||
// 默认-1为安全可控错误码只记录文件日志,非-1为不可控错误,记录文件日志+服务日志并打印堆栈
|
||||
if code == gcode.CodeNil.Code() {
|
||||
g.Log().Stdout(false).Printf(ctx, "exception:%v", err)
|
||||
g.Log().Stdout(false).Infof(ctx, "exception:%v", err)
|
||||
} else {
|
||||
g.Log().Errorf(ctx, "exception:%v", err)
|
||||
}
|
||||
|
@ -20,7 +20,6 @@ import (
|
||||
"hotgo/internal/service"
|
||||
"hotgo/utility/simple"
|
||||
"hotgo/utility/validate"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type sSysCron struct{}
|
||||
@ -90,7 +89,16 @@ func (s *sSysCron) Edit(ctx context.Context, in *sysin.CronEditInp) (err error)
|
||||
}
|
||||
|
||||
// 新增
|
||||
_, err = dao.SysCron.Ctx(ctx).Data(in).Insert()
|
||||
in.SysCron.Id, err = dao.SysCron.Ctx(ctx).Data(in).InsertAndGetId()
|
||||
if err != nil || in.SysCron.Id < 1 {
|
||||
return
|
||||
}
|
||||
|
||||
if in.SysCron.Status == consts.StatusEnabled {
|
||||
simple.SafeGo(ctx, func(ctx context.Context) {
|
||||
_ = cron.Start(&in.SysCron)
|
||||
})
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@ -163,6 +171,10 @@ func (s *sSysCron) List(ctx context.Context, in *sysin.CronListInp) (list []*sys
|
||||
mod = mod.WhereLike("name", "%"+in.Name+"%")
|
||||
}
|
||||
|
||||
if in.GroupId > 0 {
|
||||
mod = mod.Where("group_id", in.GroupId)
|
||||
}
|
||||
|
||||
if in.Status > 0 {
|
||||
mod = mod.Where("status", in.Status)
|
||||
}
|
||||
@ -210,7 +222,22 @@ func (s *sSysCron) OnlineExec(ctx context.Context, in *sysin.OnlineExecInp) (err
|
||||
err = gerror.New("定时任务不存在")
|
||||
return
|
||||
}
|
||||
|
||||
newCtx := context.WithValue(gctx.New(), consts.ContextKeyCronArgs, strings.Split(data.Params, consts.CronSplitStr))
|
||||
return cron.Once(newCtx, data)
|
||||
return cron.Once(gctx.New(), data)
|
||||
}
|
||||
|
||||
// DispatchLog 查看指定任务的调度日志
|
||||
func (s *sSysCron) DispatchLog(ctx context.Context, in *sysin.DispatchLogInp) (res *sysin.DispatchLogModel, err error) {
|
||||
var data *entity.SysCron
|
||||
if err = dao.SysCron.Ctx(ctx).Where(dao.SysCron.Columns().Id, in.Id).Scan(&data); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if data == nil {
|
||||
err = gerror.New("定时任务不存在")
|
||||
return
|
||||
}
|
||||
|
||||
res = new(sysin.DispatchLogModel)
|
||||
res.Log, err = cron.DispatchLog(data)
|
||||
return
|
||||
}
|
||||
|
@ -107,6 +107,17 @@ func (s *sSysCronGroup) List(ctx context.Context, in *sysin.CronGroupListInp) (l
|
||||
if err = mod.Page(in.Page, in.PerPage).Order("id desc").Scan(&list); err != nil {
|
||||
err = gerror.Wrap(err, consts.ErrorORM)
|
||||
}
|
||||
|
||||
for _, v := range list {
|
||||
if v.Pid < 1 {
|
||||
continue
|
||||
}
|
||||
name, err := dao.SysCronGroup.Ctx(ctx).Fields("name").WherePri(v.Pid).Value()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
v.SupName = name.String()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
// @Copyright Copyright (c) 2023 HotGo CLI
|
||||
// @Author Ms <133814250@qq.com>
|
||||
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
|
||||
// @AutoGenerate Version 2.9.3
|
||||
// @AutoGenerate Version 2.11.5
|
||||
package sys
|
||||
|
||||
import (
|
||||
|
@ -66,10 +66,11 @@ func (s *sCronClient) Start(ctx context.Context) {
|
||||
|
||||
// 注册RPC路由
|
||||
s.client.RegisterRPCRouter(
|
||||
s.OnCronDelete, // 删除任务
|
||||
s.OnCronEdit, // 编辑任务
|
||||
s.OnCronStatus, // 修改任务状态
|
||||
s.OnCronOnlineExec, // 执行一次任务
|
||||
s.OnCronDelete, // 删除任务
|
||||
s.OnCronEdit, // 编辑任务
|
||||
s.OnCronStatus, // 修改任务状态
|
||||
s.OnCronOnlineExec, // 执行一次任务
|
||||
s.OnCronDispatchLog, // 查看调度日志
|
||||
)
|
||||
|
||||
// 注册拦截器
|
||||
|
@ -34,3 +34,10 @@ func (s *sCronClient) OnCronOnlineExec(ctx context.Context, req *servmsg.CronOnl
|
||||
err = service.SysCron().OnlineExec(ctx, req.OnlineExecInp)
|
||||
return
|
||||
}
|
||||
|
||||
// OnCronDispatchLog 查看调度日志
|
||||
func (s *sCronClient) OnCronDispatchLog(ctx context.Context, req *servmsg.CronDispatchLogReq) (res *servmsg.CronDispatchLogRes, err error) {
|
||||
res = new(servmsg.CronDispatchLogRes)
|
||||
res.DispatchLogModel, err = service.SysCron().DispatchLog(ctx, req.DispatchLogInp)
|
||||
return
|
||||
}
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"hotgo/api/servmsg"
|
||||
"hotgo/internal/consts"
|
||||
"hotgo/internal/library/cron"
|
||||
)
|
||||
|
||||
// CronDelete 删除任务
|
||||
@ -95,3 +96,22 @@ func (s *sTCPServer) CronOnlineExec(ctx context.Context, in *servmsg.CronOnlineE
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DispatchLog 查看调度日志
|
||||
func (s *sTCPServer) DispatchLog(ctx context.Context, in *servmsg.CronDispatchLogReq) (log *cron.Log, err error) {
|
||||
clients := s.serv.GetGroupClients(consts.LicenseGroupCron)
|
||||
if len(clients) == 0 {
|
||||
err = gerror.New("没有在线的定时任务服务")
|
||||
return
|
||||
}
|
||||
|
||||
var res servmsg.CronDispatchLogRes
|
||||
if err = s.serv.RequestScan(ctx, clients[0], in, &res); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if err = res.GetError(); err != nil {
|
||||
return
|
||||
}
|
||||
return res.Log, nil
|
||||
}
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user