This commit is contained in:
孟帅
2024-04-22 23:08:40 +08:00
parent 82483bd7b9
commit e144b12580
445 changed files with 17457 additions and 6708 deletions

View File

@@ -13,18 +13,18 @@ import (
// ListReq 查询列表
type ListReq struct {
g.Meta `path:"/table/list" method:"get" tags:"表格" summary:"获取表格列表"`
g.Meta `path:"/table/list" method:"get" tags:"表格例子" summary:"获取表格列表"`
sysin.TableListInp
}
type ListRes struct {
form.PageRes
List []*sysin.TableListModel `json:"list" dc:"数据列表"`
List []*sysin.TableListModel `json:"list" dc:"数据列表"`
}
// ExportReq 导出列表
type ExportReq struct {
g.Meta `path:"/table/export" method:"get" tags:"表格" summary:"导出表格列表"`
g.Meta `path:"/table/export" method:"get" tags:"表格例子" summary:"导出表格列表"`
sysin.TableListInp
}
@@ -32,7 +32,7 @@ type ExportRes struct{}
// ViewReq 获取信息
type ViewReq struct {
g.Meta `path:"/table/view" method:"get" tags:"表格" summary:"获取指定信息"`
g.Meta `path:"/table/view" method:"get" tags:"表格例子" summary:"获取指定信息"`
sysin.TableViewInp
}
@@ -42,7 +42,7 @@ type ViewRes struct {
// EditReq 修改/新增
type EditReq struct {
g.Meta `path:"/table/edit" method:"post" tags:"表格" summary:"修改/新增表格"`
g.Meta `path:"/table/edit" method:"post" tags:"表格例子" summary:"修改/新增表格"`
sysin.TableEditInp
}
@@ -50,7 +50,7 @@ type EditRes struct{}
// DeleteReq 删除
type DeleteReq struct {
g.Meta `path:"/table/delete" method:"post" tags:"表格" summary:"删除表格"`
g.Meta `path:"/table/delete" method:"post" tags:"表格例子" summary:"删除表格"`
sysin.TableDeleteInp
}
@@ -58,7 +58,7 @@ type DeleteRes struct{}
// MaxSortReq 最大排序
type MaxSortReq struct {
g.Meta `path:"/table/maxSort" method:"get" tags:"表格" summary:"表格最大排序"`
g.Meta `path:"/table/maxSort" method:"get" tags:"表格例子" summary:"表格最大排序"`
sysin.TableMaxSortInp
}
@@ -68,7 +68,7 @@ type MaxSortRes struct {
// StatusReq 更新状态
type StatusReq struct {
g.Meta `path:"/table/status" method:"post" tags:"表格" summary:"更新表格状态"`
g.Meta `path:"/table/status" method:"post" tags:"表格例子" summary:"更新表格状态"`
sysin.TableStatusInp
}
@@ -76,7 +76,7 @@ type StatusRes struct{}
// SwitchReq 更新开关状态
type SwitchReq struct {
g.Meta `path:"/table/switch" method:"post" tags:"表格" summary:"更新表格状态"`
g.Meta `path:"/table/switch" method:"post" tags:"表格例子" summary:"更新表格状态"`
sysin.TableSwitchInp
}

View File

@@ -0,0 +1,59 @@
// Package tenantorder
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package tenantorder
import (
"hotgo/addons/hgexample/model/input/sysin"
"hotgo/internal/model/input/form"
"github.com/gogf/gf/v2/frame/g"
)
// ListReq 查询多租户功能演示列表
type ListReq struct {
g.Meta `path:"/tenantOrder/list" method:"get" tags:"多租户功能演示" summary:"获取多租户功能演示列表"`
sysin.TenantOrderListInp
}
type ListRes struct {
form.PageRes
List []*sysin.TenantOrderListModel `json:"list" dc:"数据列表"`
}
// ExportReq 导出多租户功能演示列表
type ExportReq struct {
g.Meta `path:"/tenantOrder/export" method:"get" tags:"多租户功能演示" summary:"导出多租户功能演示列表"`
sysin.TenantOrderListInp
}
type ExportRes struct{}
// ViewReq 获取多租户功能演示指定信息
type ViewReq struct {
g.Meta `path:"/tenantOrder/view" method:"get" tags:"多租户功能演示" summary:"获取多租户功能演示指定信息"`
sysin.TenantOrderViewInp
}
type ViewRes struct {
*sysin.TenantOrderViewModel
}
// EditReq 修改/新增多租户功能演示
type EditReq struct {
g.Meta `path:"/tenantOrder/edit" method:"post" tags:"多租户功能演示" summary:"修改/新增多租户功能演示"`
sysin.TenantOrderEditInp
}
type EditRes struct{}
// DeleteReq 删除多租户功能演示
type DeleteReq struct {
g.Meta `path:"/tenantOrder/delete" method:"post" tags:"多租户功能演示" summary:"删除多租户功能演示"`
sysin.TenantOrderDeleteInp
}
type DeleteRes struct{}

View File

@@ -13,7 +13,7 @@ import (
// ListReq 查询列表
type ListReq struct {
g.Meta `path:"/treeTable/list" method:"get" tags:"表格" summary:"获取表格列表"`
g.Meta `path:"/treeTable/list" method:"get" tags:"树形表格例子" summary:"获取表格列表"`
sysin.TreeTableListInp
}
@@ -24,7 +24,7 @@ type ListRes struct {
// ExportReq 导出列表
type ExportReq struct {
g.Meta `path:"/treeTable/export" method:"get" tags:"表格" summary:"导出表格列表"`
g.Meta `path:"/treeTable/export" method:"get" tags:"树形表格例子" summary:"导出表格列表"`
sysin.TableListInp
}
@@ -32,7 +32,7 @@ type ExportRes struct{}
// ViewReq 获取信息
type ViewReq struct {
g.Meta `path:"/treeTable/view" method:"get" tags:"表格" summary:"获取指定信息"`
g.Meta `path:"/treeTable/view" method:"get" tags:"树形表格例子" summary:"获取指定信息"`
sysin.TableViewInp
}
@@ -42,7 +42,7 @@ type ViewRes struct {
// EditReq 修改/新增
type EditReq struct {
g.Meta `path:"/treeTable/edit" method:"post" tags:"表格" summary:"修改/新增表格"`
g.Meta `path:"/treeTable/edit" method:"post" tags:"树形表格例子" summary:"修改/新增表格"`
sysin.TableEditInp
}
@@ -50,7 +50,7 @@ type EditRes struct{}
// DeleteReq 删除
type DeleteReq struct {
g.Meta `path:"/treeTable/delete" method:"post" tags:"表格" summary:"删除表格"`
g.Meta `path:"/treeTable/delete" method:"post" tags:"树形表格例子" summary:"删除表格"`
sysin.TableDeleteInp
}
@@ -58,7 +58,7 @@ type DeleteRes struct{}
// MaxSortReq 最大排序
type MaxSortReq struct {
g.Meta `path:"/treeTable/maxSort" method:"get" tags:"表格" summary:"表格最大排序"`
g.Meta `path:"/treeTable/maxSort" method:"get" tags:"树形表格例子" summary:"表格最大排序"`
sysin.TableMaxSortInp
}
@@ -68,7 +68,7 @@ type MaxSortRes struct {
// StatusReq 更新状态
type StatusReq struct {
g.Meta `path:"/treeTable/status" method:"post" tags:"表格" summary:"更新表格状态"`
g.Meta `path:"/treeTable/status" method:"post" tags:"树形表格例子" summary:"更新表格状态"`
sysin.TableStatusInp
}
@@ -76,7 +76,7 @@ type StatusRes struct{}
// SwitchReq 更新开关状态
type SwitchReq struct {
g.Meta `path:"/treeTable/switch" method:"post" tags:"表格" summary:"更新表格状态"`
g.Meta `path:"/treeTable/switch" method:"post" tags:"树形表格例子" summary:"更新表格状态"`
sysin.TableSwitchInp
}
@@ -84,7 +84,7 @@ type SwitchRes struct{}
// SelectReq 树形选项
type SelectReq struct {
g.Meta `path:"/treeTable/select" method:"get" tags:"表格" summary:"树形选项"`
g.Meta `path:"/treeTable/select" method:"get" tags:"树形表格例子" summary:"树形选项"`
}
type SelectRes struct {

View File

@@ -12,7 +12,7 @@ import (
// TestReq 测试
type TestReq struct {
g.Meta `path:"/index/test" method:"get" summary:"功能案例" tags:"测试首页"`
g.Meta `path:"/index/test" method:"get" tags:"功能案例" summary:"测试首页"`
sysin.IndexTestInp
}

View File

@@ -20,10 +20,10 @@ type cComp struct{}
// ImportExcel 导入Excel
func (c *cComp) ImportExcel(ctx context.Context, req *comp.ImportExcelReq) (res *comp.ImportExcelRes, err error) {
file, err := req.File.Open()
defer file.Close()
if err != nil {
return
}
defer file.Close()
excel, err := excelize.OpenReader(file)
if err != nil {

View File

@@ -0,0 +1,67 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package sys
import (
"context"
"hotgo/addons/hgexample/api/admin/tenantorder"
"hotgo/addons/hgexample/model/input/sysin"
"hotgo/addons/hgexample/service"
)
var (
TenantOrder = cTenantOrder{}
)
type cTenantOrder struct{}
// List 查看多租户功能演示列表
func (c *cTenantOrder) List(ctx context.Context, req *tenantorder.ListReq) (res *tenantorder.ListRes, err error) {
list, totalCount, err := service.SysTenantOrder().List(ctx, &req.TenantOrderListInp)
if err != nil {
return
}
if list == nil {
list = []*sysin.TenantOrderListModel{}
}
res = new(tenantorder.ListRes)
res.List = list
res.PageRes.Pack(req, totalCount)
return
}
// Export 导出多租户功能演示列表
func (c *cTenantOrder) Export(ctx context.Context, req *tenantorder.ExportReq) (res *tenantorder.ExportRes, err error) {
err = service.SysTenantOrder().Export(ctx, &req.TenantOrderListInp)
return
}
// Edit 更新多租户功能演示
func (c *cTenantOrder) Edit(ctx context.Context, req *tenantorder.EditReq) (res *tenantorder.EditRes, err error) {
err = service.SysTenantOrder().Edit(ctx, &req.TenantOrderEditInp)
return
}
// View 获取指定多租户功能演示信息
func (c *cTenantOrder) View(ctx context.Context, req *tenantorder.ViewReq) (res *tenantorder.ViewRes, err error) {
data, err := service.SysTenantOrder().View(ctx, &req.TenantOrderViewInp)
if err != nil {
return
}
res = new(tenantorder.ViewRes)
res.TenantOrderViewModel = data
return
}
// Delete 删除多租户功能演示
func (c *cTenantOrder) Delete(ctx context.Context, req *tenantorder.DeleteReq) (res *tenantorder.DeleteRes, err error) {
err = service.SysTenantOrder().Delete(ctx, &req.TenantOrderDeleteInp)
return
}

View File

@@ -119,7 +119,7 @@ func (s *sSysTable) Export(ctx context.Context, in *sysin.TableListInp) (err err
}
var (
fileName = "表格例子导出-" + gctx.CtxId(ctx) + ".xlsx"
fileName = "表格例子导出-" + gctx.CtxId(ctx)
sheetName = fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", totalCount, form.CalPageCount(totalCount, in.PerPage), in.Page, len(list))
exports []sysin.TableExportModel
)

View File

@@ -0,0 +1,176 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package sys
import (
"context"
"fmt"
"hotgo/addons/hgexample/model/input/sysin"
"hotgo/addons/hgexample/service"
"hotgo/internal/dao"
"hotgo/internal/library/hgorm/handler"
"hotgo/internal/library/hgorm/hook"
"hotgo/internal/model/input/form"
"hotgo/utility/convert"
"hotgo/utility/excel"
"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/gctx"
"github.com/gogf/gf/v2/util/gconv"
)
type sSysTenantOrder struct{}
func NewSysTenantOrder() *sSysTenantOrder {
return &sSysTenantOrder{}
}
func init() {
service.RegisterSysTenantOrder(NewSysTenantOrder())
}
// Model 多租户功能演示ORM模型
func (s *sSysTenantOrder) Model(ctx context.Context, option ...*handler.Option) *gdb.Model {
if len(option) == 0 {
// 过滤多租户数据权限
option = append(option, &handler.Option{
FilterTenant: true,
//FilterAuth: true, // 如果还需要维护created_by、member_id等部门数据权限范围可放开注释
})
}
return handler.Model(dao.AddonHgexampleTenantOrder.Ctx(ctx), option...)
}
// List 获取多租户功能演示列表
func (s *sSysTenantOrder) List(ctx context.Context, in *sysin.TenantOrderListInp) (list []*sysin.TenantOrderListModel, totalCount int, err error) {
mod := s.Model(ctx)
// 字段过滤
mod = mod.Fields(sysin.TenantOrderListModel{})
// 查询主键
if in.Id > 0 {
mod = mod.Where(dao.AddonHgexampleTenantOrder.Columns().Id, in.Id)
}
// 查询租户ID
if in.TenantId > 0 {
mod = mod.Where(dao.AddonHgexampleTenantOrder.Columns().TenantId, in.TenantId)
}
// 查询商户ID
if in.MerchantId > 0 {
mod = mod.Where(dao.AddonHgexampleTenantOrder.Columns().MerchantId, in.MerchantId)
}
// 查询用户ID
if in.UserId > 0 {
mod = mod.Where(dao.AddonHgexampleTenantOrder.Columns().UserId, in.UserId)
}
// 查询关联订单号
if in.OrderSn != "" {
mod = mod.Where(dao.AddonHgexampleTenantOrder.Columns().OrderSn, in.OrderSn)
}
// 查询支付状态
if in.Status > 0 {
mod = mod.Where(dao.AddonHgexampleTenantOrder.Columns().Status, in.Status)
}
// 查询创建时间
if len(in.CreatedAt) == 2 {
mod = mod.WhereBetween(dao.AddonHgexampleTenantOrder.Columns().CreatedAt, in.CreatedAt[0], in.CreatedAt[1])
}
// 分页
mod = mod.Page(in.Page, in.PerPage)
// 排序
mod = mod.OrderDesc(dao.AddonHgexampleTenantOrder.Columns().Id)
// 查询数据
if err = mod.ScanAndCount(&list, &totalCount, false); err != nil {
err = gerror.Wrap(err, "获取多租户功能演示列表失败,请稍后重试!")
return
}
return
}
// Export 导出多租户功能演示
func (s *sSysTenantOrder) Export(ctx context.Context, in *sysin.TenantOrderListInp) (err error) {
list, totalCount, err := s.List(ctx, in)
if err != nil {
return
}
// 字段的排序是依据tags的字段顺序如果你不想使用默认的排序方式可以直接定义 tags = []string{"字段名称", "字段名称2", ...}
tags, err := convert.GetEntityDescTags(sysin.TenantOrderExportModel{})
if err != nil {
return
}
var (
fileName = "导出多租户功能演示-" + gctx.CtxId(ctx)
sheetName = fmt.Sprintf("索引条件共%v行,共%v页,当前导出是第%v页,本页共%v行", totalCount, form.CalPageCount(totalCount, in.PerPage), in.Page, len(list))
exports []sysin.TenantOrderExportModel
)
if err = gconv.Scan(list, &exports); err != nil {
return
}
err = excel.ExportByStructs(ctx, tags, exports, fileName, sheetName)
return
}
// Edit 修改/新增多租户功能演示
func (s *sSysTenantOrder) Edit(ctx context.Context, in *sysin.TenantOrderEditInp) (err error) {
return g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) (err error) {
// 修改
if in.Id > 0 {
if _, err = s.Model(ctx).
Fields(sysin.TenantOrderUpdateFields{}).
WherePri(in.Id).Data(in).
Hook(hook.SaveTenant). // 自动维护租户关系更新
Update(); err != nil {
}
return
}
// 新增
if _, err = dao.AddonHgexampleTenantOrder.Ctx(ctx).
Fields(sysin.TenantOrderInsertFields{}).
Hook(hook.SaveTenant). // 自动维护租户关系更新
Data(in).
Insert(); err != nil {
}
return
})
}
// Delete 删除多租户功能演示
func (s *sSysTenantOrder) Delete(ctx context.Context, in *sysin.TenantOrderDeleteInp) (err error) {
if _, err = s.Model(ctx).WherePri(in.Id).Delete(); err != nil {
err = gerror.Wrap(err, "删除多租户功能演示失败,请稍后重试!")
return
}
return
}
// View 获取多租户功能演示指定信息
func (s *sSysTenantOrder) View(ctx context.Context, in *sysin.TenantOrderViewInp) (res *sysin.TenantOrderViewModel, err error) {
if err = s.Model(ctx).WherePri(in.Id).Scan(&res); err != nil {
err = gerror.Wrap(err, "获取多租户功能演示信息,请稍后重试!")
return
}
return
}

View File

@@ -0,0 +1,123 @@
// Package sysin
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package sysin
import (
"context"
"hotgo/internal/model/entity"
"hotgo/internal/model/input/form"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
)
// TenantOrderUpdateFields 修改多租户功能演示字段过滤
type TenantOrderUpdateFields struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
MerchantId int64 `json:"merchantId" dc:"商户ID"`
UserId int64 `json:"userId" dc:"用户ID"`
ProductName string `json:"productName" dc:"购买产品"`
OrderSn string `json:"orderSn" dc:"关联订单号"`
Money float64 `json:"money" dc:"充值金额"`
Remark string `json:"remark" dc:"备注"`
Status int `json:"status" dc:"支付状态"`
}
// TenantOrderInsertFields 新增多租户功能演示字段过滤
type TenantOrderInsertFields struct {
TenantId int64 `json:"tenantId" dc:"租户ID"`
MerchantId int64 `json:"merchantId" dc:"商户ID"`
UserId int64 `json:"userId" dc:"用户ID"`
ProductName string `json:"productName" dc:"购买产品"`
OrderSn string `json:"orderSn" dc:"关联订单号"`
Money float64 `json:"money" dc:"充值金额"`
Remark string `json:"remark" dc:"备注"`
Status int `json:"status" dc:"支付状态"`
}
// TenantOrderEditInp 修改/新增多租户功能演示
type TenantOrderEditInp struct {
entity.AddonHgexampleTenantOrder
}
func (in *TenantOrderEditInp) Filter(ctx context.Context) (err error) {
// 验证充值金额
if err := g.Validator().Rules("required").Data(in.Money).Messages("充值金额不能为空").Run(ctx); err != nil {
return err.Current()
}
return
}
type TenantOrderEditModel struct{}
// TenantOrderDeleteInp 删除多租户功能演示
type TenantOrderDeleteInp struct {
Id interface{} `json:"id" v:"required#主键不能为空" dc:"主键"`
}
func (in *TenantOrderDeleteInp) Filter(ctx context.Context) (err error) {
return
}
type TenantOrderDeleteModel struct{}
// TenantOrderViewInp 获取指定多租户功能演示信息
type TenantOrderViewInp struct {
Id int64 `json:"id" v:"required#主键不能为空" dc:"主键"`
}
func (in *TenantOrderViewInp) Filter(ctx context.Context) (err error) {
return
}
type TenantOrderViewModel struct {
entity.AddonHgexampleTenantOrder
}
// TenantOrderListInp 获取多租户功能演示列表
type TenantOrderListInp struct {
form.PageReq
Id int64 `json:"id" dc:"主键"`
TenantId int64 `json:"tenantId" dc:"租户ID"`
MerchantId int64 `json:"merchantId" dc:"商户ID"`
UserId int64 `json:"userId" dc:"用户ID"`
OrderSn string `json:"orderSn" dc:"关联订单号"`
Status int `json:"status" dc:"支付状态"`
CreatedAt []*gtime.Time `json:"createdAt" dc:"创建时间"`
}
func (in *TenantOrderListInp) Filter(ctx context.Context) (err error) {
return
}
type TenantOrderListModel struct {
Id int64 `json:"id" dc:"主键"`
TenantId int64 `json:"tenantId" dc:"租户ID"`
MerchantId int64 `json:"merchantId" dc:"商户ID"`
UserId int64 `json:"userId" dc:"用户ID"`
ProductName string `json:"productName" dc:"购买产品"`
OrderSn string `json:"orderSn" dc:"关联订单号"`
Money float64 `json:"money" dc:"充值金额"`
Remark string `json:"remark" dc:"备注"`
Status int `json:"status" dc:"支付状态"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
}
// TenantOrderExportModel 导出多租户功能演示
type TenantOrderExportModel struct {
Id int64 `json:"id" dc:"主键"`
TenantId int64 `json:"tenantId" dc:"租户ID"`
MerchantId int64 `json:"merchantId" dc:"商户ID"`
UserId int64 `json:"userId" dc:"用户ID"`
ProductName string `json:"productName" dc:"购买产品"`
OrderSn string `json:"orderSn" dc:"关联订单号"`
Money float64 `json:"money" dc:"充值金额"`
Remark string `json:"remark" dc:"备注"`
Status int `json:"status" dc:"支付状态"`
CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"`
}

View File

@@ -0,0 +1,13 @@
// Package genrouter
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package genrouter
import "hotgo/addons/hgexample/controller/admin/sys"
func init() {
LoginRequiredRouter = append(LoginRequiredRouter, sys.TenantOrder) // 多租户功能演示
}

View File

@@ -47,6 +47,20 @@ type (
// View 获取指定信息
View(ctx context.Context, in *sysin.TableViewInp) (res *sysin.TableViewModel, err error)
}
ISysTenantOrder interface {
// Model 多租户功能演示ORM模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
// List 获取多租户功能演示列表
List(ctx context.Context, in *sysin.TenantOrderListInp) (list []*sysin.TenantOrderListModel, totalCount int, err error)
// Export 导出多租户功能演示
Export(ctx context.Context, in *sysin.TenantOrderListInp) (err error)
// Edit 修改/新增多租户功能演示
Edit(ctx context.Context, in *sysin.TenantOrderEditInp) (err error)
// Delete 删除多租户功能演示
Delete(ctx context.Context, in *sysin.TenantOrderDeleteInp) (err error)
// View 获取多租户功能演示指定信息
View(ctx context.Context, in *sysin.TenantOrderViewInp) (res *sysin.TenantOrderViewModel, err error)
}
ISysTreeTable interface {
// Model Orm模型
Model(ctx context.Context, option ...*handler.Option) *gdb.Model
@@ -62,10 +76,11 @@ type (
)
var (
localSysConfig ISysConfig
localSysIndex ISysIndex
localSysTable ISysTable
localSysTreeTable ISysTreeTable
localSysConfig ISysConfig
localSysIndex ISysIndex
localSysTable ISysTable
localSysTenantOrder ISysTenantOrder
localSysTreeTable ISysTreeTable
)
func SysConfig() ISysConfig {
@@ -101,6 +116,17 @@ func RegisterSysTable(i ISysTable) {
localSysTable = i
}
func SysTenantOrder() ISysTenantOrder {
if localSysTenantOrder == nil {
panic("implement not found for interface ISysTenantOrder, forgot register?")
}
return localSysTenantOrder
}
func RegisterSysTenantOrder(i ISysTenantOrder) {
localSysTenantOrder = i
}
func SysTreeTable() ISysTreeTable {
if localSysTreeTable == nil {
panic("implement not found for interface ISysTreeTable, forgot register?")

View File

@@ -12,14 +12,14 @@ import (
// UploadFileReq 上传文件
type UploadFileReq struct {
g.Meta `path:"/upload/file" tags:"上传" method:"post" summary:"上传附件"`
g.Meta `path:"/upload/file" tags:"附件" method:"post" summary:"上传附件"`
}
type UploadFileRes *sysin.AttachmentListModel
// CheckMultipartReq 检查文件分片
type CheckMultipartReq struct {
g.Meta `path:"/upload/checkMultipart" tags:"上传" method:"post" summary:"检查文件分片"`
g.Meta `path:"/upload/checkMultipart" tags:"附件" method:"post" summary:"检查文件分片"`
sysin.CheckMultipartInp
}
@@ -29,7 +29,7 @@ type CheckMultipartRes struct {
// UploadPartReq 分片上传
type UploadPartReq struct {
g.Meta `path:"/upload/uploadPart" tags:"上传" method:"post" summary:"分片上传"`
g.Meta `path:"/upload/uploadPart" tags:"附件" method:"post" summary:"分片上传"`
sysin.UploadPartInp
}

View File

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

View File

@@ -9,6 +9,7 @@ import (
"github.com/gogf/gf/v2/frame/g"
"hotgo/internal/model/input/adminin"
"hotgo/internal/model/input/form"
"hotgo/utility/tree"
)
// ListReq 查询列表
@@ -55,17 +56,9 @@ type MaxSortRes struct {
*adminin.DeptMaxSortModel
}
// StatusReq 更新部门状态
type StatusReq struct {
g.Meta `path:"/dept/status" method:"post" tags:"部门" summary:"更新部门状态"`
adminin.DeptStatusInp
}
type StatusRes struct{}
// OptionReq 获取部门选项树
// OptionReq 获取当前登录用户可选的部门选项
type OptionReq struct {
g.Meta `path:"/dept/option" method:"get" tags:"部门" summary:"获取部门选项"`
g.Meta `path:"/dept/option" method:"get" tags:"部门" summary:"获取当前登录用户可选的部门选项"`
adminin.DeptOptionInp
}
@@ -73,3 +66,10 @@ type OptionRes struct {
*adminin.DeptOptionModel
form.PageRes
}
// TreeOptionReq 获取部门关系树选项
type TreeOptionReq struct {
g.Meta `path:"/dept/treeOption" method:"get" tags:"部门" summary:"获取部门关系树选项"`
}
type TreeOptionRes []tree.Node

View File

@@ -39,14 +39,14 @@ type DataListRes struct {
}
type DataSelectReq struct {
g.Meta `path:"/dictData/option/{Type}" method:"get" summary:"字典数据" tags:"获取指定字典选项"`
g.Meta `path:"/dictData/option/{Type}" method:"get" tags:"字典数据" summary:"获取指定字典选项"`
sysin.DataSelectInp
}
type DataSelectRes sysin.DataSelectModel
type DataSelectsReq struct {
g.Meta `path:"/dictData/options" method:"get" summary:"字典数据" tags:"获取多个字典选项"`
g.Meta `path:"/dictData/options" method:"get" tags:"字典数据" summary:"获取多个字典选项"`
Types []string `json:"types"`
}

View File

@@ -13,14 +13,14 @@ import (
// ClearReq 清空日志
type ClearReq struct {
g.Meta `path:"/log/clear" method:"post" tags:"日志" summary:"清空日志"`
g.Meta `path:"/log/clear" method:"post" tags:"访问日志" summary:"清空日志"`
}
type ClearRes struct{}
// ExportReq 导出
type ExportReq struct {
g.Meta `path:"/log/export" method:"get" tags:"日志" summary:"导出日志"`
g.Meta `path:"/log/export" method:"get" tags:"访问日志" summary:"导出日志"`
sysin.LogListInp
}
@@ -28,18 +28,18 @@ type ExportRes struct{}
// ListReq 获取菜单列表
type ListReq struct {
g.Meta `path:"/log/list" method:"get" tags:"日志" summary:"获取日志列表"`
g.Meta `path:"/log/list" method:"get" tags:"访问日志" summary:"获取日志列表"`
sysin.LogListInp
}
type ListRes struct {
List []*sysin.LogListModel `json:"list" dc:"数据列表"`
List []*sysin.LogListModel `json:"list" dc:"数据列表"`
form.PageRes
}
// DeleteReq 删除
type DeleteReq struct {
g.Meta `path:"/log/delete" method:"post" tags:"日志" summary:"删除日志"`
g.Meta `path:"/log/delete" method:"post" tags:"访问日志" summary:"删除日志"`
sysin.LogDeleteInp
}
@@ -47,7 +47,7 @@ type DeleteRes struct{}
// ViewReq 获取指定信息
type ViewReq struct {
g.Meta `path:"/log/view" method:"get" tags:"日志" summary:"获取指定信息"`
g.Meta `path:"/log/view" method:"get" tags:"访问日志" summary:"获取指定信息"`
sysin.LogViewInp
}

View File

@@ -0,0 +1,69 @@
// Package normaltreedemo
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package normaltreedemo
import (
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/utility/tree"
"github.com/gogf/gf/v2/frame/g"
)
// ListReq 查询普通树表列表
type ListReq struct {
g.Meta `path:"/normalTreeDemo/list" method:"get" tags:"普通树表" summary:"获取普通树表列表"`
sysin.NormalTreeDemoListInp
}
type ListRes struct {
form.PageRes
List []*sysin.NormalTreeDemoListModel `json:"list" dc:"数据列表"`
}
// ViewReq 获取普通树表指定信息
type ViewReq struct {
g.Meta `path:"/normalTreeDemo/view" method:"get" tags:"普通树表" summary:"获取普通树表指定信息"`
sysin.NormalTreeDemoViewInp
}
type ViewRes struct {
*sysin.NormalTreeDemoViewModel
}
// EditReq 修改/新增普通树表
type EditReq struct {
g.Meta `path:"/normalTreeDemo/edit" method:"post" tags:"普通树表" summary:"修改/新增普通树表"`
sysin.NormalTreeDemoEditInp
}
type EditRes struct{}
// DeleteReq 删除普通树表
type DeleteReq struct {
g.Meta `path:"/normalTreeDemo/delete" method:"post" tags:"普通树表" summary:"删除普通树表"`
sysin.NormalTreeDemoDeleteInp
}
type DeleteRes struct{}
// MaxSortReq 获取普通树表最大排序
type MaxSortReq struct {
g.Meta `path:"/normalTreeDemo/maxSort" method:"get" tags:"普通树表" summary:"获取普通树表最大排序"`
sysin.NormalTreeDemoMaxSortInp
}
type MaxSortRes struct {
*sysin.NormalTreeDemoMaxSortModel
}
// TreeOptionReq 获取普通树表关系树选项
type TreeOptionReq struct {
g.Meta `path:"/normalTreeDemo/treeOption" method:"get" tags:"普通树表" summary:"获取普通树表关系树选项"`
}
type TreeOptionRes []tree.Node

View File

@@ -0,0 +1,69 @@
// Package optiontreedemo
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package optiontreedemo
import (
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"hotgo/utility/tree"
"github.com/gogf/gf/v2/frame/g"
)
// ListReq 查询选项树表列表
type ListReq struct {
g.Meta `path:"/optionTreeDemo/list" method:"get" tags:"选项树表" summary:"获取选项树表列表"`
sysin.OptionTreeDemoListInp
}
type ListRes struct {
form.PageRes
List []*sysin.OptionTreeDemoListModel `json:"list" dc:"数据列表"`
}
// ViewReq 获取选项树表指定信息
type ViewReq struct {
g.Meta `path:"/optionTreeDemo/view" method:"get" tags:"选项树表" summary:"获取选项树表指定信息"`
sysin.OptionTreeDemoViewInp
}
type ViewRes struct {
*sysin.OptionTreeDemoViewModel
}
// EditReq 修改/新增选项树表
type EditReq struct {
g.Meta `path:"/optionTreeDemo/edit" method:"post" tags:"选项树表" summary:"修改/新增选项树表"`
sysin.OptionTreeDemoEditInp
}
type EditRes struct{}
// DeleteReq 删除选项树表
type DeleteReq struct {
g.Meta `path:"/optionTreeDemo/delete" method:"post" tags:"选项树表" summary:"删除选项树表"`
sysin.OptionTreeDemoDeleteInp
}
type DeleteRes struct{}
// MaxSortReq 获取选项树表最大排序
type MaxSortReq struct {
g.Meta `path:"/optionTreeDemo/maxSort" method:"get" tags:"选项树表" summary:"获取选项树表最大排序"`
sysin.OptionTreeDemoMaxSortInp
}
type MaxSortRes struct {
*sysin.OptionTreeDemoMaxSortModel
}
// TreeOptionReq 获取选项树表关系树选项
type TreeOptionReq struct {
g.Meta `path:"/optionTreeDemo/treeOption" method:"get" tags:"选项树表" summary:"获取选项树表关系树选项"`
}
type TreeOptionRes []tree.Node

View File

@@ -98,7 +98,7 @@ type UniqueIdRes struct {
// SelectReq 省市区选项
type SelectReq struct {
g.Meta `path:"/provinces/select" method:"get" summary:"省市区" tags:"省市区选项"`
g.Meta `path:"/provinces/select" method:"get" tags:"省市区" summary:"省市区选项"`
sysin.ProvincesSelectInp
}
@@ -108,7 +108,7 @@ type SelectRes struct {
// CityLabelReq 获取指定城市标签
type CityLabelReq struct {
g.Meta `path:"/provinces/cityLabel" method:"get" summary:"省市区" tags:"获取指定城市标签"`
g.Meta `path:"/provinces/cityLabel" method:"get" tags:"省市区" summary:"获取指定城市标签" `
sysin.ProvincesCityLabelInp
}

View File

@@ -25,7 +25,7 @@ type ListRes struct {
// DynamicReq 动态路由
type DynamicReq struct {
g.Meta `path:"/role/dynamic" method:"get" tags:"路由" summary:"获取动态路由" description:"获取登录用户动态路由"`
g.Meta `path:"/role/dynamic" method:"get" tags:"角色" summary:"获取动态路由" description:"获取登录用户动态路由"`
}
type DynamicRes struct {
@@ -66,7 +66,7 @@ type DeleteRes struct{}
// DataScopeSelectReq 获取数据权限选项
type DataScopeSelectReq struct {
g.Meta `path:"/role/dataScope/select" method:"get" summary:"角色" tags:"获取数据权限选项"`
g.Meta `path:"/role/dataScope/select" method:"get" tags:"角色" summary:"获取数据权限选项"`
}
type DataScopeSelectRes struct {

View File

@@ -13,7 +13,7 @@ import (
// ListReq 查询列表
type ListReq struct {
g.Meta `path:"/smsLog/list" method:"get" tags:"短信记录" summary:"获取短信记录列表"`
g.Meta `path:"/smsLog/list" method:"get" tags:"短信" summary:"获取短信记录列表"`
sysin.SmsLogListInp
}
@@ -24,7 +24,7 @@ type ListRes struct {
// ViewReq 获取指定信息
type ViewReq struct {
g.Meta `path:"/smsLog/view" method:"get" tags:"短信记录" summary:"获取指定信息"`
g.Meta `path:"/smsLog/view" method:"get" tags:"短信" summary:"获取指定短信信息"`
sysin.SmsLogViewInp
}
@@ -32,26 +32,10 @@ type ViewRes struct {
*sysin.SmsLogViewModel
}
// EditReq 修改/新增数据
type EditReq struct {
g.Meta `path:"/smsLog/edit" method:"post" tags:"短信记录" summary:"修改/新增短信记录"`
sysin.SmsLogEditInp
}
type EditRes struct{}
// DeleteReq 删除
type DeleteReq struct {
g.Meta `path:"/smsLog/delete" method:"post" tags:"短信记录" summary:"删除短信记录"`
g.Meta `path:"/smsLog/delete" method:"post" tags:"短信" summary:"删除短信记录"`
sysin.SmsLogDeleteInp
}
type DeleteRes struct{}
// StatusReq 更新状态
type StatusReq struct {
g.Meta `path:"/smsLog/status" method:"post" tags:"短信记录" summary:"更新短信记录状态"`
sysin.SmsLogStatusInp
}
type StatusRes struct{}

View File

@@ -0,0 +1,69 @@
// Package testcategory
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package testcategory
import (
"hotgo/internal/model/input/form"
"hotgo/internal/model/input/sysin"
"github.com/gogf/gf/v2/frame/g"
)
// ListReq 查询测试分类列表
type ListReq struct {
g.Meta `path:"/testCategory/list" method:"get" tags:"测试分类" summary:"获取测试分类列表"`
sysin.TestCategoryListInp
}
type ListRes struct {
form.PageRes
List []*sysin.TestCategoryListModel `json:"list" dc:"数据列表"`
}
// ViewReq 获取测试分类指定信息
type ViewReq struct {
g.Meta `path:"/testCategory/view" method:"get" tags:"测试分类" summary:"获取测试分类指定信息"`
sysin.TestCategoryViewInp
}
type ViewRes struct {
*sysin.TestCategoryViewModel
}
// EditReq 修改/新增测试分类
type EditReq struct {
g.Meta `path:"/testCategory/edit" method:"post" tags:"测试分类" summary:"修改/新增测试分类"`
sysin.TestCategoryEditInp
}
type EditRes struct{}
// DeleteReq 删除测试分类
type DeleteReq struct {
g.Meta `path:"/testCategory/delete" method:"post" tags:"测试分类" summary:"删除测试分类"`
sysin.TestCategoryDeleteInp
}
type DeleteRes struct{}
// MaxSortReq 获取测试分类最大排序
type MaxSortReq struct {
g.Meta `path:"/testCategory/maxSort" method:"get" tags:"测试分类" summary:"获取测试分类最大排序"`
sysin.TestCategoryMaxSortInp
}
type MaxSortRes struct {
*sysin.TestCategoryMaxSortModel
}
// StatusReq 更新测试分类状态
type StatusReq struct {
g.Meta `path:"/testCategory/status" method:"post" tags:"测试分类" summary:"更新测试分类状态"`
sysin.TestCategoryStatusInp
}
type StatusRes struct{}

View File

@@ -1,19 +0,0 @@
// Package user
// @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 user
import (
"github.com/gogf/gf/v2/frame/g"
)
type HelloReq struct {
g.Meta `path:"/hello" tags:"Hello" method:"get" summary:"You first hello api"`
Name string `json:"name" d:"hotgo" dc:"名字"`
}
type HelloRes struct {
Tips string `json:"tips"`
}

View File

@@ -1,6 +1,8 @@
module hotgo
go 1.19
go 1.21
toolchain go1.22.1
require (
github.com/Shopify/sarama v1.34.1
@@ -9,20 +11,20 @@ require (
github.com/alibabacloud-go/tea v1.1.20
github.com/alibabacloud-go/tea-utils/v2 v2.0.1
github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible
github.com/apache/rocketmq-client-go/v2 v2.1.0
github.com/apache/rocketmq-client-go/v2 v2.1.2
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.6.4
github.com/gogf/gf/contrib/nosql/redis/v2 v2.6.4
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.4
github.com/gogf/gf/v2 v2.6.4
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.0
github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.0
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.7.0
github.com/gogf/gf/v2 v2.7.0
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f
github.com/golang-jwt/jwt/v5 v5.0.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/mojocn/base64Captcha v1.3.5
github.com/mojocn/base64Captcha v1.3.6
github.com/olekukonko/tablewriter v0.0.5
github.com/qiniu/go-sdk/v7 v7.14.0
github.com/shirou/gopsutil/v3 v3.23.3
@@ -32,14 +34,16 @@ require (
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.24.0
go.opentelemetry.io/otel v1.25.0
golang.org/x/mod v0.9.0
golang.org/x/net v0.24.0
golang.org/x/tools v0.7.0
gopkg.in/yaml.v3 v3.0.1
)
require (
aead.dev/minisign v0.2.0 // indirect
filippo.io/edwards25519 v1.1.0 // indirect
github.com/BurntSushi/toml v1.3.2 // indirect
github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible // indirect
github.com/alibabacloud-go/alibabacloud-gateway-spi v0.0.4 // indirect
@@ -50,7 +54,7 @@ require (
github.com/alibabacloud-go/tea-xml v1.1.2 // indirect
github.com/aliyun/credentials-go v1.1.2 // indirect
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/clbanning/mxj v1.8.4 // indirect
github.com/clbanning/mxj/v2 v2.7.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
@@ -67,7 +71,7 @@ require (
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
github.com/go-sql-driver/mysql v1.7.1 // indirect
github.com/go-sql-driver/mysql v1.8.1 // indirect
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
github.com/golang/mock v1.6.0 // indirect
github.com/golang/snappy v0.0.4 // indirect
@@ -98,6 +102,7 @@ require (
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/patrickmn/go-cache v2.1.0+incompatible // 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
@@ -120,17 +125,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.24.0 // indirect
go.opentelemetry.io/otel/sdk v1.24.0 // indirect
go.opentelemetry.io/otel/trace v1.24.0 // indirect
go.opentelemetry.io/otel/metric v1.25.0 // indirect
go.opentelemetry.io/otel/sdk v1.25.0 // indirect
go.opentelemetry.io/otel/trace v1.25.0 // indirect
go.uber.org/atomic v1.7.0 // indirect
golang.org/x/crypto v0.21.0 // indirect
golang.org/x/image v0.1.0 // indirect
golang.org/x/net v0.22.0 // indirect
golang.org/x/crypto v0.22.0 // indirect
golang.org/x/image v0.13.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/sys v0.19.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.67.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
stathat.com/c/consistent v1.0.0 // indirect
)

View File

@@ -33,7 +33,10 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
@@ -80,22 +83,24 @@ github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible h1:KXeJoM1wo9I/6xPTyt6qC
github.com/aliyun/aliyun-oss-go-sdk v2.2.6+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
github.com/aliyun/credentials-go v1.1.2 h1:qU1vwGIBb3UJ8BwunHDRFtAhS6jnQLnde/yk0+Ih2GY=
github.com/aliyun/credentials-go v1.1.2/go.mod h1:ozcZaMR5kLM7pwtCMEpVmQ242suV6qTJya2bDq4X1Tw=
github.com/apache/rocketmq-client-go/v2 v2.1.0 h1:3eABKfxc1WmS2lLTTbKMe1gZfZV6u1Sx9orFnOfABV0=
github.com/apache/rocketmq-client-go/v2 v2.1.0/go.mod h1:oEZKFDvS7sz/RWU0839+dQBupazyBV7WX5cP6nrio0Q=
github.com/apache/rocketmq-client-go/v2 v2.1.2 h1:yt73olKe5N6894Dbm+ojRf/JPiP0cxfDNNffKwhpJVg=
github.com/apache/rocketmq-client-go/v2 v2.1.2/go.mod h1:6I6vgxHR3hzrvn+6n/4mrhS+UTulzK/X9LB2Vk1U5gE=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d h1:pVrfxiGfwelyab6n21ZBkbkmbevaf+WvMIiR7sr97hw=
github.com/bradfitz/gomemcache v0.0.0-20220106215444-fb4bf637b56d/go.mod h1:H0wQNHz2YrLsuXOZozoeDmnHXkNCRmMW0gwFWDfEZDA=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/casbin/casbin/v2 v2.55.0 h1:RyU+OacnVzjxof1U3bmxHM7oCRdx9+gNnkclrvof/zI=
github.com/casbin/casbin/v2 v2.55.0/go.mod h1:vByNa/Fchek0KZUgG5wEsl7iFsiviAYKRtgrQfcJqHg=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
@@ -166,18 +171,18 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
github.com/go-playground/validator/v10 v10.8.0/go.mod h1:9JhgTzTaE31GZDpH/HSvHiRJrJ3iKAgqqH0Bl/Ocjdk=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI=
github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
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.6.4 h1:ScG3YcYMDEP/UrwNtwQPt2noySa5ZpoV7BxrwaeBaro=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.6.4/go.mod h1:oFFE9u1zHkxVXk7ZkNipXQR9JFyDZDiixZy243ywhfQ=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.6.4 h1:43517FF//GKgGpb4pxHl3NWLxW/inTAQ7rUFnfUIoYY=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.6.4/go.mod h1:9qNdKgqB+tHC9XczIoMzfSHmWkphQMXqxJXF6g9Icr4=
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.4 h1:PV0V2CPspwC+qgmqMC7qjCFkxH/SkfLwC0fg26ZTY54=
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.6.4/go.mod h1:Wnu7ASD+BWWlPn9NlSNOmCip7tHnYSXRSSjFJ5cCTEo=
github.com/gogf/gf/v2 v2.6.4 h1:w7HXdH9mcTsn/aE13CkaDbRArmAL1KS3FuQqDi6u74Y=
github.com/gogf/gf/v2 v2.6.4/go.mod h1:x2XONYcI4hRQ/4gMNbWHmZrNzSEIg20s2NULbzom5k0=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.0 h1:5Igvtz4gy5UMvH+Ut4kLIpwSzggV9ZgDVBsIiOctH5E=
github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.0/go.mod h1:0+flZ0clMKjtH1sTI7YD2KG4FPr8xz0L9h1WMd5M2Z8=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.0 h1:hJxshC0gZyFZaGo2HItXd5XMzIMbCRcgShr1ljMYwUc=
github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.0/go.mod h1:is3Q3ItZSPMZ1RBJ3xIcEasyGZnOg8eNeG9dubOx/zc=
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.7.0 h1:P75Jfq5rP8TUUTyobAooULJDDCaSOkgL14gnXudgY1E=
github.com/gogf/gf/contrib/trace/jaeger/v2 v2.7.0/go.mod h1:hRnwcGAFG8c6+9rg//zbr0Ve3XZVzAuALfzfbz3xBBk=
github.com/gogf/gf/v2 v2.7.0 h1:CjxhbMiE7oqf6K8ZtGuKt3dQEwK4vL6LhiI+dI7tJGU=
github.com/gogf/gf/v2 v2.7.0/go.mod h1:Qu8nimKt9aupJQcdUL85tWF4Mfxocz97zUt8UC4abVI=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f h1:7xfXR/BhG3JDqO1s45n65Oyx9t4E/UqDOXep6jXdLCM=
github.com/gogf/selfupdate v0.0.0-20231215043001-5c48c528462f/go.mod h1:HnYoio6S7VaFJdryKcD/r9HgX+4QzYfr00XiXUo/xz0=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
@@ -232,6 +237,7 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
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=
@@ -288,7 +294,6 @@ github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZ
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
@@ -350,8 +355,8 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/mojocn/base64Captcha v1.3.5 h1:Qeilr7Ta6eDtG4S+tQuZ5+hO+QHbiGAJdi4PfoagaA0=
github.com/mojocn/base64Captcha v1.3.5/go.mod h1:/tTTXn4WTpX9CfrmipqRytCpJ27Uw3G6I7NcP2WwcmY=
github.com/mojocn/base64Captcha v1.3.6 h1:gZEKu1nsKpttuIAQgWHO+4Mhhls8cAKyiV2Ew03H+Tw=
github.com/mojocn/base64Captcha v1.3.6/go.mod h1:i5CtHvm+oMbj1UzEPXaA8IH/xHFZ3DGY3Wh3dBpZ28E=
github.com/mozillazg/go-httpheader v0.2.1 h1:geV7TrjbL8KXSyvghnFm+NyTux/hxwueTSrwhe88TQQ=
github.com/mozillazg/go-httpheader v0.2.1/go.mod h1:jJ8xECTlalr6ValeXYdOF8fFUISeBAdw6E61aqQma60=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
@@ -374,6 +379,8 @@ 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/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
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=
@@ -436,7 +443,7 @@ github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeV
github.com/silenceper/wechat/v2 v2.1.4 h1:X+G9C/EiBET5AK0zhrflX3ESCP/yxhJUvoRoSXHm0js=
github.com/silenceper/wechat/v2 v2.1.4/go.mod h1:F0PKqImb15THnwoqRNrZO1z3vpwyWuiHr5zzfnjdECY=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
github.com/sirupsen/logrus v1.4.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
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=
@@ -446,7 +453,6 @@ github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVs
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=
github.com/smartystreets/goconvey v0.0.0-20190710185942-9d28bd7c0945/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
@@ -466,7 +472,8 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
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=
@@ -475,13 +482,11 @@ github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.633 h1:rtgRqgZ
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/sms v1.0.633/go.mod h1:9q29WcGkZ7R0uQjoY10Tzb8A18C2cNggbq2ZC2HRXZE=
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.13.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.0.1/go.mod h1:LujAq0jyVjBy028G1WhWfIzbpQfMO8bBZ6Tyb0+pL9E=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v0.0.0-20190325153808-1166b9ac2b65/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tjfoc/gmsm v1.3.2 h1:7JVkAn5bvUJ7HtU08iW6UiD+UTmJTIToHCfeFzkcCxM=
@@ -516,16 +521,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.24.0 h1:0LAOdjNmQeSTzGBzduGe/rU4tZhMwL5rWgtp9Ku5Jfo=
go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo=
go.opentelemetry.io/otel v1.25.0 h1:gldB5FfhRl7OJQbUHt/8s0a7cE8fbsPAtdpRaApKy4k=
go.opentelemetry.io/otel v1.25.0/go.mod h1:Wa2ds5NOXEMkCmUou1WA7ZBfLTHWIsp034OVD7AO+Vg=
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.24.0 h1:6EhoGWWK28x1fbpA4tYTOWBkPefTDQnb8WSGXlc88kI=
go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco=
go.opentelemetry.io/otel/sdk v1.24.0 h1:YMPPDNymmQN3ZgczicBY3B6sf9n62Dlj9pWD3ucgoDw=
go.opentelemetry.io/otel/sdk v1.24.0/go.mod h1:KVrIYw6tEubO9E96HQpcmpTKDVn9gdv35HoYiQWGDFg=
go.opentelemetry.io/otel/trace v1.24.0 h1:CsKnnL4dUAr/0llH9FKuc698G04IrpWV0MQA/Y1YELI=
go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU=
go.opentelemetry.io/otel/metric v1.25.0 h1:LUKbS7ArpFL/I2jJHdJcqMGxkRdxpPHE0VU/D4NuEwA=
go.opentelemetry.io/otel/metric v1.25.0/go.mod h1:rkDLUSd2lC5lq2dFNrX9LGAbINP5B7WBkC78RXCpH5s=
go.opentelemetry.io/otel/sdk v1.25.0 h1:PDryEJPC8YJZQSyLY5eqLeafHtG+X7FWnf3aXMtxbqo=
go.opentelemetry.io/otel/sdk v1.25.0/go.mod h1:oFgzCM2zdsxKzz6zwpTZYLLQsFwc+K0daArPdIhuxkw=
go.opentelemetry.io/otel/trace v1.25.0 h1:tqukZGLwQYRIFtSQM2u2+yfMVTgGVeqRLPUYx1Dq6RM=
go.opentelemetry.io/otel/trace v1.25.0/go.mod h1:hCCs70XM/ljO+BeQkyFnbK28SBIJ/Emuha+ccrCRT7I=
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=
@@ -544,8 +549,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y
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.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30=
golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M=
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=
@@ -557,11 +562,10 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190501045829-6d32002ffd75/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20211028202545-6944b10bf410/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
golang.org/x/image v0.13.0 h1:3cge/F/QTkNLauhf2QoE9zp+7sr+ZcL4HnoZmdwg9sg=
golang.org/x/image v0.13.0/go.mod h1:6mmbMOeV28HuMTgA6OSRkdXKYw/t5W9Uwn2Yv1r3Yxk=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -582,6 +586,7 @@ golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.9.0 h1:KENHtAZL2y3NLMYZeHY9DW8HW8V+kQyJsY/V9JlKvCs=
golang.org/x/mod v0.9.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -623,8 +628,9 @@ 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.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
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=
@@ -705,11 +711,12 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
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.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.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=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -717,7 +724,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
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.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
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=
@@ -770,6 +778,7 @@ golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.7.0 h1:W4OVu8VVOaIO0yzWMNdepAulS7YfoS3Zabrm8DOXXU4=
golang.org/x/tools v0.7.0/go.mod h1:4pg6aUX35JBAogB10C9AtvVL+qowtN4pT3CGSQex14s=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -865,6 +874,8 @@ gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaD
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/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
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=

View File

@@ -22,7 +22,7 @@ gfcli:
gen:
dao:
- link: "mysql:hotgo:hg123456.@tcp(127.0.0.1:3306)/hotgo?loc=Local&parseTime=true"
- link: "mysql:hotgo:hg123456.@tcp(127.0.0.1:3306)/hotgo?loc=Local&parseTime=true&charset=utf8mb4"
group: "default" # 分组 使用hotgo代码生成功能时必须填
# tables: "" # 指定当前数据库中需要执行代码生成的数据表如果为空表示数据库的所有表都会生成
tablesEx: "hg_sys_addons_install" # 指定当前数据库中需要排除代码生成的数据表

View File

@@ -36,6 +36,8 @@ var (
---------------------------------------------------------------------------------
工具
>> 释放casbin权限用于清理无效的权限设置 [go run main.go tools -m=casbin -a1=refresh]
>> 打印所有打包的资源文件列表 [go run main.go tools -m=gres -a1=dump]
>> 打印指定打包的资源文件内容 [go run main.go tools -m=gres -a1=content -a2=resource/template/home/index.html]
---------------------------------------------------------------------------------
升级更新
>> 修复菜单关系树 [go run main.go up -m=fix -a1=menuTree]

View File

@@ -23,8 +23,8 @@ var (
// signalHandlerForOverall 关闭信号处理
func signalHandlerForOverall(sig os.Signal) {
serverCloseSignal <- struct{}{}
serverCloseEvent(gctx.GetInitCtx())
serverCloseSignal <- struct{}{}
}
// signalListen 信号监听

View File

@@ -7,9 +7,11 @@ package cmd
import (
"context"
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gcmd"
"github.com/gogf/gf/v2/os/gres"
"hotgo/internal/library/casbin"
)
@@ -35,6 +37,8 @@ var (
switch method {
case "casbin":
err = handleCasbin(ctx, args)
case "gres":
err = handleGRes(ctx, args)
default:
err = gerror.Newf("tools method[%v] does not exist", method)
}
@@ -66,3 +70,38 @@ func handleCasbin(ctx context.Context, args map[string]string) (err error) {
}
return
}
func handleGRes(ctx context.Context, args map[string]string) (err error) {
a1, ok := args["a1"]
if !ok {
err = gerror.New("gres args cannot be empty.")
return
}
switch a1 {
case "dump":
gres.Dump()
case "content":
path, ok := args["a2"]
if !ok {
err = gerror.New("缺少查看文件路径参数:`a2`")
return
}
if !gres.Contains(path) {
err = gerror.Newf("没有找到资源文件:%v", path)
return
}
content := string(gres.GetContent(path))
if len(content) == 0 {
err = gerror.Newf("没有找到资源文件内容,请确认传入`a2`参数是一个文件a2:%v", path)
return
}
fmt.Println("以下是资源文件内容:")
fmt.Println(content)
default:
err = gerror.Newf("handleGRes a1 is invalid, a1:%v", a1)
}
return
}

View File

@@ -22,3 +22,10 @@ const (
DefaultPageSize = 1 // 默认列表分页加载页码
MaxSortIncr = 10 // 最大排序值增量
)
// TenantField 租户字段
const (
TenantId = "tenant_id" // 租户ID
MerchantId = "merchant_id" // 商户ID
UserId = "user_id" // 用户ID
)

View File

@@ -0,0 +1,30 @@
// Package consts
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
package consts
import (
"hotgo/internal/library/dict"
"hotgo/internal/model"
)
func init() {
dict.RegisterEnums("deptType", "部门类型选项", DeptTypeOptions)
}
const (
DeptTypeCompany = "company" // 公司
DeptTypeTenant = "tenant" // 租户
DeptTypeMerchant = "merchant" // 商户
DeptTypeUser = "user" // 用户
)
// DeptTypeOptions 部门类型选项
var DeptTypeOptions = []*model.Option{
dict.GenSuccessOption(DeptTypeCompany, "公司"),
dict.GenErrorOption(DeptTypeTenant, "租户"),
dict.GenInfoOption(DeptTypeMerchant, "商户"),
dict.GenWarningOption(DeptTypeUser, "用户"),
}

View File

@@ -3,9 +3,13 @@
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package consts
import (
"hotgo/internal/library/dict"
"hotgo/internal/model"
)
// 生成代码类型
const (
GenCodesTypeCurd = 10 // 增删改查列表
@@ -16,7 +20,7 @@ const (
var GenCodesTypeNameMap = map[int]string{
GenCodesTypeCurd: "增删改查列表",
GenCodesTypeTree: "关系树列表(未实现)",
GenCodesTypeTree: "关系树列表",
GenCodesTypeQueue: "队列消费者(未实现)",
GenCodesTypeCron: "定时任务(未实现)",
}
@@ -79,3 +83,14 @@ const (
GenCodesIndexPK = "PRI" // 主键索引
GenCodesIndexUNI = "UNI" // 唯一索引
)
const (
GenCodesTreeStyleTypeNormal = 1 // 普通树表格
GenCodesTreeStyleTypeOption = 2 // 选项式树表
)
// GenCodesTreeStyleTypeOptions 树表样式选项
var GenCodesTreeStyleTypeOptions = []*model.Option{
dict.GenSuccessOption(GenCodesTreeStyleTypeNormal, "普通树表格"),
dict.GenInfoOption(GenCodesTreeStyleTypeOption, "选项式树表"),
}

View File

@@ -14,6 +14,7 @@ import (
func init() {
dict.RegisterEnums("payType", "支付方式", PayTypeOptions)
dict.RegisterEnums("payStatus", "支付状态", PayStatusOptions)
}
const (
@@ -72,6 +73,12 @@ const (
PayStatusOk = 2 // 已支付
)
// PayStatusOptions 支付状态选项
var PayStatusOptions = []*model.Option{
dict.GenDefaultOption(PayStatusWait, "待支付"),
dict.GenSuccessOption(PayStatusOk, "已支付"),
}
// 退款状态
const (

View File

@@ -7,5 +7,5 @@ package consts
// VersionApp HotGo版本
const (
VersionApp = "2.13.1"
VersionApp = "2.15.1"
)

View File

@@ -54,12 +54,6 @@ func (c *cDept) List(ctx context.Context, req *dept.ListReq) (res *dept.ListRes,
return
}
// Status 更新部门状态
func (c *cDept) Status(ctx context.Context, req *dept.StatusReq) (res *dept.StatusRes, err error) {
err = service.AdminDept().Status(ctx, &req.DeptStatusInp)
return
}
// Option 获取部门选项树
func (c *cDept) Option(ctx context.Context, req *dept.OptionReq) (res *dept.OptionRes, err error) {
list, totalCount, err := service.AdminDept().Option(ctx, &req.DeptOptionInp)
@@ -72,3 +66,10 @@ func (c *cDept) Option(ctx context.Context, req *dept.OptionReq) (res *dept.Opti
res.PageRes.Pack(req, totalCount)
return
}
// TreeOption 获取部门管理关系树选项
func (c *cDept) TreeOption(ctx context.Context, req *dept.TreeOptionReq) (res *dept.TreeOptionRes, err error) {
data, err := service.AdminDept().TreeOption(ctx)
res = (*dept.TreeOptionRes)(&data)
return
}

View File

@@ -8,7 +8,6 @@ package admin
import (
"context"
"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"
"hotgo/api/admin/monitor"
@@ -103,12 +102,10 @@ func (c *cMonitor) UserOnlineList(ctx context.Context, req *monitor.UserOnlineLi
return clients[i].FirstTime < clients[j].FirstTime
})
isDemo := g.Cfg().MustGet(ctx, "hotgo.isDemo", false).Bool()
_, perPage, offset := form.CalPage(req.Page, req.PerPage)
for k, v := range clients {
if k >= offset && i <= perPage {
if isDemo {
if simple.IsDemo(ctx) {
v.IP = consts.DemoTips
}
res.List = append(res.List, v)

View File

@@ -3,7 +3,7 @@
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.12.10
// @AutoGenerate Version 2.13.1
package sys
import (
@@ -19,7 +19,7 @@ var (
type cCurdDemo struct{}
// List 查看生成演示列表
// List 查看CURD列表列表
func (c *cCurdDemo) List(ctx context.Context, req *curddemo.ListReq) (res *curddemo.ListRes, err error) {
list, totalCount, err := service.SysCurdDemo().List(ctx, &req.CurdDemoListInp)
if err != nil {
@@ -36,19 +36,19 @@ func (c *cCurdDemo) List(ctx context.Context, req *curddemo.ListReq) (res *curdd
return
}
// Export 导出生成演示列表
// Export 导出CURD列表列表
func (c *cCurdDemo) Export(ctx context.Context, req *curddemo.ExportReq) (res *curddemo.ExportRes, err error) {
err = service.SysCurdDemo().Export(ctx, &req.CurdDemoListInp)
return
}
// Edit 更新生成演示
// Edit 更新CURD列表
func (c *cCurdDemo) Edit(ctx context.Context, req *curddemo.EditReq) (res *curddemo.EditRes, err error) {
err = service.SysCurdDemo().Edit(ctx, &req.CurdDemoEditInp)
return
}
// MaxSort 获取生成演示最大排序
// MaxSort 获取CURD列表最大排序
func (c *cCurdDemo) MaxSort(ctx context.Context, req *curddemo.MaxSortReq) (res *curddemo.MaxSortRes, err error) {
data, err := service.SysCurdDemo().MaxSort(ctx, &req.CurdDemoMaxSortInp)
if err != nil {
@@ -60,7 +60,7 @@ func (c *cCurdDemo) MaxSort(ctx context.Context, req *curddemo.MaxSortReq) (res
return
}
// View 获取指定生成演示信息
// View 获取指定CURD列表信息
func (c *cCurdDemo) View(ctx context.Context, req *curddemo.ViewReq) (res *curddemo.ViewRes, err error) {
data, err := service.SysCurdDemo().View(ctx, &req.CurdDemoViewInp)
if err != nil {
@@ -72,19 +72,13 @@ func (c *cCurdDemo) View(ctx context.Context, req *curddemo.ViewReq) (res *curdd
return
}
// Delete 删除生成演示
// Delete 删除CURD列表
func (c *cCurdDemo) Delete(ctx context.Context, req *curddemo.DeleteReq) (res *curddemo.DeleteRes, err error) {
err = service.SysCurdDemo().Delete(ctx, &req.CurdDemoDeleteInp)
return
}
// Status 更新生成演示状态
func (c *cCurdDemo) Status(ctx context.Context, req *curddemo.StatusReq) (res *curddemo.StatusRes, err error) {
err = service.SysCurdDemo().Status(ctx, &req.CurdDemoStatusInp)
return
}
// Switch 更新生成演示开关状态
// Switch 更新CURD列表开关状态
func (c *cCurdDemo) Switch(ctx context.Context, req *curddemo.SwitchReq) (res *curddemo.SwitchRes, err error) {
err = service.SysCurdDemo().Switch(ctx, &req.CurdDemoSwitchInp)
return

View File

@@ -0,0 +1,80 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package sys
import (
"context"
"hotgo/api/admin/normaltreedemo"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
var (
NormalTreeDemo = cNormalTreeDemo{}
)
type cNormalTreeDemo struct{}
// List 查看普通树表列表
func (c *cNormalTreeDemo) List(ctx context.Context, req *normaltreedemo.ListReq) (res *normaltreedemo.ListRes, err error) {
list, totalCount, err := service.SysNormalTreeDemo().List(ctx, &req.NormalTreeDemoListInp)
if err != nil {
return
}
if list == nil {
list = []*sysin.NormalTreeDemoListModel{}
}
res = new(normaltreedemo.ListRes)
res.List = list
res.PageRes.Pack(req, totalCount)
return
}
// Edit 更新普通树表
func (c *cNormalTreeDemo) Edit(ctx context.Context, req *normaltreedemo.EditReq) (res *normaltreedemo.EditRes, err error) {
err = service.SysNormalTreeDemo().Edit(ctx, &req.NormalTreeDemoEditInp)
return
}
// MaxSort 获取普通树表最大排序
func (c *cNormalTreeDemo) MaxSort(ctx context.Context, req *normaltreedemo.MaxSortReq) (res *normaltreedemo.MaxSortRes, err error) {
data, err := service.SysNormalTreeDemo().MaxSort(ctx, &req.NormalTreeDemoMaxSortInp)
if err != nil {
return
}
res = new(normaltreedemo.MaxSortRes)
res.NormalTreeDemoMaxSortModel = data
return
}
// View 获取指定普通树表信息
func (c *cNormalTreeDemo) View(ctx context.Context, req *normaltreedemo.ViewReq) (res *normaltreedemo.ViewRes, err error) {
data, err := service.SysNormalTreeDemo().View(ctx, &req.NormalTreeDemoViewInp)
if err != nil {
return
}
res = new(normaltreedemo.ViewRes)
res.NormalTreeDemoViewModel = data
return
}
// Delete 删除普通树表
func (c *cNormalTreeDemo) Delete(ctx context.Context, req *normaltreedemo.DeleteReq) (res *normaltreedemo.DeleteRes, err error) {
err = service.SysNormalTreeDemo().Delete(ctx, &req.NormalTreeDemoDeleteInp)
return
}
// TreeOption 获取普通树表关系树选项
func (c *cNormalTreeDemo) TreeOption(ctx context.Context, req *normaltreedemo.TreeOptionReq) (res *normaltreedemo.TreeOptionRes, err error) {
data, err := service.SysNormalTreeDemo().TreeOption(ctx)
res = (*normaltreedemo.TreeOptionRes)(&data)
return
}

View File

@@ -0,0 +1,80 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package sys
import (
"context"
"hotgo/api/admin/optiontreedemo"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
var (
OptionTreeDemo = cOptionTreeDemo{}
)
type cOptionTreeDemo struct{}
// List 查看选项树表列表
func (c *cOptionTreeDemo) List(ctx context.Context, req *optiontreedemo.ListReq) (res *optiontreedemo.ListRes, err error) {
list, totalCount, err := service.SysOptionTreeDemo().List(ctx, &req.OptionTreeDemoListInp)
if err != nil {
return
}
if list == nil {
list = []*sysin.OptionTreeDemoListModel{}
}
res = new(optiontreedemo.ListRes)
res.List = list
res.PageRes.Pack(req, totalCount)
return
}
// Edit 更新选项树表
func (c *cOptionTreeDemo) Edit(ctx context.Context, req *optiontreedemo.EditReq) (res *optiontreedemo.EditRes, err error) {
err = service.SysOptionTreeDemo().Edit(ctx, &req.OptionTreeDemoEditInp)
return
}
// MaxSort 获取选项树表最大排序
func (c *cOptionTreeDemo) MaxSort(ctx context.Context, req *optiontreedemo.MaxSortReq) (res *optiontreedemo.MaxSortRes, err error) {
data, err := service.SysOptionTreeDemo().MaxSort(ctx, &req.OptionTreeDemoMaxSortInp)
if err != nil {
return
}
res = new(optiontreedemo.MaxSortRes)
res.OptionTreeDemoMaxSortModel = data
return
}
// View 获取指定选项树表信息
func (c *cOptionTreeDemo) View(ctx context.Context, req *optiontreedemo.ViewReq) (res *optiontreedemo.ViewRes, err error) {
data, err := service.SysOptionTreeDemo().View(ctx, &req.OptionTreeDemoViewInp)
if err != nil {
return
}
res = new(optiontreedemo.ViewRes)
res.OptionTreeDemoViewModel = data
return
}
// Delete 删除选项树表
func (c *cOptionTreeDemo) Delete(ctx context.Context, req *optiontreedemo.DeleteReq) (res *optiontreedemo.DeleteRes, err error) {
err = service.SysOptionTreeDemo().Delete(ctx, &req.OptionTreeDemoDeleteInp)
return
}
// TreeOption 获取选项树表关系树选项
func (c *cOptionTreeDemo) TreeOption(ctx context.Context, req *optiontreedemo.TreeOptionReq) (res *optiontreedemo.TreeOptionRes, err error) {
data, err := service.SysOptionTreeDemo().TreeOption(ctx)
res = (*optiontreedemo.TreeOptionRes)(&data)
return
}

View File

@@ -23,12 +23,6 @@ func (c *cSmsLog) Delete(ctx context.Context, req *smslog.DeleteReq) (res *smslo
return
}
// Edit 更新
func (c *cSmsLog) Edit(ctx context.Context, req *smslog.EditReq) (res *smslog.EditRes, err error) {
err = service.SysSmsLog().Edit(ctx, &req.SmsLogEditInp)
return
}
// View 获取指定信息
func (c *cSmsLog) View(ctx context.Context, req *smslog.ViewReq) (res *smslog.ViewRes, err error) {
data, err := service.SysSmsLog().View(ctx, &req.SmsLogViewInp)
@@ -53,9 +47,3 @@ func (c *cSmsLog) List(ctx context.Context, req *smslog.ListReq) (res *smslog.Li
res.PageRes.Pack(req, totalCount)
return
}
// Status 更新状态
func (c *cSmsLog) Status(ctx context.Context, req *smslog.StatusReq) (res *smslog.StatusRes, err error) {
err = service.SysSmsLog().Status(ctx, &req.SmsLogStatusInp)
return
}

View File

@@ -0,0 +1,79 @@
// Package sys
// @Link https://github.com/bufanyun/hotgo
// @Copyright Copyright (c) 2024 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
// @AutoGenerate Version 2.13.1
package sys
import (
"context"
"hotgo/api/admin/testcategory"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
)
var (
TestCategory = cTestCategory{}
)
type cTestCategory struct{}
// List 查看测试分类列表
func (c *cTestCategory) List(ctx context.Context, req *testcategory.ListReq) (res *testcategory.ListRes, err error) {
list, totalCount, err := service.SysTestCategory().List(ctx, &req.TestCategoryListInp)
if err != nil {
return
}
if list == nil {
list = []*sysin.TestCategoryListModel{}
}
res = new(testcategory.ListRes)
res.List = list
res.PageRes.Pack(req, totalCount)
return
}
// Edit 更新测试分类
func (c *cTestCategory) Edit(ctx context.Context, req *testcategory.EditReq) (res *testcategory.EditRes, err error) {
err = service.SysTestCategory().Edit(ctx, &req.TestCategoryEditInp)
return
}
// MaxSort 获取测试分类最大排序
func (c *cTestCategory) MaxSort(ctx context.Context, req *testcategory.MaxSortReq) (res *testcategory.MaxSortRes, err error) {
data, err := service.SysTestCategory().MaxSort(ctx, &req.TestCategoryMaxSortInp)
if err != nil {
return
}
res = new(testcategory.MaxSortRes)
res.TestCategoryMaxSortModel = data
return
}
// View 获取指定测试分类信息
func (c *cTestCategory) View(ctx context.Context, req *testcategory.ViewReq) (res *testcategory.ViewRes, err error) {
data, err := service.SysTestCategory().View(ctx, &req.TestCategoryViewInp)
if err != nil {
return
}
res = new(testcategory.ViewRes)
res.TestCategoryViewModel = data
return
}
// Delete 删除测试分类
func (c *cTestCategory) Delete(ctx context.Context, req *testcategory.DeleteReq) (res *testcategory.DeleteRes, err error) {
err = service.SysTestCategory().Delete(ctx, &req.TestCategoryDeleteInp)
return
}
// Status 更新测试分类状态
func (c *cTestCategory) Status(ctx context.Context, req *testcategory.StatusReq) (res *testcategory.StatusRes, err error) {
err = service.SysTestCategory().Status(ctx, &req.TestCategoryStatusInp)
return
}

View File

@@ -1,26 +0,0 @@
// Package user
// @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 user
import (
"context"
"fmt"
"hotgo/api/api/user"
"hotgo/utility/simple"
)
var (
Hello = cHello{}
)
type cHello struct{}
func (c *cHello) Hello(ctx context.Context, req *user.HelloReq) (res *user.HelloRes, err error) {
res = &user.HelloRes{
Tips: fmt.Sprintf("hello %v, this is the api for %v applications.", req.Name, simple.AppName(ctx)),
}
return
}

View File

@@ -21,6 +21,7 @@ import (
"hotgo/internal/websocket"
"hotgo/utility/file"
"hotgo/utility/format"
"hotgo/utility/simple"
"os"
"runtime"
"time"
@@ -76,8 +77,7 @@ func (c *cMonitor) RunInfo(client *websocket.Client, req *websocket.WRequest) {
"goSize": file.DirSize(pwd),
}
isDemo := g.Cfg().MustGet(client.Context(), "hotgo.isDemo", false).Bool()
if isDemo {
if simple.IsDemo(client.Context()) {
data["rootPath"] = consts.DemoTips
data["pwd"] = consts.DemoTips
data["intranet_ip"] = consts.DemoTips

View File

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

View File

@@ -18,7 +18,7 @@ type adminDeptDao struct {
}
var (
// AdminDept is globally common accessible object for table hg_admin_dept operations.
// AdminDept is globally public accessible object for table hg_admin_dept operations.
AdminDept = adminDeptDao{
internal.NewAdminDeptDao(),
}

View File

@@ -18,7 +18,7 @@ type adminMemberDao struct {
}
var (
// AdminMember is globally common accessible object for table hg_admin_member operations.
// AdminMember is globally public accessible object for table hg_admin_member operations.
AdminMember = adminMemberDao{
internal.NewAdminMemberDao(),
}

View File

@@ -18,7 +18,7 @@ type adminMemberPostDao struct {
}
var (
// AdminMemberPost is globally common accessible object for table hg_admin_member_post operations.
// AdminMemberPost is globally public accessible object for table hg_admin_member_post operations.
AdminMemberPost = adminMemberPostDao{
internal.NewAdminMemberPostDao(),
}

View File

@@ -18,7 +18,7 @@ type adminMemberRoleDao struct {
}
var (
// AdminMemberRole is globally common accessible object for table hg_admin_member_role operations.
// AdminMemberRole is globally public accessible object for table hg_admin_member_role operations.
AdminMemberRole = adminMemberRoleDao{
internal.NewAdminMemberRoleDao(),
}

View File

@@ -18,7 +18,7 @@ type adminMenuDao struct {
}
var (
// AdminMenu is globally common accessible object for table hg_admin_menu operations.
// AdminMenu is globally public accessible object for table hg_admin_menu operations.
AdminMenu = adminMenuDao{
internal.NewAdminMenuDao(),
}

View File

@@ -18,7 +18,7 @@ type adminNoticeDao struct {
}
var (
// AdminNotice is globally common accessible object for table hg_admin_notice operations.
// AdminNotice is globally public accessible object for table hg_admin_notice operations.
AdminNotice = adminNoticeDao{
internal.NewAdminNoticeDao(),
}

View File

@@ -18,7 +18,7 @@ type adminPostDao struct {
}
var (
// AdminPost is globally common accessible object for table hg_admin_post operations.
// AdminPost is globally public accessible object for table hg_admin_post operations.
AdminPost = adminPostDao{
internal.NewAdminPostDao(),
}

View File

@@ -18,7 +18,7 @@ type adminRoleDao struct {
}
var (
// AdminRole is globally common accessible object for table hg_admin_role operations.
// AdminRole is globally public accessible object for table hg_admin_role operations.
AdminRole = adminRoleDao{
internal.NewAdminRoleDao(),
}

View File

@@ -18,7 +18,7 @@ type adminRoleMenuDao struct {
}
var (
// AdminRoleMenu is globally common accessible object for table hg_admin_role_menu operations.
// AdminRoleMenu is globally public accessible object for table hg_admin_role_menu operations.
AdminRoleMenu = adminRoleMenuDao{
internal.NewAdminRoleMenuDao(),
}

View File

@@ -21,6 +21,9 @@ type AddonHgexampleTableDao struct {
// AddonHgexampleTableColumns defines and stores column names for table hg_addon_hgexample_table.
type AddonHgexampleTableColumns struct {
Id string // ID
Pid string // 上级ID
Level string // 树等级
Tree string // 关系树
CategoryId string // 分类ID
Flag string // 标签
Title string // 标题
@@ -47,9 +50,6 @@ type AddonHgexampleTableColumns struct {
Hobby string // 爱好
Channel string // 渠道
CityId string // 所在城市
Pid string // 上级ID
Level string // 树等级
Tree string // 关系树
Remark string // 备注
Status string // 状态
CreatedBy string // 创建者
@@ -62,6 +62,9 @@ type AddonHgexampleTableColumns struct {
// addonHgexampleTableColumns holds the columns for table hg_addon_hgexample_table.
var addonHgexampleTableColumns = AddonHgexampleTableColumns{
Id: "id",
Pid: "pid",
Level: "level",
Tree: "tree",
CategoryId: "category_id",
Flag: "flag",
Title: "title",
@@ -88,9 +91,6 @@ var addonHgexampleTableColumns = AddonHgexampleTableColumns{
Hobby: "hobby",
Channel: "channel",
CityId: "city_id",
Pid: "pid",
Level: "level",
Tree: "tree",
Remark: "remark",
Status: "status",
CreatedBy: "created_by",

View File

@@ -0,0 +1,93 @@
// ==========================================================================
// Code generated and maintained by GoFrame CLI tool. DO NOT EDIT.
// ==========================================================================
package internal
import (
"context"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
)
// AddonHgexampleTenantOrderDao is the data access object for table hg_addon_hgexample_tenant_order.
type AddonHgexampleTenantOrderDao struct {
table string // table is the underlying table name of the DAO.
group string // group is the database configuration group name of current DAO.
columns AddonHgexampleTenantOrderColumns // columns contains all the column names of Table for convenient usage.
}
// AddonHgexampleTenantOrderColumns defines and stores column names for table hg_addon_hgexample_tenant_order.
type AddonHgexampleTenantOrderColumns struct {
Id string // 主键
TenantId string // 租户ID
MerchantId string // 商户ID
UserId string // 用户ID
ProductName string // 购买产品
OrderSn string // 订单号
Money string // 充值金额
Remark string // 备注
Status string // 订单状态
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
}
// addonHgexampleTenantOrderColumns holds the columns for table hg_addon_hgexample_tenant_order.
var addonHgexampleTenantOrderColumns = AddonHgexampleTenantOrderColumns{
Id: "id",
TenantId: "tenant_id",
MerchantId: "merchant_id",
UserId: "user_id",
ProductName: "product_name",
OrderSn: "order_sn",
Money: "money",
Remark: "remark",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewAddonHgexampleTenantOrderDao creates and returns a new DAO object for table data access.
func NewAddonHgexampleTenantOrderDao() *AddonHgexampleTenantOrderDao {
return &AddonHgexampleTenantOrderDao{
group: "default",
table: "hg_addon_hgexample_tenant_order",
columns: addonHgexampleTenantOrderColumns,
}
}
// DB retrieves and returns the underlying raw database management object of current DAO.
func (dao *AddonHgexampleTenantOrderDao) DB() gdb.DB {
return g.DB(dao.group)
}
// Table returns the table name of current dao.
func (dao *AddonHgexampleTenantOrderDao) Table() string {
return dao.table
}
// Columns returns all column names of current dao.
func (dao *AddonHgexampleTenantOrderDao) Columns() AddonHgexampleTenantOrderColumns {
return dao.columns
}
// Group returns the configuration group name of database of current dao.
func (dao *AddonHgexampleTenantOrderDao) Group() string {
return dao.group
}
// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation.
func (dao *AddonHgexampleTenantOrderDao) Ctx(ctx context.Context) *gdb.Model {
return dao.DB().Model(dao.table).Safe().Ctx(ctx)
}
// Transaction wraps the transaction logic using function f.
// It rollbacks the transaction and returns the error from function f if it returns non-nil error.
// It commits the transaction and returns nil if function f returns nil.
//
// Note that, you should not Commit or Rollback the transaction in function f
// as it is automatically handled by this function.
func (dao *AddonHgexampleTenantOrderDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) {
return dao.Ctx(ctx).Transaction(ctx, f)
}

View File

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

View File

@@ -20,32 +20,38 @@ type SysLoginLogDao struct {
// SysLoginLogColumns defines and stores column names for table hg_sys_login_log.
type SysLoginLogColumns struct {
Id string // 日志ID
ReqId string // 请求ID
MemberId string // 用户ID
Username string // 用户名
Response string // 响应数据
LoginAt string // 登录时间
LoginIp string // 登录IP
ErrMsg string // 错误提示
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
Id string // 日志ID
ReqId string // 请求ID
MemberId string // 用户ID
Username string // 用户名
Response string // 响应数据
LoginAt string // 登录时间
LoginIp string // 登录IP
ProvinceId string // 省编码
CityId string // 市编码
UserAgent string // UA信息
ErrMsg string // 错误提示
Status string // 状态
CreatedAt string // 创建时间
UpdatedAt string // 修改时间
}
// sysLoginLogColumns holds the columns for table hg_sys_login_log.
var sysLoginLogColumns = SysLoginLogColumns{
Id: "id",
ReqId: "req_id",
MemberId: "member_id",
Username: "username",
Response: "response",
LoginAt: "login_at",
LoginIp: "login_ip",
ErrMsg: "err_msg",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
Id: "id",
ReqId: "req_id",
MemberId: "member_id",
Username: "username",
Response: "response",
LoginAt: "login_at",
LoginIp: "login_ip",
ProvinceId: "province_id",
CityId: "city_id",
UserAgent: "user_agent",
ErrMsg: "err_msg",
Status: "status",
CreatedAt: "created_at",
UpdatedAt: "updated_at",
}
// NewSysLoginLogDao creates and returns a new DAO object for table data access.

View File

@@ -22,6 +22,7 @@ type TestCategoryDao struct {
type TestCategoryColumns struct {
Id string // 分类ID
Name string // 分类名称
ShortName string // 简称
Description string // 描述
Sort string // 排序
Remark string // 备注
@@ -35,6 +36,7 @@ type TestCategoryColumns struct {
var testCategoryColumns = TestCategoryColumns{
Id: "id",
Name: "name",
ShortName: "short_name",
Description: "description",
Sort: "sort",
Remark: "remark",

View File

@@ -18,7 +18,7 @@ type sysConfigDao struct {
}
var (
// SysConfig is globally common accessible object for table hg_sys_config operations.
// SysConfig is globally public accessible object for table hg_sys_config operations.
SysConfig = sysConfigDao{
internal.NewSysConfigDao(),
}

View File

@@ -18,7 +18,7 @@ type sysDictDataDao struct {
}
var (
// SysDictData is globally common accessible object for table hg_sys_dict_data operations.
// SysDictData is globally public accessible object for table hg_sys_dict_data operations.
SysDictData = sysDictDataDao{
internal.NewSysDictDataDao(),
}

View File

@@ -18,7 +18,7 @@ type sysDictTypeDao struct {
}
var (
// SysDictType is globally common accessible object for table hg_sys_dict_type operations.
// SysDictType is globally public accessible object for table hg_sys_dict_type operations.
SysDictType = sysDictTypeDao{
internal.NewSysDictTypeDao(),
}

View File

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

View File

@@ -18,7 +18,7 @@ type sysLogDao struct {
}
var (
// SysLog is globally common accessible object for table hg_sys_log operations.
// SysLog is globally public accessible object for table hg_sys_log operations.
SysLog = sysLogDao{
internal.NewSysLogDao(),
}

View File

@@ -18,7 +18,7 @@ type sysProvincesDao struct {
}
var (
// SysProvinces is globally common accessible object for table hg_sys_provinces operations.
// SysProvinces is globally public accessible object for table hg_sys_provinces operations.
SysProvinces = sysProvincesDao{
internal.NewSysProvincesDao(),
}

View File

@@ -13,12 +13,12 @@ import (
"hotgo/internal/library/hgrds/lock"
"hotgo/internal/library/hgrds/pubsub"
"hotgo/internal/service"
"hotgo/utility/simple"
)
// SubscribeClusterSync 订阅集群同步,可以用来集中同步数据、状态等
func SubscribeClusterSync(ctx context.Context) {
isCluster := g.Cfg().MustGet(ctx, "hotgo.isCluster").Bool()
if !isCluster {
if !simple.IsCluster(ctx) {
return
}
@@ -35,8 +35,7 @@ func SubscribeClusterSync(ctx context.Context) {
// PublishClusterSync 推送集群同步消息,如果没有开启集群部署,则不进行推送
func PublishClusterSync(ctx context.Context, channel string, message interface{}) {
isCluster := g.Cfg().MustGet(ctx, "hotgo.isCluster").Bool()
if !isCluster {
if !simple.IsCluster(ctx) {
return
}

View File

@@ -154,7 +154,7 @@ func InitTrace(ctx context.Context) {
// SetGFMode 设置gf运行模式
func SetGFMode(ctx context.Context) {
mode := g.Cfg().MustGet(ctx, "hotgo.mode").String()
mode := g.Cfg().MustGet(ctx, "system.mode").String()
if len(mode) == 0 {
mode = gmode.NOT_SET
}

View File

@@ -18,9 +18,9 @@ func GetResourcePath(ctx context.Context) string {
if len(cacheResourcePath) > 0 {
return cacheResourcePath
}
basePath := g.Cfg().MustGet(ctx, "hotgo.addonsResourcePath").String()
basePath := g.Cfg().MustGet(ctx, "system.addonsResourcePath").String()
if basePath == "" {
g.Log().Warning(ctx, "addons GetResourcePath not config found:'hotgo.addonsResourcePath', use default values:'resource'")
g.Log().Warning(ctx, "addons GetResourcePath not config found:'system.addonsResourcePath', use default values:'resource'")
basePath = "resource"
}

View File

@@ -45,7 +45,7 @@ func Build(ctx context.Context, option *BuildOption) (err error) {
)
if resourcePath == "" {
err = gerror.New("请先设置一个有效的插件资源路径,配置名称:'hotgo.addonsResourcePath'")
err = gerror.New("请先设置一个有效的插件资源路径,配置名称:'system.addonsResourcePath'")
return
}

View File

@@ -11,7 +11,6 @@ import (
"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"
"sync"
@@ -27,16 +26,15 @@ type Option struct {
// Skeleton 模块骨架
type Skeleton struct {
Label string `json:"label"` // 标识
Name string `json:"name"` // 名称
Group int `json:"group"` // 分组
Logo string `json:"logo"` // logo
Brief string `json:"brief"` // 简介
Description string `json:"description"` // 详细描述
Author string `json:"author"` // 作者
Version string `json:"version"` // 版本号
RootPath string `json:"rootPath"` // 根路径
View *gview.View `json:"view"` // 模板引擎
Label string `json:"label"` // 标识
Name string `json:"name"` // 名称
Group int `json:"group"` // 分组
Logo string `json:"logo"` // logo
Brief string `json:"brief"` // 简介
Description string `json:"description"` // 详细描述
Author string `json:"author"` // 作者
Version string `json:"version"` // 版本号
RootPath string `json:"rootPath"` // 根路径
}
func (s *Skeleton) GetModule() Module {
@@ -99,7 +97,6 @@ func RegisterModule(m Module) Module {
}
sk.RootPath = GetModulePath(name)
sk.View = NewView(m.Ctx(), name)
modules[name] = m
return m
}
@@ -139,40 +136,6 @@ func GetModuleRealPath(name string) string {
return path
}
// NewView 初始化一个插件的模板引擎
func NewView(ctx context.Context, name string) *gview.View {
basePath := GetResourcePath(ctx)
if basePath == "" {
return nil
}
view := gview.New()
path := ViewPath(name, basePath)
if !gfile.IsDir(gfile.RealPath(path)) {
g.Log().Warningf(ctx, "NewView template path does not exist:%v,default use of main module template.", path)
return nil
}
if err := view.SetPath(path); err != nil {
g.Log().Warningf(ctx, "NewView SetPath err:%+v", err)
return nil
}
// 默认和主模块使用一致的变量分隔符号
delimiters := g.Cfg().MustGet(ctx, "viewer.delimiters", []string{"@{", "}"}).Strings()
if len(delimiters) != 2 {
g.Log().Warning(ctx, "NewView delimiters config error")
return nil
}
view.SetDelimiters(delimiters[0], delimiters[1])
// 更多配置
// view.SetI18n()
// ...
return view
}
// AddStaticPath 设置插件静态目录映射
func AddStaticPath(ctx context.Context, server *ghttp.Server) {
basePath := GetResourcePath(ctx)

View File

@@ -48,7 +48,7 @@ func Generate(ctx context.Context) (id string, base64 string) {
}
c := base64Captcha.NewCaptcha(driver.ConvertFonts(), base64Captcha.DefaultMemStore)
id, base64, err := c.Generate()
id, base64, _, err := c.Generate()
if err != nil {
g.Log().Errorf(ctx, "captcha.Generate err:%+v", err)
}

View File

@@ -8,8 +8,11 @@ package casbin
import (
"context"
"github.com/casbin/casbin/v2"
"github.com/casbin/casbin/v2/model"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gfile"
"github.com/gogf/gf/v2/os/gres"
"hotgo/internal/consts"
"net/http"
"strings"
@@ -37,12 +40,29 @@ func InitEnforcer(ctx context.Context) {
return
}
Enforcer, err = casbin.NewEnforcer("./manifest/config/casbin.conf", a)
if err != nil {
g.Log().Panicf(ctx, "casbin.NewEnforcer err . %v", err)
return
path := "manifest/config/casbin.conf"
// 优先从本地加载casbin.conf如果不存在就从资源文件中找
modelContent := gfile.GetContents(path)
if len(modelContent) == 0 {
if !gres.IsEmpty() && gres.Contains(path) {
modelContent = string(gres.GetContent(path))
}
}
if len(modelContent) == 0 {
g.Log().Panicf(ctx, "casbin model file does not exist%v", path)
}
m, err := model.NewModelFromString(modelContent)
if err != nil {
g.Log().Panicf(ctx, "casbin NewModelFromString err%v", err)
}
Enforcer, err = casbin.NewEnforcer(m, a)
if err != nil {
g.Log().Panicf(ctx, "casbin NewEnforcer err%v", err)
}
loadPermissions(ctx)
}

View File

@@ -96,6 +96,35 @@ func GetRoleKey(ctx context.Context) string {
return user.RoleKey
}
// GetDeptType 获取用户部门类型
func GetDeptType(ctx context.Context) string {
user := GetUser(ctx)
if user == nil {
return ""
}
return user.DeptType
}
// IsCompanyDept 是否为公司部门
func IsCompanyDept(ctx context.Context) bool {
return GetDeptType(ctx) == consts.DeptTypeCompany
}
// IsTenantDept 是否为租户部门
func IsTenantDept(ctx context.Context) bool {
return GetDeptType(ctx) == consts.DeptTypeTenant
}
// IsMerchantDept 是否为商户部门
func IsMerchantDept(ctx context.Context) bool {
return GetDeptType(ctx) == consts.DeptTypeMerchant
}
// IsUserDept 是否为普通用户部门
func IsUserDept(ctx context.Context) bool {
return GetDeptType(ctx) == consts.DeptTypeUser
}
// GetModule 获取应用模块
func GetModule(ctx context.Context) string {
c := Get(ctx)

View File

@@ -9,6 +9,7 @@ import (
"context"
"errors"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"hash/fnv"
"hotgo/internal/model"
"strconv"
@@ -40,6 +41,7 @@ func GetOptionsById(ctx context.Context, id int64) (opts []*model.Option, err er
}
for _, v := range GetAllFunc() {
g.Log().Warningf(ctx, "GetAllFunc GetOptionsById v:%v, %v", v.Id, v.Key)
if v.Id == id {
return LoadFuncOptions(ctx, v)
}
@@ -49,6 +51,24 @@ func GetOptionsById(ctx context.Context, id int64) (opts []*model.Option, err er
return
}
// GetTypeById 通过类型ID获取内置选项类型
func GetTypeById(ctx context.Context, id int64) (typ string, err error) {
for _, v := range GetAllEnums() {
if v.Id == id {
return v.Key, nil
}
}
for _, v := range GetAllFunc() {
if v.Id == id {
return v.Key, nil
}
}
err = NotExistKeyError
return
}
// GenIdHash 生成字典id
func GenIdHash(str string, t int64) int64 {
prefix := 10000 * t

View File

@@ -56,9 +56,7 @@ func RegisterEnums(key, label string, opts []*model.Option) {
func SaveEnums(key, label string, opts []*model.Option) {
eLock.Lock()
defer eLock.Unlock()
if _, ok := enumsOptions[key]; ok {
delete(enumsOptions, key)
}
delete(enumsOptions, key)
RegisterEnums(key, label, opts)
}

View File

@@ -67,9 +67,7 @@ func RegisterFunc(key, label string, fun FuncDict, cache ...bool) {
func SaveFunc(key, label string, fun FuncDict, cache ...bool) {
fLock.Lock()
defer fLock.Unlock()
if _, ok := funcOptions[key]; ok {
delete(funcOptions, key)
}
delete(funcOptions, key)
RegisterFunc(key, label, fun, cache...)
}

View File

@@ -6,7 +6,9 @@
package hggen
import (
"github.com/gogf/gf/v2/os/gfile"
_ "hotgo/internal/library/hggen/internal/cmd/gendao"
"hotgo/internal/library/hggen/internal/utility/utils"
_ "unsafe"
"context"
@@ -31,13 +33,37 @@ func doGenDaoForArray(ctx context.Context, index int, in gendao.CGenDaoInput)
// Dao 生成数据库实体
func Dao(ctx context.Context) (err error) {
// 在执行gf gen dao时先将生成文件放在临时路径生成完成后再拷贝到项目
// 目的是希望减少触发gf热编译的几率防止热编译运行时代码生成流程未结束被自动重启打断
// gf gen dao 的执行时长主要取决于需要生成数据库表的数量,表越多速度越慢
tempPathPrefix := views.GetTempGeneratePath(ctx) + "/dao"
for _, v := range daoConfig {
inp := defaultGenDaoInput
err = gconv.Scan(v, &inp)
if err != nil {
if err = gconv.Scan(v, &inp); err != nil {
return
}
oldPath := inp.Path
inp.ImportPrefix = utils.GetImportPath(inp.Path)
inp.Path = tempPathPrefix + "/" + inp.Path
if err = gfile.Remove(inp.Path); err != nil {
err = gerror.Newf("清理临时生成目录失败:%v", err)
return err
}
if err = gfile.Mkdir(inp.Path); err != nil {
err = gerror.Newf("创建临时生成目录失败:%v", err)
return err
}
doGenDaoForArray(ctx, -1, inp)
if err = gfile.CopyDir(inp.Path, gfile.Pwd()+"/"+oldPath); err != nil {
err = gerror.Newf("拷贝生成文件失败:%v", err)
return err
}
}
return
}
@@ -129,8 +155,16 @@ func TableSelects(ctx context.Context, in *sysin.GenCodesSelectsInp) (res *sysin
Label: v,
})
}
for _, v := range views.TableAligns {
res.TableAlign = append(res.TableAlign, &form.Select{
Value: v,
Name: views.TableAlignMap[v],
Label: views.TableAlignMap[v],
})
}
res.Addons = addons.ModuleSelect()
res.TreeStyleType = consts.GenCodesTreeStyleTypeOptions
return
}
@@ -196,15 +230,12 @@ func Preview(ctx context.Context, in *sysin.GenCodesPreviewInp) (res *sysin.GenC
}
switch in.GenType {
case consts.GenCodesTypeCurd:
case consts.GenCodesTypeCurd, consts.GenCodesTypeTree:
return views.Curd.DoPreview(ctx, &views.CurdPreviewInput{
In: in,
DaoConfig: GetDaoConfig(in.DbName),
Config: genConfig,
})
case consts.GenCodesTypeTree:
err = gerror.Newf("生成类型开发中!")
return
case consts.GenCodesTypeQueue:
err = gerror.Newf("生成类型开发中!")
return
@@ -222,7 +253,7 @@ func Build(ctx context.Context, in *sysin.GenCodesBuildInp) (err error) {
}
switch in.GenType {
case consts.GenCodesTypeCurd:
case consts.GenCodesTypeCurd, consts.GenCodesTypeTree:
pin := &sysin.GenCodesPreviewInp{SysGenCodes: in.SysGenCodes}
return views.Curd.DoBuild(ctx, &views.CurdBuildInput{
PreviewIn: &views.CurdPreviewInput{
@@ -233,25 +264,17 @@ func Build(ctx context.Context, in *sysin.GenCodesBuildInp) (err error) {
BeforeEvent: views.CurdBuildEvent{"runDao": Dao},
AfterEvent: views.CurdBuildEvent{"runService": func(ctx context.Context) (err error) {
cfg := GetServiceConfig()
if err = ServiceWithCfg(ctx, cfg); err != nil {
return
}
// 插件模块,同时运行模块下的gen service
// 插件模块,切换到插件下运行gen service
if genConfig.Application.Crud.Templates[pin.GenTemplate].IsAddon {
// 依然使用配置中的参数,只是将生成路径指向插件模块路径
cfg.SrcFolder = "addons/" + pin.AddonName + "/logic"
cfg.DstFolder = "addons/" + pin.AddonName + "/service"
if err = ServiceWithCfg(ctx, cfg); err != nil {
return
}
}
err = ServiceWithCfg(ctx, cfg)
return
}},
})
case consts.GenCodesTypeTree:
err = gerror.Newf("生成类型开发中!")
return
case consts.GenCodesTypeQueue:
err = gerror.Newf("生成类型开发中!")
return

View File

@@ -25,6 +25,7 @@ import (
)
var (
// Init .
Init = cInit{}
)
@@ -64,14 +65,13 @@ type cInitInput struct {
Name string `name:"NAME" arg:"true" v:"required" brief:"{cInitNameBrief}"`
Mono bool `name:"mono" short:"m" brief:"initialize a mono-repo instead a single-repo" orphan:"true"`
Update bool `name:"update" short:"u" brief:"update to the latest goframe version" orphan:"true"`
Module string `name:"module" short:"g" brief:"custom go module"`
}
type cInitOutput struct{}
func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err error) {
var (
overwrote = false
)
var overwrote = false
if !gfile.IsEmpty(in.Name) && !allyes.Check() {
s := gcmd.Scanf(`the folder "%s" is not empty, files might be overwrote, continue? [y/n]: `, in.Name)
if strings.EqualFold(s, "n") {
@@ -105,7 +105,7 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
err = gfile.ReadLines(gitignoreFile, func(line string) error {
// Add only hidden files or directories
// If other directories are added, it may cause the entire directory to be ignored
// such as 'main' in the .gitignore file, but the path is 'D:\main\my-project'
// such as 'main' in the .gitignore file, but the path is ' D:\main\my-project '
if line != "" && strings.HasPrefix(line, ".") {
ignoreFiles = append(ignoreFiles, line)
}
@@ -118,6 +118,11 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
}
}
// Replace module name.
if in.Module == "" {
in.Module = gfile.Basename(gfile.RealPath(in.Name))
}
// Replace template name to project name.
err = gfile.ReplaceDirFunc(func(path, content string) string {
for _, ignoreFile := range ignoreFiles {
@@ -125,7 +130,7 @@ func (c cInit) Index(ctx context.Context, in cInitInput) (out *cInitOutput, err
return content
}
}
return gstr.Replace(gfile.GetContents(path), cInitRepoPrefix+templateRepoName, gfile.Basename(gfile.RealPath(in.Name)))
return gstr.Replace(gfile.GetContents(path), cInitRepoPrefix+templateRepoName, in.Module)
}, in.Name, "*", true)
if err != nil {
return

View File

@@ -135,9 +135,14 @@ func generateStructFieldDefinition(
" #" + gstr.CaseCamel(newFiledName),
" #" + localTypeNameStr,
}
attrLines = append(attrLines, " #"+fmt.Sprintf(tagKey+`json:"%s"`, jsonTag))
attrLines = append(attrLines, " #"+fmt.Sprintf(`description:"%s"`+tagKey, descriptionTag))
attrLines = append(attrLines, " #"+fmt.Sprintf(`// %s`, formatComment(field.Comment)))
attrLines = append(attrLines, fmt.Sprintf(` #%sjson:"%s"`, tagKey, jsonTag))
// orm tag
if !in.IsDo {
// entity
attrLines = append(attrLines, fmt.Sprintf(` #orm:"%s"`, field.Name))
}
attrLines = append(attrLines, fmt.Sprintf(` #description:"%s"%s`, descriptionTag, tagKey))
attrLines = append(attrLines, fmt.Sprintf(` #// %s`, formatComment(field.Comment)))
for k, v := range attrLines {
if in.NoJsonTag {

View File

@@ -181,12 +181,12 @@ func setDefaultFormMode(field *sysin.GenCodesColumnListModel) {
return
}
if field.GoType == GoTypeString && field.Length >= 200 && field.Length <= 500 {
if field.GoType == GoTypeString && field.Length >= 256 && field.Length <= 512 {
field.FormMode = FormModeInputTextarea
return
}
if field.GoType == GoTypeString && field.Length > 500 {
if field.GoType == GoTypeString && field.Length > 512 {
field.FormMode = FormModeInputEditor
return
}

View File

@@ -3,12 +3,12 @@
// @Copyright Copyright (c) 2023 HotGo CLI
// @Author Ms <133814250@qq.com>
// @License https://github.com/bufanyun/hotgo/blob/master/LICENSE
//
package views
import (
"github.com/gogf/gf/v2/text/gstr"
"hotgo/internal/model/input/sysin"
"hotgo/utility/validate"
)
// 字段映射关系
@@ -109,6 +109,8 @@ const (
FormModeCheckbox = "Checkbox" // 复选按钮
FormModeSelect = "Select" // 单选下拉框
FormModeSelectMultiple = "SelectMultiple" // 多选下拉框
FormModeTreeSelect = "TreeSelect" // 树型选择
FormModeCascader = "Cascader" // 级联选择
FormModeUploadImage = "UploadImage" // 单图上传
FormModeUploadImages = "UploadImages" // 多图上传
FormModeUploadFile = "UploadFile" // 单文件上传
@@ -116,12 +118,13 @@ const (
FormModeSwitch = "Switch" // 开关
FormModeRate = "Rate" // 评分
FormModeCitySelector = "CitySelector" // 省市区选择
FormModePidTreeSelect = "PidTreeSelect" // 树型上级选择,树表生成专用
)
var FormModes = []string{
FormModeInput, FormModeInputNumber, FormModeInputTextarea, FormModeInputEditor, FormModeInputDynamic,
FormModeDate, FormModeDateRange, FormModeTime, FormModeTimeRange,
FormModeRadio, FormModeCheckbox, FormModeSelect, FormModeSelectMultiple,
FormModeRadio, FormModeCheckbox, FormModeSelect, FormModeSelectMultiple, FormModeTreeSelect, FormModeCascader,
FormModeUploadImage, FormModeUploadImages, FormModeUploadFile, FormModeUploadFiles,
FormModeSwitch,
FormModeRate,
@@ -142,6 +145,8 @@ var FormModeMap = map[string]string{
FormModeCheckbox: "复选按钮",
FormModeSelect: "单选下拉框",
FormModeSelectMultiple: "多选下拉框",
FormModeTreeSelect: "树型选择",
FormModeCascader: "级联选择",
FormModeUploadImage: "单图上传",
FormModeUploadImages: "多图上传",
FormModeUploadFile: "单文件上传",
@@ -190,20 +195,20 @@ var FormRoleMap = map[string]string{
// 查询条件
const (
WhereModeEq = "=" // =
WhereModeNeq = "!=" // !=
WhereModeGt = ">" // >
WhereModeGte = ">=" // >=
WhereModeLt = "<" // <
WhereModeLte = "<=" // <=
WhereModeIn = "IN" // IN (...)
WhereModeNotIn = "NOT IN" // NOT IN (...)
WhereModeBetween = "BETWEEN" // BETWEEN
WhereModeNotBetween = "NOT BETWEEN" // NOT BETWEEN
WhereModeLike = "LIKE" // LIKE
WhereModeLikeAll = "LIKE %...%" // LIKE %...%
WhereModeNotLike = "NOT LIKE" // NOT LIKE
WhereModeJsonContains = "JSON_CONTAINS(json_doc, val)" // JSON_CONTAINS(json_doc, val[, path]) // 判断是否包含某个json值
WhereModeEq = "=" // =
WhereModeNeq = "!=" // !=
WhereModeGt = ">" // >
WhereModeGte = ">=" // >=
WhereModeLt = "<" // <
WhereModeLte = "<=" // <=
WhereModeIn = "IN" // IN (...)
WhereModeNotIn = "NOT IN" // NOT IN (...)
WhereModeBetween = "BETWEEN" // BETWEEN
WhereModeNotBetween = "NOT BETWEEN" // NOT BETWEEN
WhereModeLike = "LIKE" // LIKE
WhereModeLikeAll = "LIKE %...%" // LIKE %...%
WhereModeNotLike = "NOT LIKE" // NOT LIKE
WhereModeJsonContains = "JSON_CONTAINS(doc, val)" // JSON_CONTAINS(json_doc, val[, path]) // 判断是否包含某个json值
)
var WhereModes = []string{WhereModeEq,
@@ -214,6 +219,21 @@ var WhereModes = []string{WhereModeEq,
WhereModeJsonContains,
}
// 表格列的排序方式
const (
TableAlignLeft = "left"
TableAlignRight = "right"
TableAlignCenter = "center"
)
var TableAligns = []string{TableAlignLeft, TableAlignRight, TableAlignCenter}
var TableAlignMap = map[string]string{
TableAlignLeft: "居左",
TableAlignRight: "居右",
TableAlignCenter: "居中",
}
// IsNumberType 是否是数字类型
func IsNumberType(goType string) bool {
switch goType {
@@ -225,8 +245,17 @@ func IsNumberType(goType string) bool {
return false
}
func HasColumn(masterFields []*sysin.GenCodesColumnListModel, column string) bool {
for _, field := range masterFields {
// IsSelectFormMode 是否是选择器组件
func IsSelectFormMode(formMode string) bool {
switch formMode {
case FormModeRadio, FormModeCheckbox, FormModeSelect, FormModeSelectMultiple, FormModeCitySelector, FormModeTreeSelect, FormModeCascader:
return true
}
return false
}
func HasColumn(fields []*sysin.GenCodesColumnListModel, column string) bool {
for _, field := range fields {
if field.GoName == column {
return true
}
@@ -234,29 +263,77 @@ func HasColumn(masterFields []*sysin.GenCodesColumnListModel, column string) boo
return false
}
func HasColumnWithFormMode(masterFields []*sysin.GenCodesColumnListModel, column string) bool {
for _, field := range masterFields {
if field.FormMode == column {
func HasColumnWithFormMode(fields []*sysin.GenCodesColumnListModel, formMode string) bool {
for _, field := range fields {
if field.FormMode == formMode {
return true
}
}
return false
}
func HasMaxSort(masterFields []*sysin.GenCodesColumnListModel) bool {
return HasColumn(masterFields, "Sort")
func HasMaxSort(fields []*sysin.GenCodesColumnListModel) bool {
return HasColumn(fields, "Sort")
}
func HasStatus(headOps []string, masterFields []*sysin.GenCodesColumnListModel) bool {
func HasStatus(headOps []string, fields []*sysin.GenCodesColumnListModel) bool {
if !gstr.InArray(headOps, "status") {
return false
}
return HasColumn(masterFields, "Status")
return HasColumn(fields, "Status")
}
func HasSwitch(headOps []string, masterFields []*sysin.GenCodesColumnListModel) bool {
if !gstr.InArray(headOps, "switch") {
return false
}
return HasColumnWithFormMode(masterFields, "Switch")
func HasSwitch(fields []*sysin.GenCodesColumnListModel) bool {
return HasColumnWithFormMode(fields, FormModeSwitch)
}
func HasHookMemberSummary(fields []*sysin.GenCodesColumnListModel) bool {
for _, field := range fields {
if IsMemberSummaryField(field.Name) {
if field.IsList {
return true
}
}
}
return false
}
func HasQueryMemberSummary(fields []*sysin.GenCodesColumnListModel) bool {
for _, field := range fields {
if IsMemberSummaryField(field.Name) {
if field.IsQuery {
return true
}
}
}
return false
}
func IsMemberSummaryField(name string) bool {
switch name {
case "created_by", "updated_by", "deleted_by":
return true
}
return false
}
// ReviseFields 校正字段值,兼容版本升级前的老数据格式
func ReviseFields(fields []*sysin.GenCodesColumnListModel) []*sysin.GenCodesColumnListModel {
for _, field := range fields {
if !validate.InSlice(TableAligns, field.Align) {
field.Align = TableAlignLeft
}
if field.Width < 1 {
field.Width = -1
}
if field.Width > 2000 {
field.Width = 2000
}
if field.FormGridSpan < 1 {
field.FormGridSpan = 1
}
}
return fields
}

View File

@@ -7,6 +7,7 @@ package views
import (
"context"
"github.com/gogf/gf/v2/container/gvar"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
@@ -17,12 +18,13 @@ import (
"hotgo/internal/consts"
"hotgo/internal/dao"
"hotgo/internal/library/hggen/internal/cmd/gendao"
"hotgo/internal/library/hggen/internal/utility/utils"
"hotgo/internal/library/hgorm"
"hotgo/internal/model"
"hotgo/internal/model/input/sysin"
"hotgo/internal/service"
"hotgo/utility/convert"
"hotgo/utility/file"
"hotgo/utility/tree"
"runtime"
"strings"
)
@@ -32,18 +34,41 @@ var Curd = gCurd{}
type gCurd struct{}
type CurdStep struct {
HasMaxSort bool `json:"hasMaxSort"`
HasAdd bool `json:"hasAdd"`
HasBatchDel bool `json:"hasBatchDel"`
HasExport bool `json:"hasExport"`
HasNotFilterAuth bool `json:"hasNotFilterAuth"`
HasEdit bool `json:"hasEdit"`
HasDel bool `json:"hasDel"`
HasView bool `json:"hasView"`
HasStatus bool `json:"hasStatus"`
HasSwitch bool `json:"hasSwitch"`
HasCheck bool `json:"hasCheck"`
HasMenu bool `json:"hasMenu"`
HasMaxSort bool // 最大排序
HasAdd bool // 表单添加
HasBatchDel bool // 批量删除
HasExport bool // 表格导出
HasNotFilterAuth bool // 不过滤认证权限
HasEdit bool // 表单编辑
HasDel bool // 删除
HasView bool // 查看详情
HasStatus bool // 修改状态
HasSwitch bool // 数值开关
HasCheck bool // 勾选列
HasMenu bool // 菜单权限
IsTreeTable bool // 树型列表
IsOptionTreeTable bool // 选项式树型列表
HasRules bool // 表单验证规则
HasRulesValidator bool // 表单验证器
HasSearchForm bool // 列表搜索
HasDict bool // 字典
HasFuncDict bool // 注册方法字典
HasQueryMemberSummary bool // 查询用户摘要
HasHookMemberSummary bool // hook用户摘要
ImportModel ImportModel // 公用导包 - model.ts
ActionColumnWidth int64 // 列表操作栏宽度
IsAddon bool // 是否是插件
}
// ImportModel 导包 - model.ts
type ImportModel struct {
NaiveUI []string
UtilsIs []string
UtilsUrl []string
UtilsDate []string
UtilsValidate []string
UtilsHotGo []string
UtilsIndex []string
}
type CurdOptionsJoin struct {
@@ -63,18 +88,52 @@ type CurdOptionsMenu struct {
Sort int `json:"sort"`
}
type OptionsTree struct {
TitleColumn string `json:"titleColumn"`
StyleType int `json:"styleType"`
TitleField *sysin.GenCodesColumnListModel
}
// PresetStep 预设生成流程参数
type PresetStep struct {
FormGridCols int `json:"formGridCols" dc:"表单显示的栅格数量"`
}
type CurdOptions struct {
AutoOps []string `json:"autoOps"`
ColumnOps []string `json:"columnOps"`
HeadOps []string `json:"headOps"`
Join []*CurdOptionsJoin `json:"join"`
Menu *CurdOptionsMenu `json:"menu"`
Tree *OptionsTree `json:"tree"`
TemplateGroup string `json:"templateGroup"`
ApiPrefix string `json:"apiPrefix"`
ImportWebApi string `json:"importWebApi"`
FuncDict *FuncDict `json:"funcDict"`
PresetStep *PresetStep `json:"presetStep"`
Step *CurdStep // 转换后的流程控制条件
DictOps CurdOptionsDict // 字典选项
dictMap g.Map // 字典选项 -> 字段映射关系
}
type FuncDict struct {
ValueColumn string // 选项值
LabelColumn string //选项名称
Value *sysin.GenCodesColumnListModel
Label *sysin.GenCodesColumnListModel
}
type CurdOptionsDict struct {
Has bool
Types []string
Schemas []*OptionsSchemasField
}
type OptionsSchemasField struct {
Field string
Type string
}
type CurdPreviewInput struct {
In *sysin.GenCodesPreviewInp // 提交参数
DaoConfig gendao.CGenDaoInput // 生成dao配置
@@ -98,31 +157,44 @@ func (l *gCurd) initInput(ctx context.Context, in *CurdPreviewInput) (err error)
in.content = new(sysin.GenCodesPreviewModel)
in.content.Views = make(map[string]*sysin.GenFile)
// 加载主表配置
if err = in.In.MasterColumns.Scan(&in.masterFields); err != nil {
return
// 初始化生成选项
if err = initOptions(in); err != nil {
return err
}
if len(in.masterFields) == 0 {
if in.masterFields, err = DoTableColumns(ctx, &sysin.GenCodesColumnListInp{Name: in.In.DbName, Table: in.In.TableName}, in.DaoConfig); err != nil {
return
}
// 初始化表字段配置
if err = initTableField(ctx, in); err != nil {
return err
}
// 主键属性
in.pk = l.getPkField(in)
if in.pk == nil {
return gerror.New("initInput no primary key is set in the table!")
}
// 加载选项
if err = in.In.Options.Scan(&in.options); err != nil {
return
// 初始化树表
if err = initTableTree(in); err != nil {
return err
}
initStep(in)
in.options.dictMap = make(g.Map)
// 初始化方法字典
if err = initFuncDict(in); err != nil {
return err
}
// 初始化生成模板
if err = initTemplate(in); err != nil {
return err
}
return
}
func initOptions(in *CurdPreviewInput) (err error) {
if err = in.In.Options.Scan(&in.options); err != nil {
return
}
in.options.dictMap = make(g.Map)
return
}
func initTemplate(in *CurdPreviewInput) (err error) {
if len(in.Config.Application.Crud.Templates)-1 < in.In.GenTemplate {
return gerror.New("没有找到生成模板的配置,请检查!")
}
@@ -141,20 +213,126 @@ func (l *gCurd) initInput(ctx context.Context, in *CurdPreviewInput) (err error)
return
}
func initFuncDict(in *CurdPreviewInput) (err error) {
if !in.options.Step.HasFuncDict || in.options.FuncDict == nil {
return
}
if len(in.options.FuncDict.LabelColumn) == 0 || len(in.options.FuncDict.ValueColumn) == 0 {
err = gerror.New("生成字典选项必须设置选项值和选项名称")
return err
}
for _, field := range in.masterFields {
if field.Name == in.options.FuncDict.ValueColumn {
in.options.FuncDict.Value = field
}
if field.Name == in.options.FuncDict.LabelColumn {
in.options.FuncDict.Label = field
}
}
return
}
func initTableField(ctx context.Context, in *CurdPreviewInput) (err error) {
// 加载主表配置
if err = in.In.MasterColumns.Scan(&in.masterFields); err != nil {
return
}
if len(in.masterFields) == 0 {
if in.masterFields, err = DoTableColumns(ctx, &sysin.GenCodesColumnListInp{Name: in.In.DbName, Table: in.In.TableName}, in.DaoConfig); err != nil {
return
}
}
// 主键属性
in.pk = getPkField(in)
if in.pk == nil {
return gerror.New("initInput no primary key is set in the table!")
}
in.masterFields = ReviseFields(in.masterFields)
// 检查表命名
var names = []string{in.In.DaoName}
for _, v := range in.options.Join {
v.Columns = ReviseFields(v.Columns)
names = append(names, v.DaoName)
}
if err = CheckIllegalName("数据库表名", names...); err != nil {
return
}
if err = CheckIllegalName("实体命名", in.In.VarName); err != nil {
return
}
return
}
func initTableTree(in *CurdPreviewInput) (err error) {
// 检查树表字段
if in.In.GenType == consts.GenCodesTypeTree {
if err = CheckTreeTableFields(in.masterFields); err != nil {
return err
}
// 解析选项树名称字段
has := false
for _, field := range in.masterFields {
if in.options.Tree.TitleColumn == field.Name {
in.options.Tree.TitleField = field
has = true
break
}
}
if !has {
err = gerror.New("请选择一个有效的树名称字段")
return
}
}
return err
}
func initStep(in *CurdPreviewInput) {
in.options.Step = new(CurdStep)
in.options.Step.HasMaxSort = HasMaxSort(in.masterFields)
in.options.Step.HasAdd = gstr.InArray(in.options.HeadOps, "add")
in.options.Step.HasBatchDel = gstr.InArray(in.options.HeadOps, "batchDel")
in.options.Step.HasBatchDel = gstr.InArray(in.options.HeadOps, "batchDel") && gstr.InArray(in.options.ColumnOps, "check")
in.options.Step.HasExport = gstr.InArray(in.options.HeadOps, "export")
in.options.Step.HasNotFilterAuth = gstr.InArray(in.options.ColumnOps, "notFilterAuth")
in.options.Step.HasEdit = gstr.InArray(in.options.ColumnOps, "edit")
in.options.Step.HasDel = gstr.InArray(in.options.ColumnOps, "del")
in.options.Step.HasView = gstr.InArray(in.options.ColumnOps, "view")
in.options.Step.HasStatus = HasStatus(in.options.ColumnOps, in.masterFields)
in.options.Step.HasSwitch = HasSwitch(in.options.ColumnOps, in.masterFields)
in.options.Step.HasSwitch = HasSwitch(in.masterFields)
in.options.Step.HasCheck = gstr.InArray(in.options.ColumnOps, "check")
in.options.Step.HasMenu = gstr.InArray(in.options.AutoOps, "genMenuPermissions")
in.options.Step.HasQueryMemberSummary = HasQueryMemberSummary(in.masterFields)
in.options.Step.HasHookMemberSummary = HasHookMemberSummary(in.masterFields)
in.options.Step.IsTreeTable = in.In.GenType == consts.GenCodesTypeTree
if in.options.Step.IsTreeTable {
in.options.Step.IsOptionTreeTable = in.options.Tree.StyleType == consts.GenCodesTreeStyleTypeOption
}
in.options.Step.HasFuncDict = gstr.InArray(in.options.AutoOps, "genFuncDict")
in.options.Step.IsAddon = in.Config.Application.Crud.Templates[in.In.GenTemplate].IsAddon
if in.options.PresetStep.FormGridCols < 1 {
in.options.PresetStep.FormGridCols = 1
}
}
// getPkField 获取主键
func getPkField(in *CurdPreviewInput) *sysin.GenCodesColumnListModel {
if len(in.masterFields) == 0 {
panic("getPkField masterFields uninitialized.")
}
for _, field := range in.masterFields {
if IsIndexPK(field.Index) {
return field
}
}
return nil
}
func (l *gCurd) loadView(ctx context.Context, in *CurdPreviewInput) (err error) {
@@ -170,14 +348,14 @@ func (l *gCurd) loadView(ctx context.Context, in *CurdPreviewInput) (err error)
now := gtime.Now()
view.BindFuncMap(g.Map{
"NowYear": now.Year, // 当前年
"ToLower": strings.ToLower, // 全部小写
"LcFirst": gstr.LcFirst, // 首字母小写
"UcFirst": gstr.UcFirst, // 首字母大写
"NowYear": now.Year, // 当前年
"ToLower": strings.ToLower, // 全部小写
"LcFirst": gstr.LcFirst, // 首字母小写
"UcFirst": gstr.UcFirst, // 首字母大写
"ToTSArray": ToTSArray, // 转为ts数组格式
})
dictOptions, err := l.generateWebModelDictOptions(ctx, in)
if err != nil {
if err = l.generateWebModelDictOptions(ctx, in); err != nil {
return
}
@@ -193,9 +371,9 @@ func (l *gCurd) loadView(ctx context.Context, in *CurdPreviewInput) (err error)
importService = "hotgo/addons/" + in.In.AddonName + "/service"
}
importWebApi := "@/api/" + gstr.LcFirst(in.In.VarName)
in.options.ImportWebApi = "@/api/" + gstr.LcFirst(in.In.VarName)
if temp.IsAddon {
importWebApi = "@/api/addons/" + in.In.AddonName + "/" + gstr.LcFirst(in.In.VarName)
in.options.ImportWebApi = "@/api/addons/" + in.In.AddonName + "/" + gstr.LcFirst(in.In.VarName)
}
componentPrefix := gstr.LcFirst(in.In.VarName)
@@ -216,12 +394,12 @@ func (l *gCurd) loadView(ctx context.Context, in *CurdPreviewInput) (err error)
"masterFields": in.masterFields, // 主表字段
"pk": in.pk, // 主键属性
"options": in.options, // 提交选项
"dictOptions": dictOptions, // web字典选项
"dictOptions": in.options.DictOps, // web字典选项
"importApi": importApi, // 导入goApi包
"importInput": importInput, // 导入input包
"importController": importController, // 导入控制器包
"importService": importService, // 导入业务服务
"importWebApi": importWebApi, // 导入webApi
"importWebApi": in.options.ImportWebApi, // 导入webApi
"apiPrefix": in.options.ApiPrefix, // api前缀
"componentPrefix": componentPrefix, // vue子组件前缀
})
@@ -231,6 +409,7 @@ func (l *gCurd) loadView(ctx context.Context, in *CurdPreviewInput) (err error)
}
func (l *gCurd) DoBuild(ctx context.Context, in *CurdBuildInput) (err error) {
st := gtime.Now()
preview, err := l.DoPreview(ctx, in.PreviewIn)
if err != nil {
return
@@ -296,10 +475,6 @@ func (l *gCurd) DoBuild(ctx context.Context, in *CurdBuildInput) (err error) {
if err = gfile.PutContents(vi.Path, strings.TrimSpace(vi.Content)); err != nil {
return gerror.Newf("writing content to '%s' failed: %v", vi.Path, err)
}
if gstr.Str(vi.Path, `.`) == ".go" {
utils.GoFmt(vi.Path)
}
}
// 后置操作
@@ -312,6 +487,7 @@ func (l *gCurd) DoBuild(ctx context.Context, in *CurdBuildInput) (err error) {
}
}
}
g.Log().Debugf(ctx, "generate code operation completed, %vms", gtime.Now().Sub(st).Milliseconds())
return
}
@@ -386,6 +562,11 @@ func (l *gCurd) generateApiContent(ctx context.Context, in *CurdPreviewInput) (e
return err
}
genFile.Content, err = FormatGo(ctx, name, genFile.Content)
if err != nil {
return err
}
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].ApiPath, strings.ToLower(in.In.VarName), strings.ToLower(in.In.VarName)+".go")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -417,6 +598,12 @@ func (l *gCurd) generateInputContent(ctx context.Context, in *CurdPreviewInput)
if err != nil {
return err
}
genFile.Content, err = FormatGo(ctx, name, genFile.Content)
if err != nil {
return err
}
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].InputPath, convert.CamelCaseToUnderline(in.In.VarName)+".go")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -443,6 +630,12 @@ func (l *gCurd) generateControllerContent(ctx context.Context, in *CurdPreviewIn
if err != nil {
return err
}
genFile.Content, err = FormatGo(ctx, name, genFile.Content)
if err != nil {
return err
}
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].ControllerPath, convert.CamelCaseToUnderline(in.In.VarName)+".go")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -473,6 +666,12 @@ func (l *gCurd) generateLogicContent(ctx context.Context, in *CurdPreviewInput)
if err != nil {
return err
}
genFile.Content, err = FormatGo(ctx, name, genFile.Content)
if err != nil {
return err
}
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].LogicPath, convert.CamelCaseToUnderline(in.In.VarName)+".go")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -499,6 +698,11 @@ func (l *gCurd) generateRouterContent(ctx context.Context, in *CurdPreviewInput)
return err
}
genFile.Content, err = FormatGo(ctx, name, genFile.Content)
if err != nil {
return err
}
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].RouterPath, convert.CamelCaseToUnderline(in.In.VarName)+".go")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -525,6 +729,8 @@ func (l *gCurd) generateWebApiContent(ctx context.Context, in *CurdPreviewInput)
return err
}
genFile.Content = FormatTs(genFile.Content)
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].WebApiPath, gstr.LcFirst(in.In.VarName), "index.ts")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -556,6 +762,8 @@ func (l *gCurd) generateWebModelContent(ctx context.Context, in *CurdPreviewInpu
return
}
genFile.Content = FormatTs(genFile.Content)
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].WebViewsPath, gstr.LcFirst(in.In.VarName), "model.ts")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -586,6 +794,8 @@ func (l *gCurd) generateWebIndexContent(ctx context.Context, in *CurdPreviewInpu
return err
}
genFile.Content = FormatVue(genFile.Content)
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].WebViewsPath, gstr.LcFirst(in.In.VarName), "index.vue")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -616,6 +826,8 @@ func (l *gCurd) generateWebEditContent(ctx context.Context, in *CurdPreviewInput
return err
}
genFile.Content = FormatVue(genFile.Content)
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].WebViewsPath, gstr.LcFirst(in.In.VarName), "edit.vue")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -651,6 +863,8 @@ func (l *gCurd) generateWebViewContent(ctx context.Context, in *CurdPreviewInput
return err
}
genFile.Content = FormatVue(genFile.Content)
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].WebViewsPath, gstr.LcFirst(in.In.VarName), "view.vue")
genFile.Meth = consts.GenCodesBuildMethCreate
if gfile.Exists(genFile.Path) {
@@ -683,6 +897,11 @@ func (l *gCurd) generateSqlContent(ctx context.Context, in *CurdPreviewInput) (e
genFile = new(sysin.GenFile)
)
menus, err := service.AdminMenu().GetFastList(ctx)
if err != nil {
return err
}
tplData["dirPid"], tplData["dirLevel"], tplData["dirTree"], err = hgorm.AutoUpdateTree(ctx, &dao.AdminMenu, 0, int64(in.options.Menu.Pid))
if err != nil {
return err
@@ -692,9 +911,30 @@ func (l *gCurd) generateSqlContent(ctx context.Context, in *CurdPreviewInput) (e
tplData["btnLevel"] = tplData["dirLevel"].(int) + 2
tplData["sortLevel"] = tplData["dirLevel"].(int) + 3
pageRedirect := ""
if in.options.Menu.Pid > 0 {
tplData["mainComponent"] = "ParentLayout"
menu, ok := menus[int64(in.options.Menu.Pid)]
if !ok {
err = gerror.New("选择的上级菜单不存在")
return
}
for _, id := range tree.GetIds(menu.Tree) {
if v, ok2 := menus[id]; ok2 {
if !gstr.HasSuffix(pageRedirect, "/") && !gstr.HasPrefix(v.Path, "/") {
pageRedirect += "/"
}
pageRedirect += v.Path
}
}
if !gstr.HasSuffix(pageRedirect, "/") && !gstr.HasPrefix(menu.Path, "/") {
pageRedirect += "/"
}
pageRedirect += menu.Path
}
pageRedirect += "/" + gstr.LcFirst(in.In.VarName) + "/index"
tplData["pageRedirect"] = pageRedirect
genFile.Path = file.MergeAbs(in.Config.Application.Crud.Templates[in.In.GenTemplate].SqlPath, convert.CamelCaseToUnderline(in.In.VarName)+"_menu.sql")
genFile.Meth = consts.GenCodesBuildMethCreate
@@ -708,6 +948,48 @@ func (l *gCurd) generateSqlContent(ctx context.Context, in *CurdPreviewInput) (e
genFile.Required = false
}
// 需要生成时,检查菜单命名是否存在
if genFile.Meth == consts.GenCodesBuildMethCreate {
menuNamePrefix := gstr.LcFirst(in.In.VarName)
menuNames := []string{menuNamePrefix, menuNamePrefix + "Index"}
if in.options.Step.HasEdit {
menuNames = append(menuNames, menuNamePrefix+"Edit")
menuNames = append(menuNames, menuNamePrefix+"View")
}
if in.options.Step.HasView {
menuNames = append(menuNames, menuNamePrefix+"View")
}
if in.options.Step.HasMaxSort {
menuNames = append(menuNames, menuNamePrefix+"MaxSort")
}
if in.options.Step.HasDel {
menuNames = append(menuNames, menuNamePrefix+"Delete")
}
if in.options.Step.HasStatus {
menuNames = append(menuNames, menuNamePrefix+"Status")
}
if in.options.Step.HasSwitch {
menuNames = append(menuNames, menuNamePrefix+"Switch")
}
if in.options.Step.HasExport {
menuNames = append(menuNames, menuNamePrefix+"Export")
}
if in.options.Step.IsTreeTable {
menuNames = append(menuNames, menuNamePrefix+"TreeOption")
}
menuNames = convert.UniqueSlice(menuNames)
hasMenus, err := service.AdminMenu().Model(ctx).Fields("name").WhereIn("name", menuNames).Array()
if err != nil {
return err
}
if len(hasMenus) > 0 {
err = gerror.Newf("要生成的菜单中有已存在的路由别名,请检查并删除:%v", strings.Join(gvar.New(hasMenus).Strings(), ``))
return err
}
}
tplData["generatePath"] = genFile.Path
genFile.Content, err = in.view.Parse(ctx, name+".template", tplData)
if err != nil {

View File

@@ -28,6 +28,7 @@ const (
InputTypeEditInpValidator = 4 // 添加&编辑验证器
InputTypeUpdateFields = 5 // 编辑修改过滤字段
InputTypeInsertFields = 6 // 编辑新增过滤字段
InputTypeTreeOptionFields = 7 // 关系树查询字段
EditInpValidatorGenerally = "if err := g.Validator().Rules(\"%s\").Data(in.%s).Messages(\"%s\").Run(ctx); err != nil {\n\t\treturn err.Current()\n\t}\n"
)
@@ -39,21 +40,79 @@ func (l *gCurd) inputTplData(ctx context.Context, in *CurdPreviewInput) (data g.
data["editInpValidator"] = l.generateInputListColumns(ctx, in, InputTypeEditInpValidator)
data["updateFieldsColumns"] = l.generateInputListColumns(ctx, in, InputTypeUpdateFields)
data["insertFieldsColumns"] = l.generateInputListColumns(ctx, in, InputTypeInsertFields)
data["viewModelColumns"] = l.generateInputViewColumns(ctx, in)
if in.options.Step.IsTreeTable {
data["treeOptionFields"] = l.generateInputListColumns(ctx, in, InputTypeTreeOptionFields)
}
return
}
func (l *gCurd) generateInputViewColumns(ctx context.Context, in *CurdPreviewInput) string {
buffer := bytes.NewBuffer(nil)
index := 0
array := make([][]string, 1000)
// 主表
for _, field := range in.masterFields {
// 查询用户摘要
if field.IsList && in.options.Step.HasHookMemberSummary && IsMemberSummaryField(field.Name) {
tagKey := "`"
descriptionTag := gstr.Replace(formatComment(field.Dc)+"摘要信息", `"`, `\"`)
result := []string{" #" + field.GoName + "Summa"}
result = append(result, " #*hook.MemberSumma")
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, field.TsName+"Summa"))
result = append(result, " #"+fmt.Sprintf(`dc:"%s"`+tagKey, descriptionTag))
array[index] = result
index++
}
}
tw := tablewriter.NewWriter(buffer)
tw.SetBorder(false)
tw.SetRowLine(false)
tw.SetAutoWrapText(false)
tw.SetColumnSeparator("")
tw.AppendBulk(array)
tw.Render()
stContent := buffer.String()
// Let's do this hack of table writer for indent!
stContent = gstr.Replace(stContent, " #", "")
stContent = gstr.Replace(stContent, "` ", "`")
stContent = gstr.Replace(stContent, "``", "")
stContent = removeEndWrap(stContent)
buffer.Reset()
buffer.WriteString(stContent)
return "\tentity." + in.In.DaoName + "\n" + buffer.String()
}
func (l *gCurd) generateInputListColumns(ctx context.Context, in *CurdPreviewInput, inputType int) string {
buffer := bytes.NewBuffer(nil)
index := 0
array := make([][]string, 1000)
// 主表
for _, field := range in.masterFields {
row := l.generateStructFieldDefinition(field, inputType)
row := l.generateStructFieldDefinition(in, field, inputType, true)
if row == nil {
continue
}
array[index] = row
index++
switch inputType {
case InputTypeListModel:
// 查询用户摘要
if field.IsList && in.options.Step.HasHookMemberSummary && IsMemberSummaryField(field.Name) {
tagKey := "`"
descriptionTag := gstr.Replace(formatComment(field.Dc)+"摘要信息", `"`, `\"`)
result := []string{" #" + field.GoName + "Summa"}
result = append(result, " #*hook.MemberSumma")
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, field.TsName+"Summa"))
result = append(result, " #"+fmt.Sprintf(`dc:"%s"`+tagKey, descriptionTag))
array[index] = result
index++
}
}
}
// 关联表
@@ -63,7 +122,7 @@ func (l *gCurd) generateInputListColumns(ctx context.Context, in *CurdPreviewInp
continue
}
for _, field := range v.Columns {
row := l.generateStructFieldDefinition(field, inputType)
row := l.generateStructFieldDefinition(in, field, inputType, false)
if row != nil {
array[index] = row
index++
@@ -92,43 +151,62 @@ func (l *gCurd) generateInputListColumns(ctx context.Context, in *CurdPreviewInp
}
// generateStructFieldForModel generates and returns the attribute definition for specified field.
func (l *gCurd) generateStructFieldDefinition(field *sysin.GenCodesColumnListModel, inputType int) []string {
func (l *gCurd) generateStructFieldDefinition(in *CurdPreviewInput, field *sysin.GenCodesColumnListModel, inputType int, isMaster bool) []string {
var (
tagKey = "`"
result = []string{" #" + field.GoName}
descriptionTag = gstr.Replace(formatComment(field.Dc), `"`, `\"`)
)
addResult := func() []string {
result = append(result, " #"+field.GoType)
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, field.TsName))
result = append(result, " #"+fmt.Sprintf(`dc:"%s"`+tagKey, descriptionTag))
return result
}
isQuery := false
switch inputType {
case InputTypeListInp:
if !field.IsQuery {
if in.options.Step.IsTreeTable && IsPidName(field.Name) {
isQuery = true
field.QueryWhere = WhereModeEq
}
if !field.IsQuery && !isQuery {
return nil
}
if field.QueryWhere == WhereModeBetween {
result = append(result, " #[]"+field.GoType)
} else {
result = append(result, " #"+field.GoType)
// 查询用户摘要时,固定接收字符串类型
if field.IsQuery && in.options.Step.HasQueryMemberSummary && IsMemberSummaryField(field.Name) {
result = append(result, " #string")
} else {
result = append(result, " #"+field.GoType)
}
}
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, field.TsName))
result = append(result, " #"+fmt.Sprintf(`dc:"%s"`+tagKey, descriptionTag))
case InputTypeListModel:
if !field.IsList {
// 主表的主键
if IsIndexPK(field.Index) && isMaster {
addResult()
// 树表的pid字段
} else if in.options.Step.IsTreeTable && IsPidName(field.Name) {
addResult()
} else if field.IsList {
addResult()
} else {
return nil
}
result = append(result, " #"+field.GoType)
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, field.TsName))
result = append(result, " #"+fmt.Sprintf(`dc:"%s"`+tagKey, descriptionTag))
case InputTypeExportModel:
if !field.IsExport {
return nil
}
result = append(result, " #"+field.GoType)
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, field.TsName))
result = append(result, " #"+fmt.Sprintf(`dc:"%s"`+tagKey, descriptionTag))
addResult()
case InputTypeEditInpValidator:
if !field.IsEdit {
return nil
@@ -150,18 +228,23 @@ func (l *gCurd) generateStructFieldDefinition(field *sysin.GenCodesColumnListMod
if !field.IsEdit && field.GoName != "UpdatedBy" {
return nil
}
result = append(result, " #"+field.GoType)
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, field.TsName))
result = append(result, " #"+fmt.Sprintf(`dc:"%s"`+tagKey, descriptionTag))
addResult()
case InputTypeInsertFields:
if !field.IsEdit && field.GoName != "CreatedBy" {
return nil
}
result = append(result, " #"+field.GoType)
result = append(result, " #"+fmt.Sprintf(tagKey+`json:"%s"`, field.TsName))
result = append(result, " #"+fmt.Sprintf(`dc:"%s"`+tagKey, descriptionTag))
addResult()
case InputTypeTreeOptionFields:
if IsIndexPK(field.Index) {
return addResult()
}
if IsPidName(field.Name) {
return addResult()
}
if in.options.Tree.TitleColumn == field.Name {
return addResult()
}
return nil
default:
panic("inputType is invalid")
}

View File

@@ -16,22 +16,20 @@ import (
)
const (
LogicWhereComments = "\n\t// 查询%s\n"
LogicWhereNoSupport = "\t// TODO 暂不支持生成[ %s ]查询方式,请自行补充此处代码!"
LogicListSimpleSelect = "\tfields, err := hgorm.GenSelect(ctx, sysin.%sListModel{}, dao.%s)\n\tif err != nil {\n\t\treturn\n\t}"
LogicListJoinSelect = "\t// 关联表select\n\tfields, err := hgorm.GenJoinSelect(ctx, %sin.%sListModel{}, &dao.%s, []*hgorm.Join{\n%v\t})\n\n\tif err != nil {\n\t\terr = gerror.Wrap(err, \"获取%s关联字段失败,请稍后重试!\")\n\t\treturn\n\t}"
LogicListJoinOnRelation = "\t// 关联表%s\n\tmod = mod.%s(hgorm.GenJoinOnRelation(\n\t\tdao.%s.Table(), dao.%s.Columns().%s, // 主表表名,关联字段\n\t\tdao.%s.Table(), \"%s\", dao.%s.Columns().%s, // 关联表表名,别名,关联字段\n\t)...)\n\n"
LogicEditUpdate = "\tif _, err = s.Model(ctx%s).\n\t\t\tFields(%sin.%sUpdateFields{}).\n\t\t\tWherePri(in.%s).Data(in).Update(); err != nil {\n\t\t\terr = gerror.Wrap(err, \"修改%s失败请稍后重试\")\n\t\t}\n\t\treturn"
LogicEditInsert = "\tif _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).\n\t\tFields(%sin.%sInsertFields{}).\n\t\tData(in).Insert(); err != nil {\n\t\terr = gerror.Wrap(err, \"新增%s失败请稍后重试\")\n\t}"
LogicEditUnique = "\t// 验证'%s'唯一\n\tif err = hgorm.IsUnique(ctx, &dao.%s, g.Map{dao.%s.Columns().%s: in.%s}, \"%s已存在\", in.Id); err != nil {\n\t\treturn\n\t}\n"
LogicSwitchUpdate = "g.Map{\n\t\tin.Key: in.Value,\n%s}"
LogicStatusUpdate = "g.Map{\n\t\tdao.%s.Columns().Status: in.Status,\n%s}"
LogicWhereComments = "\n\t// 查询%s\n"
LogicWhereNoSupport = "\t// TODO 暂不支持生成[ %s ]查询方式,请自行补充此处代码!"
LogicEditUpdate = "\tif _, err = s.Model(ctx%s).\n\t\t\tFields(%sin.%sUpdateFields{}).\n\t\t\tWherePri(in.%s).Data(in).Update(); err != nil {\n\t\t\terr = gerror.Wrap(err, \"修改%s失败请稍后重试\")\n\t\t}\n\t\treturn"
LogicEditInsert = "\tif _, err = s.Model(ctx, &handler.Option{FilterAuth: false}).\n\t\tFields(%sin.%sInsertFields{}).\n\t\tData(in).Insert(); err != nil {\n\t\terr = gerror.Wrap(err, \"新增%s失败,请稍后重试!\")\n\t}"
LogicEditUnique = "\t// 验证'%s'唯一\n\tif err = hgorm.IsUnique(ctx, &dao.%s, g.Map{dao.%s.Columns().%s: in.%s}, \"%s已存在\", in.Id); err != nil {\n\t\treturn\n\t}\n"
LogicSwitchUpdate = "g.Map{\n\t\tin.Key: in.Value,\n%s}"
LogicStatusUpdate = "g.Map{\n\t\tdao.%s.Columns().Status: in.Status,\n%s}"
)
func (l *gCurd) logicTplData(ctx context.Context, in *CurdPreviewInput) (data g.Map, err error) {
data = make(g.Map)
data["listWhere"] = l.generateLogicListWhere(ctx, in)
data["listJoin"] = l.generateLogicListJoin(ctx, in)
data["listFields"] = l.generateLogicListFields(ctx, in)
data["listOrder"] = l.generateLogicListOrder(ctx, in)
data["edit"] = l.generateLogicEdit(ctx, in)
data["switchFields"] = l.generateLogicSwitchFields(ctx, in)
@@ -113,76 +111,109 @@ func (l *gCurd) generateLogicEdit(ctx context.Context, in *CurdPreviewInput) g.M
}
func (l *gCurd) generateLogicListOrder(ctx context.Context, in *CurdPreviewInput) string {
statement := ""
if hasEffectiveJoins(in.options.Join) {
statement = "dao." + in.In.DaoName + ".Table() + \".\" +"
}
buffer := bytes.NewBuffer(nil)
if in.options.Step.HasMaxSort {
buffer.WriteString("OrderAsc(dao." + in.In.DaoName + ".Columns().Sort).")
buffer.WriteString("OrderAsc(" + statement + "dao." + in.In.DaoName + ".Columns().Sort).")
}
buffer.WriteString("OrderDesc(dao." + in.In.DaoName + ".Columns()." + in.pk.GoName + ")")
buffer.WriteString("OrderDesc(" + statement + "dao." + in.In.DaoName + ".Columns()." + in.pk.GoName + ")")
return buffer.String()
}
func (l *gCurd) generateLogicListJoin(ctx context.Context, in *CurdPreviewInput) g.Map {
var data = make(g.Map)
data["link"] = ""
func (l *gCurd) generateLogicListJoin(ctx context.Context, in *CurdPreviewInput) (link string) {
connector := `"="`
if hasEffectiveJoins(in.options.Join) {
var (
selectBuffer = bytes.NewBuffer(nil)
linkBuffer = bytes.NewBuffer(nil)
joinSelectRows string
)
linkBuffer := bytes.NewBuffer(nil)
for _, join := range in.options.Join {
if isEffectiveJoin(join) {
joinSelectRows = joinSelectRows + fmt.Sprintf("\t\t{Dao: &dao.%s, Alias: \"%s\"},\n", join.DaoName, join.Alias)
linkBuffer.WriteString(fmt.Sprintf(LogicListJoinOnRelation, join.Alias, consts.GenCodesJoinLinkMap[join.LinkMode], in.In.DaoName, in.In.DaoName, gstr.CaseCamel(join.MasterField), join.DaoName, join.Alias, join.DaoName, gstr.CaseCamel(join.Field)))
linkBuffer.WriteString("\tmod = mod." + consts.GenCodesJoinLinkMap[join.LinkMode] + "OnFields(dao." + join.DaoName + ".Table(), dao." + in.In.DaoName + ".Columns()." + gstr.CaseCamel(join.MasterField) + "," + connector + ", dao." + join.DaoName + ".Columns()." + gstr.CaseCamel(join.Field) + ")\n")
}
}
selectBuffer.WriteString(fmt.Sprintf(LogicListJoinSelect, in.options.TemplateGroup, in.In.VarName, in.In.DaoName, joinSelectRows, in.In.TableComment))
data["select"] = selectBuffer.String()
data["fields"] = "fields"
data["link"] = linkBuffer.String()
} else {
data["fields"] = fmt.Sprintf("%sin.%sListModel{}", in.options.TemplateGroup, in.In.VarName)
link = linkBuffer.String()
}
return data
return
}
func (l *gCurd) generateLogicListFields(ctx context.Context, in *CurdPreviewInput) (fields string) {
selectBuffer := bytes.NewBuffer(nil)
if hasEffectiveJoins(in.options.Join) {
selectBuffer.WriteString("mod = mod.FieldsPrefix(dao." + in.In.DaoName + ".Table(), " + in.options.TemplateGroup + "in." + in.In.VarName + "ListModel{})\n")
for _, join := range in.options.Join {
if isEffectiveJoin(join) {
selectBuffer.WriteString("mod = mod.Fields(hgorm.JoinFields(ctx, " + in.options.TemplateGroup + "in." + in.In.VarName + "ListModel{}, &dao." + join.DaoName + ", \"" + join.Alias + "\"))\n")
}
}
fields = selectBuffer.String()
} else {
fields = fmt.Sprintf("mod = mod.Fields(%sin.%sListModel{})", in.options.TemplateGroup, in.In.VarName)
}
return
}
func (l *gCurd) generateLogicListWhere(ctx context.Context, in *CurdPreviewInput) string {
buffer := bytes.NewBuffer(nil)
// 主表
l.generateLogicListWhereEach(buffer, in.masterFields, in.In.DaoName, "")
l.generateLogicListWhereEach(buffer, in, in.masterFields, in.In.DaoName, "")
// 关联表
if hasEffectiveJoins(in.options.Join) {
for _, v := range in.options.Join {
if isEffectiveJoin(v) {
l.generateLogicListWhereEach(buffer, v.Columns, v.DaoName, v.Alias)
l.generateLogicListWhereEach(buffer, in, v.Columns, v.DaoName, v.Alias)
}
}
}
return buffer.String()
}
func (l *gCurd) generateLogicListWhereEach(buffer *bytes.Buffer, fields []*sysin.GenCodesColumnListModel, daoName string, alias string) {
func (l *gCurd) generateLogicListWhereEach(buffer *bytes.Buffer, in *CurdPreviewInput, fields []*sysin.GenCodesColumnListModel, daoName string, alias string) {
isLink := false
if alias != "" {
alias = `"` + alias + `."+`
isLink = true
}
tablePrefix := ""
wherePrefix := "Where"
if isLink {
wherePrefix = "WherePrefix"
tablePrefix = "dao." + daoName + ".Table(), "
}
for _, field := range fields {
if !field.IsQuery || field.QueryWhere == "" {
isQuery := false
// 树表查询上级
if in.options.Step.IsTreeTable && IsPidName(field.Name) {
isQuery = true
field.QueryWhere = WhereModeEq
}
if (!field.IsQuery && !isQuery) || field.QueryWhere == "" {
continue
}
buffer.WriteString(fmt.Sprintf(LogicWhereComments, field.Dc))
var (
linkMode string
whereTag string
columnName string
)
// 查询用户摘要
if field.IsQuery && in.options.Step.HasQueryMemberSummary && IsMemberSummaryField(field.Name) {
servicePackName := "service"
if in.options.Step.IsAddon {
servicePackName = "isc"
}
buffer.WriteString(fmt.Sprintf("if in.%v != \"\" {\n\t\t\t\tids, err := %v.AdminMember().GetIdsByKeyword(ctx, in.%v)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn nil, 0, err\n\t\t\t\t}\n\t\t\t\tmod = mod.WhereIn(dao.%v.Columns().%v, ids)\n\t\t\t}\n", field.GoName, servicePackName, field.GoName, in.In.DaoName, field.GoName))
continue
}
if IsNumberType(field.GoType) {
linkMode = `in.` + field.GoName + ` > 0`
} else if field.GoType == GoTypeGTime {
@@ -197,8 +228,6 @@ func (l *gCurd) generateLogicListWhereEach(buffer *bytes.Buffer, fields []*sysin
linkMode = `len(in.` + field.GoName + `) == 2`
}
buffer.WriteString(fmt.Sprintf(LogicWhereComments, field.Dc))
// 如果是关联表重新转换字段
columnName = field.GoName
if isLink {
@@ -207,35 +236,35 @@ func (l *gCurd) generateLogicListWhereEach(buffer *bytes.Buffer, fields []*sysin
switch field.QueryWhere {
case WhereModeEq:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.Where(" + alias + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeNeq:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereNot(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "Not(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeGt:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereGT(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "GT(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeGte:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereGTE(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "GTE(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeLt:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereLT(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "LT(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeLte:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereLTE(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "LTE(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeIn:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereIn(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "In(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeNotIn:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereNotIn(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "NotIn(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeBetween:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereBetween(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + "[0], in." + field.GoName + "[1])\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "Between(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + "[0], in." + field.GoName + "[1])\n\t}"
case WhereModeNotBetween:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereNotBetween(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + "[0], in." + field.GoName + "[1])\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "NotBetween(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + "[0], in." + field.GoName + "[1])\n\t}"
case WhereModeLike:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereLike(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "Like(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeLikeAll:
val := `"%"+in.` + field.GoName + `+"%"`
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereLike(dao." + daoName + ".Columns()." + columnName + ", " + val + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "Like(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", " + val + ")\n\t}"
case WhereModeNotLike:
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod.WhereNotLike(dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
whereTag = "\tif " + linkMode + " {\n\t\tmod = mod." + wherePrefix + "NotLike(" + tablePrefix + "dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")\n\t}"
case WhereModeJsonContains:
val := "fmt.Sprintf(`JSON_CONTAINS(%s,'%v')`, dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")"
whereTag = "\tif in." + field.GoName + linkMode + " {\n\t\tmod = mod.Where(" + val + ")\n\t}"
val := tablePrefix + "fmt.Sprintf(`JSON_CONTAINS(%s,'%v')`, dao." + daoName + ".Columns()." + columnName + ", in." + field.GoName + ")"
whereTag = "\tif in." + field.GoName + linkMode + " {\n\t\tmod = mod." + wherePrefix + "(" + val + ")\n\t}"
default:
buffer.WriteString(fmt.Sprintf(LogicWhereNoSupport, field.QueryWhere))

View File

@@ -22,7 +22,7 @@ func (l *gCurd) webEditTplData(ctx context.Context, in *CurdPreviewInput) (data
func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInput) string {
buffer := bytes.NewBuffer(nil)
for k, field := range in.masterFields {
for _, field := range in.masterFields {
if !field.IsEdit {
continue
}
@@ -36,6 +36,10 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
component string
)
if in.options.Step.IsTreeTable && IsPidName(field.Name) {
field.FormMode = FormModePidTreeSelect
}
switch field.FormMode {
case FormModeInput:
component = defaultComponent
@@ -98,16 +102,45 @@ func (l *gCurd) generateWebEditFormItem(ctx context.Context, in *CurdPreviewInpu
case FormModeCitySelector:
component = fmt.Sprintf("<n-form-item label=\"%s\" path=\"%s\">\n <CitySelector v-model:value=\"formValue.%s\" />\n </n-form-item>", field.Dc, field.TsName, field.TsName)
case FormModePidTreeSelect:
component = fmt.Sprintf(`<n-form-item label="%v" path="pid">
<n-tree-select
:options="treeOption"
v-model:value="formValue.pid"
key-field="%v"
label-field="%v"
clearable
filterable
default-expand-all
show-path
/>
</n-form-item>`, field.Dc, in.pk.TsName, in.options.Tree.TitleField.TsName)
case FormModeTreeSelect:
component = fmt.Sprintf(`<n-form-item label="%v" path="%v">
<n-tree-select
placeholder="请选择%v"
v-model:value="formValue.%v"
:options="[{ label: 'AA', key: 1, children: [{ label: 'BB', key: 2 }] }]"
clearable
filterable
default-expand-all
/>
</n-form-item>`, field.Dc, field.TsName, field.Dc, field.TsName)
case FormModeCascader:
component = fmt.Sprintf(`<n-form-item label="%v" path="%v">
<n-cascader
placeholder="请选择%v"
v-model:value="formValue.%v"
:options="[{ label: 'AA', value: 1, children: [{ label: 'BB', value: 2 }] }]"
clearable
filterable
/>
</n-form-item>`, field.Dc, field.TsName, field.Dc, field.TsName)
default:
component = defaultComponent
}
if len(in.masterFields) == k {
buffer.WriteString(" " + component)
} else {
buffer.WriteString(" " + component + "\n\n")
}
buffer.WriteString(fmt.Sprintf("<n-gi span=\"%v\">%v</n-gi>\n\n", field.FormGridSpan, component))
}
return buffer.String()
}
@@ -119,23 +152,25 @@ func (l *gCurd) generateWebEditScript(ctx context.Context, in *CurdPreviewInput)
setupBuffer = bytes.NewBuffer(nil)
)
importBuffer.WriteString(" import { ref, computed } from 'vue';\n")
// 导入api
var importApiMethod = []string{"Edit", "View"}
if in.options.Step.HasMaxSort {
importBuffer.WriteString(" import { ref } from 'vue';\n")
if in.Config.Application.Crud.Templates[in.In.GenTemplate].IsAddon {
importBuffer.WriteString(" import { Edit, MaxSort, View } from '@/api/addons/" + in.In.AddonName + "/" + gstr.LcFirst(in.In.VarName) + "';\n")
} else {
importBuffer.WriteString(" import { Edit, MaxSort, View } from '@/api/" + gstr.LcFirst(in.In.VarName) + "';\n")
}
setupBuffer.WriteString(" function openModal(state: State) {\n adaModalWidth(dialogWidth);\n showModal.value = true;\n loading.value = true;\n\n // 新增\n if (!state || state.id < 1) {\n formValue.value = newState(state);\n MaxSort()\n .then((res) => {\n formValue.value.sort = res.sort;\n })\n .finally(() => {\n loading.value = false;\n });\n return;\n }\n\n // 编辑\n View({ id: state.id })\n .then((res) => {\n formValue.value = res;\n })\n .finally(() => {\n loading.value = false;\n });\n }")
} else {
importBuffer.WriteString(" import { ref } from 'vue';\n")
if in.Config.Application.Crud.Templates[in.In.GenTemplate].IsAddon {
importBuffer.WriteString(" import { Edit, View } from '@/api/addons/" + in.In.AddonName + "/" + gstr.LcFirst(in.In.VarName) + "';\n")
} else {
importBuffer.WriteString(" import { Edit, View } from '@/api/" + gstr.LcFirst(in.In.VarName) + "';\n")
}
setupBuffer.WriteString(" function openModal(state: State) {\n adaModalWidth(dialogWidth);\n showModal.value = true;\n loading.value = true;\n\n // 新增\n if (!state || state.id < 1) {\n formValue.value = newState(state);\n return;\n }\n\n // 编辑\n View({ id: state.id })\n .then((res) => {\n formValue.value = res;\n })\n .finally(() => {\n loading.value = false;\n });\n }")
importApiMethod = append(importApiMethod, "MaxSort")
}
importBuffer.WriteString(" import " + ImportWebMethod(importApiMethod) + " from '" + in.options.ImportWebApi + "';\n")
// 导入model
var importModelMethod = []string{"options", "State", "newState"}
if in.options.Step.IsTreeTable {
importModelMethod = append(importModelMethod, []string{"treeOption", "loadTreeOption"}...)
}
if in.options.Step.HasRules {
importModelMethod = append(importModelMethod, "rules")
}
importBuffer.WriteString(" import " + ImportWebMethod(importModelMethod) + " from './model';\n")
for _, field := range in.masterFields {
if !field.IsEdit {

View File

@@ -6,59 +6,135 @@
package views
import (
"bytes"
"context"
"fmt"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
)
const (
IndexApiImport = " import {%v } from '@/api/%s';" // 这里将导入的包路径写死了,后面可以优化成根据配置动态读取
IndexApiAddonsImport = " import {%v } from '@/api/addons/%s/%s';"
IndexIconsImport = " import {%v } from '@vicons/antd';"
)
func (l *gCurd) webIndexTplData(ctx context.Context, in *CurdPreviewInput) (g.Map, error) {
var (
data = make(g.Map)
apiImport = []string{" List"}
iconsImport []string
data = make(g.Map)
importBuffer = bytes.NewBuffer(nil)
importVueMethod = []string{"h", "reactive", "ref", "computed"}
importApiMethod = []string{"List"}
importModelMethod = []string{"columns", "schemas"}
importUtilsMethod = []string{"adaTableScrollX"}
importIcons []string
actionWidth int64 = 72
)
// 添加
if in.options.Step.HasAdd {
iconsImport = append(iconsImport, " PlusOutlined")
importIcons = append(importIcons, "PlusOutlined")
}
// 编辑
// if in.options.Step.HasEdit {
// }
if in.options.Step.HasEdit {
in.options.Step.ActionColumnWidth += actionWidth
if in.options.Step.IsTreeTable && !in.options.Step.IsOptionTreeTable {
in.options.Step.ActionColumnWidth += actionWidth
}
if in.options.Step.IsOptionTreeTable {
importIcons = append(importIcons, "EditOutlined")
}
}
// 导出
if in.options.Step.HasExport {
iconsImport = append(iconsImport, " ExportOutlined")
apiImport = append(apiImport, " Export")
importIcons = append(importIcons, "ExportOutlined")
importApiMethod = append(importApiMethod, "Export")
}
// 删除
if in.options.Step.HasDel || in.options.Step.HasBatchDel {
iconsImport = append(iconsImport, " DeleteOutlined")
apiImport = append(apiImport, " Delete")
if in.options.Step.HasDel {
importApiMethod = append(importApiMethod, "Delete")
in.options.Step.ActionColumnWidth += actionWidth
}
// 导出
// 批量删除
if in.options.Step.HasBatchDel {
importIcons = append(importIcons, "DeleteOutlined")
importApiMethod = append(importApiMethod, "Delete")
}
// 修改状态
if in.options.Step.HasStatus {
apiImport = append(apiImport, " Status")
importApiMethod = append(importApiMethod, "Status")
importUtilsMethod = append(importUtilsMethod, "getOptionLabel")
importModelMethod = append(importModelMethod, "options")
in.options.Step.ActionColumnWidth += actionWidth
}
if in.Config.Application.Crud.Templates[in.In.GenTemplate].IsAddon {
data["apiImport"] = fmt.Sprintf(IndexApiAddonsImport, gstr.Implode(",", apiImport), in.In.AddonName, gstr.LcFirst(in.In.VarName))
} else {
data["apiImport"] = fmt.Sprintf(IndexApiImport, gstr.Implode(",", apiImport), gstr.LcFirst(in.In.VarName))
// 更多
// 查看详情
if in.options.Step.HasView {
in.options.Step.ActionColumnWidth += actionWidth
}
if len(iconsImport) > 0 {
data["iconsImport"] = fmt.Sprintf(IndexIconsImport, gstr.Implode(",", iconsImport))
// 展开树
if in.options.Step.IsTreeTable {
importIcons = append(importIcons, "AlignLeftOutlined")
}
// 存在字典数据选项
if in.options.DictOps.Has {
importVueMethod = append(importVueMethod, "onMounted")
importModelMethod = append(importModelMethod, "loadOptions")
}
// 普通树表
if in.options.Step.IsTreeTable && !in.options.Step.IsOptionTreeTable {
importUtilsMethod = append(importUtilsMethod, "convertListToTree")
}
// 选项式树表
if in.options.Step.IsOptionTreeTable {
importVueMethod = append(importVueMethod, []string{"onMounted", "unref"}...)
importIcons = append(importIcons, []string{"FormOutlined", "SearchOutlined"}...)
importApiMethod = append(importApiMethod, "TreeOption")
importUtilsMethod = append(importUtilsMethod, "getTreeKeys")
importModelMethod = append(importModelMethod, []string{"loadTreeOption", "treeOption", "State"}...)
}
// 操作按钮宽度最小值
if in.options.Step.ActionColumnWidth > 0 && in.options.Step.ActionColumnWidth < actionWidth*2 {
in.options.Step.ActionColumnWidth = 100
}
// 导入基础包
importBuffer.WriteString(" import " + ImportWebMethod(importVueMethod) + " from 'vue';\n")
importBuffer.WriteString(" import { useDialog, useMessage } from 'naive-ui';\n")
importBuffer.WriteString(" import { BasicTable, TableAction } from '@/components/Table';\n")
importBuffer.WriteString(" import { BasicForm, useForm } from '@/components/Form/index';\n")
importBuffer.WriteString(" import { usePermission } from '@/hooks/web/usePermission';\n")
// 导入api
importBuffer.WriteString(" import " + ImportWebMethod(importApiMethod) + " from '" + in.options.ImportWebApi + "';\n")
// 导入icons
if len(importIcons) > 0 {
importBuffer.WriteString(" import " + ImportWebMethod(importIcons) + " from '@vicons/antd';\n")
}
// 导入model
if in.options.Step.IsTreeTable {
importModelMethod = append(importModelMethod, "newState")
}
importBuffer.WriteString(" import " + ImportWebMethod(importModelMethod) + " from './model';\n")
// 导入utils
if len(importUtilsMethod) > 0 {
importBuffer.WriteString(" import " + ImportWebMethod(importUtilsMethod) + " from '@/utils/hotgo';\n")
}
// 导入edit组件
if in.options.Step.HasEdit {
importBuffer.WriteString(" import Edit from './edit.vue';\n")
}
// 导入view组件
if in.options.Step.HasView {
importBuffer.WriteString(" import View from './view.vue';\n")
}
// 没有需要查询的字段则隐藏搜索表单
@@ -83,5 +159,6 @@ func (l *gCurd) webIndexTplData(ctx context.Context, in *CurdPreviewInput) (g.Ma
}
}
data["isSearchForm"] = isSearchForm
data["import"] = importBuffer.String()
return data, nil
}

View File

@@ -12,61 +12,148 @@ import (
"fmt"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/library/dict"
"hotgo/internal/model/input/sysin"
"hotgo/utility/convert"
)
const (
ModelLoadOptionsTemplate = "async function loadOptions() {\n options.value = await Dicts({\n types: [\n %v ],\n });\n for (const item of schemas.value) {\n switch (item.field) {\n%v }\n }\n}\n\nawait loadOptions();"
)
type StateItem struct {
Name string
DefaultValue interface{}
Dc string
}
func (l *gCurd) webModelTplData(ctx context.Context, in *CurdPreviewInput) (data g.Map, err error) {
data = make(g.Map)
data["state"] = l.generateWebModelState(ctx, in)
data["stateItems"] = l.generateWebModelStateItems(ctx, in)
data["rules"] = l.generateWebModelRules(ctx, in)
data["formSchema"] = l.generateWebModelFormSchema(ctx, in)
if data["columns"], err = l.generateWebModelColumns(ctx, in); err != nil {
return nil, err
}
// 根据表单生成情况,按需导包
data["import"] = l.generateWebModelImport(ctx, in)
return
}
func (l *gCurd) generateWebModelState(ctx context.Context, in *CurdPreviewInput) string {
buffer := bytes.NewBuffer(nil)
buffer.WriteString("export class State {\n")
func (l *gCurd) generateWebModelImport(ctx context.Context, in *CurdPreviewInput) string {
importBuffer := bytes.NewBuffer(nil)
importBuffer.WriteString("import { h, ref } from 'vue';\n")
// 导入基础组件
if len(in.options.Step.ImportModel.NaiveUI) > 0 {
importBuffer.WriteString("import " + ImportWebMethod(in.options.Step.ImportModel.NaiveUI) + " from 'naive-ui';\n")
}
importBuffer.WriteString("import { cloneDeep } from 'lodash-es';\n")
// 导入表单搜索
if in.options.Step.HasSearchForm {
importBuffer.WriteString("import { FormSchema } from '@/components/Form';\n")
}
// 导入字典选项
if in.options.DictOps.Has {
importBuffer.WriteString("import { Dicts } from '@/api/dict/dict';\n")
}
// 导入工具类
if len(in.options.Step.ImportModel.UtilsIs) > 0 {
importBuffer.WriteString("import " + ImportWebMethod(in.options.Step.ImportModel.UtilsIs) + " from '@/utils/is';\n")
}
if len(in.options.Step.ImportModel.UtilsUrl) > 0 {
importBuffer.WriteString("import " + ImportWebMethod(in.options.Step.ImportModel.UtilsUrl) + " from '@/utils/urlUtils';\n")
}
if len(in.options.Step.ImportModel.UtilsDate) > 0 {
importBuffer.WriteString("import " + ImportWebMethod(in.options.Step.ImportModel.UtilsDate) + " from '@/utils/dateUtil';\n")
}
if in.options.Step.HasRulesValidator {
importBuffer.WriteString("import { validate } from '@/utils/validateUtil';\n")
}
if len(in.options.Step.ImportModel.UtilsHotGo) > 0 {
importBuffer.WriteString("import " + ImportWebMethod(in.options.Step.ImportModel.UtilsHotGo) + " from '@/utils/hotgo';\n")
}
if len(in.options.Step.ImportModel.UtilsIndex) > 0 {
importBuffer.WriteString("import " + ImportWebMethod(in.options.Step.ImportModel.UtilsIndex) + " from '@/utils';\n")
}
// 导入api
var importApiMethod []string
if in.options.Step.HasSwitch {
importApiMethod = append(importApiMethod, "Switch")
}
if in.options.Step.IsTreeTable {
importApiMethod = append(importApiMethod, "TreeOption")
}
if len(importApiMethod) > 0 {
importBuffer.WriteString("import " + ImportWebMethod(importApiMethod) + " from '" + in.options.ImportWebApi + "';\n")
}
if in.options.Step.HasSwitch {
importBuffer.WriteString("import { usePermission } from '@/hooks/web/usePermission';\n")
importBuffer.WriteString("const { hasPermission } = usePermission();\n")
importBuffer.WriteString("const $message = window['$message'];\n")
}
return importBuffer.String()
}
func (l *gCurd) generateWebModelStateItems(ctx context.Context, in *CurdPreviewInput) (items []*StateItem) {
for _, field := range in.masterFields {
var value = field.DefaultValue
if value == nil {
value = "null"
}
if value == "" {
value = "''"
value = `''`
}
// 选项组件默认值调整
if gconv.Int(value) == 0 && IsSelectFormMode(field.FormMode) {
value = "null"
}
if field.Name == "status" {
value = 1
}
if field.FormMode == "Switch" {
if field.FormMode == FormModeSwitch {
value = 2
}
if field.FormMode == "InputDynamic" {
if field.FormMode == FormModeInputDynamic {
value = "[]"
}
buffer.WriteString(fmt.Sprintf(" public %s = %v; // %s\n", field.TsName, value, field.Dc))
items = append(items, &StateItem{
Name: field.TsName,
DefaultValue: value,
Dc: field.Dc,
})
// 查询用户摘要
if field.IsList && in.options.Step.HasHookMemberSummary && IsMemberSummaryField(field.Name) {
items = append(items, &StateItem{
Name: field.TsName + "Summa?: null | MemberSumma",
DefaultValue: "null",
Dc: field.Dc + "摘要信息",
})
}
}
buffer.WriteString("\n constructor(state?: Partial<State>) {\n if (state) {\n Object.assign(this, state);\n }\n }")
buffer.WriteString("}")
return buffer.String()
return
}
func (l *gCurd) generateWebModelDictOptions(ctx context.Context, in *CurdPreviewInput) (g.Map, error) {
func (l *gCurd) generateWebModelDictOptions(ctx context.Context, in *CurdPreviewInput) error {
type DictType struct {
Id int64 `json:"id"`
Type string `json:"type"`
}
var (
options = make(g.Map)
dictTypeIds []int64
dictTypeList []*DictType
builtinDictTypeIds []int64
@@ -87,8 +174,7 @@ func (l *gCurd) generateWebModelDictOptions(ctx context.Context, in *CurdPreview
builtinDictTypeIds = convert.UniqueSlice(builtinDictTypeIds)
if len(dictTypeIds) == 0 && len(builtinDictTypeIds) == 0 {
options["has"] = false
return options, nil
return nil
}
if len(dictTypeIds) > 0 {
@@ -97,71 +183,52 @@ func (l *gCurd) generateWebModelDictOptions(ctx context.Context, in *CurdPreview
WhereIn("id", dictTypeIds).
Scan(&dictTypeList)
if err != nil {
return nil, err
return err
}
}
if len(builtinDictTypeIds) > 0 {
for _, id := range builtinDictTypeIds {
opts, err := dict.GetOptionsById(ctx, id)
typ, err := dict.GetTypeById(ctx, id)
if err != nil && !errors.Is(err, dict.NotExistKeyError) {
return nil, err
return err
}
if len(opts) > 0 {
if len(typ) > 0 {
row := new(DictType)
row.Id = id
row.Type = opts[0].Type
row.Type = typ
builtinDictTypeList = append(builtinDictTypeList, row)
}
}
}
if len(dictTypeList) == 0 && len(builtinDictTypeList) == 0 {
options["has"] = false
return options, nil
return nil
}
if len(builtinDictTypeList) > 0 {
dictTypeList = append(dictTypeList, builtinDictTypeList...)
}
options["has"] = true
in.options.DictOps.Has = true
var (
awaitLoadOptions string
switchLoadOptions string
)
interfaceOptionsBuffer := bytes.NewBuffer(nil)
interfaceOptionsBuffer.WriteString("export interface IOptions extends Options {\n")
constOptionsBuffer := bytes.NewBuffer(nil)
constOptionsBuffer.WriteString("export const options = ref<IOptions>({\n")
// 导入选项包
in.options.Step.ImportModel.UtilsHotGo = append(in.options.Step.ImportModel.UtilsHotGo, "Option")
for _, v := range dictTypeList {
// 字段映射字典
for _, field := range in.masterFields {
if field.DictType != 0 && v.Id == field.DictType {
in.options.dictMap[field.TsName] = v.Type
switchLoadOptions = fmt.Sprintf("%s case '%s':\n item.componentProps.options = options.value.%s;\n break;\n", switchLoadOptions, field.TsName, v.Type)
in.options.DictOps.Schemas = append(in.options.DictOps.Schemas, &OptionsSchemasField{
Field: field.TsName,
Type: v.Type,
})
}
}
awaitLoadOptions = fmt.Sprintf("%s '%s',\n", awaitLoadOptions, v.Type)
interfaceOptionsBuffer.WriteString(" " + v.Type + ": Option[]; \n")
constOptionsBuffer.WriteString(" " + v.Type + ": [],\n")
in.options.DictOps.Types = append(in.options.DictOps.Types, v.Type)
}
interfaceOptionsBuffer.WriteString("};\n")
constOptionsBuffer.WriteString("});\n")
loadOptionsBuffer := bytes.NewBuffer(nil)
loadOptionsBuffer.WriteString(fmt.Sprintf(ModelLoadOptionsTemplate, awaitLoadOptions, switchLoadOptions))
options["interface"] = interfaceOptionsBuffer.String()
options["const"] = constOptionsBuffer.String()
options["load"] = loadOptionsBuffer.String()
return options, nil
return nil
}
func (l *gCurd) generateWebModelRules(ctx context.Context, in *CurdPreviewInput) string {
@@ -172,9 +239,11 @@ func (l *gCurd) generateWebModelRules(ctx context.Context, in *CurdPreviewInput)
continue
}
in.options.Step.HasRules = true
if field.FormRole == "" || field.FormRole == FormRoleNone || field.FormRole == "required" {
buffer.WriteString(fmt.Sprintf(" %s: {\n required: %v,\n trigger: ['blur', 'input'],\n type: '%s',\n message: '请输入%s',\n },\n", field.TsName, field.Required, field.TsType, field.Dc))
} else {
in.options.Step.HasRulesValidator = true
buffer.WriteString(fmt.Sprintf(" %s: {\n required: %v,\n trigger: ['blur', 'input'],\n type: '%s',\n validator: validate.%v,\n },\n", field.TsName, field.Required, field.TsType, field.FormRole))
}
}
@@ -187,7 +256,7 @@ func (l *gCurd) generateWebModelFormSchema(ctx context.Context, in *CurdPreviewI
buffer.WriteString("export const schemas = ref<FormSchema[]>([\n")
// 主表
l.generateWebModelFormSchemaEach(buffer, in.masterFields)
l.generateWebModelFormSchemaEach(buffer, in.masterFields, in)
// 关联表
if len(in.options.Join) > 0 {
@@ -195,7 +264,7 @@ func (l *gCurd) generateWebModelFormSchema(ctx context.Context, in *CurdPreviewI
if !isEffectiveJoin(v) {
continue
}
l.generateWebModelFormSchemaEach(buffer, v.Columns)
l.generateWebModelFormSchemaEach(buffer, v.Columns, in)
}
}
@@ -203,11 +272,18 @@ func (l *gCurd) generateWebModelFormSchema(ctx context.Context, in *CurdPreviewI
return buffer.String()
}
func (l *gCurd) generateWebModelFormSchemaEach(buffer *bytes.Buffer, fields []*sysin.GenCodesColumnListModel) {
func (l *gCurd) generateWebModelFormSchemaEach(buffer *bytes.Buffer, fields []*sysin.GenCodesColumnListModel, in *CurdPreviewInput) {
for _, field := range fields {
if !field.IsQuery {
continue
}
in.options.Step.HasSearchForm = true
// 查询用户摘要
if field.IsQuery && in.options.Step.HasQueryMemberSummary && IsMemberSummaryField(field.Name) {
buffer.WriteString(fmt.Sprintf(" {\n field: '%s',\n component: '%s',\n label: '%s',\n componentProps: {\n placeholder: '请输入ID|用户名|姓名|手机号',\n onUpdateValue: (e: any) => {\n console.log(e);\n },\n },\n },\n", field.TsName, "NInput", field.Dc))
continue
}
var (
defaultComponent = fmt.Sprintf(" {\n field: '%s',\n component: '%s',\n label: '%s',\n componentProps: {\n placeholder: '请输入%s',\n onUpdateValue: (e: any) => {\n console.log(e);\n },\n },\n },\n", field.TsName, "NInput", field.Dc, field.Dc)
@@ -224,15 +300,19 @@ func (l *gCurd) generateWebModelFormSchemaEach(buffer *bytes.Buffer, fields []*s
case FormModeDate:
component = fmt.Sprintf(" {\n field: '%s',\n component: '%s',\n label: '%s',\n componentProps: {\n type: '%s',\n clearable: true,\n shortcuts: %s,\n onUpdateValue: (e: any) => {\n console.log(e);\n },\n },\n },\n", field.TsName, "NDatePicker", field.Dc, "date", "defShortcuts()")
in.options.Step.ImportModel.UtilsDate = append(in.options.Step.ImportModel.UtilsDate, "defShortcuts")
case FormModeDateRange:
component = fmt.Sprintf(" {\n field: '%s',\n component: '%s',\n label: '%s',\n componentProps: {\n type: '%s',\n clearable: true,\n shortcuts: %s,\n onUpdateValue: (e: any) => {\n console.log(e);\n },\n },\n },\n", field.TsName, "NDatePicker", field.Dc, "daterange", "defRangeShortcuts()")
in.options.Step.ImportModel.UtilsDate = append(in.options.Step.ImportModel.UtilsDate, "defRangeShortcuts")
case FormModeTime:
component = fmt.Sprintf(" {\n field: '%s',\n component: '%s',\n label: '%s',\n componentProps: {\n type: '%s',\n clearable: true,\n shortcuts: %s,\n onUpdateValue: (e: any) => {\n console.log(e);\n },\n },\n },\n", field.TsName, "NDatePicker", field.Dc, "datetime", "defShortcuts()")
in.options.Step.ImportModel.UtilsDate = append(in.options.Step.ImportModel.UtilsDate, "defShortcuts")
case FormModeTimeRange:
component = fmt.Sprintf(" {\n field: '%s',\n component: '%s',\n label: '%s',\n componentProps: {\n type: '%s',\n clearable: true,\n shortcuts: %s,\n onUpdateValue: (e: any) => {\n console.log(e);\n },\n },\n },\n", field.TsName, "NDatePicker", field.Dc, "datetimerange", "defRangeShortcuts()")
in.options.Step.ImportModel.UtilsDate = append(in.options.Step.ImportModel.UtilsDate, "defRangeShortcuts")
case FormModeSwitch:
fallthrough
@@ -287,14 +367,22 @@ func (l *gCurd) generateWebModelColumnsEach(buffer *bytes.Buffer, in *CurdPrevie
continue
}
var (
defaultComponent = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n },\n", field.Dc, field.TsName)
defaultComponent = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n },\n", field.Dc, field.TsName, field.Align, field.Width)
component string
)
// 查询用户摘要
if in.options.Step.HasHookMemberSummary && IsMemberSummaryField(field.Name) {
buffer.WriteString(fmt.Sprintf(" {\n title: '%v',\n key: '%v',\n align: '%v',\n width: %v,\n render(row) {\n return renderPopoverMemberSumma(row.%vSumma);\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, field.TsName))
in.options.Step.ImportModel.UtilsIndex = append(in.options.Step.ImportModel.UtilsIndex, []string{"renderPopoverMemberSumma", "MemberSumma"}...)
continue
}
// 这里根据编辑表单组件来进行推断如果没有则使用默认input这可能会导致和查询条件所需参数不符的情况
switch field.FormMode {
case FormModeDate:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n return formatToDate(row.%s);\n },\n },\n", field.Dc, field.TsName, field.TsName)
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n return formatToDate(row.%s);\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, field.TsName)
in.options.Step.ImportModel.UtilsDate = append(in.options.Step.ImportModel.UtilsDate, "formatToDate")
case FormModeRadio:
fallthrough
@@ -303,32 +391,50 @@ func (l *gCurd) generateWebModelColumnsEach(buffer *bytes.Buffer, in *CurdPrevie
err = gerror.Newf("设置单选下拉框选项时,必须选择字典类型,字段名称:%v", field.Name)
return
}
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return h(\n NTag,\n {\n style: {\n marginRight: '6px',\n },\n type: getOptionTag(options.value.%s, row.%s),\n bordered: false,\n },\n {\n default: () => getOptionLabel(options.value.%s, row.%s),\n }\n );\n },\n },\n", field.Dc, field.TsName, field.TsName, in.options.dictMap[field.TsName], field.TsName, in.options.dictMap[field.TsName], field.TsName)
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return h(\n NTag,\n {\n style: {\n marginRight: '6px',\n },\n type: getOptionTag(options.value.%s, row.%s),\n bordered: false,\n },\n {\n default: () => getOptionLabel(options.value.%s, row.%s),\n }\n );\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, field.TsName, in.options.dictMap[field.TsName], field.TsName, in.options.dictMap[field.TsName], field.TsName)
in.options.Step.ImportModel.NaiveUI = append(in.options.Step.ImportModel.NaiveUI, "NTag")
in.options.Step.ImportModel.UtilsIs = append(in.options.Step.ImportModel.UtilsIs, "isNullObject")
in.options.Step.ImportModel.UtilsHotGo = append(in.options.Step.ImportModel.UtilsHotGo, []string{"getOptionLabel", "getOptionTag"}...)
case FormModeSelectMultiple:
if g.IsEmpty(in.options.dictMap[field.TsName]) {
err = gerror.Newf("设置多选下拉框选项时,必须选择字典类型,字段名称:%v", field.Name)
return
}
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s) || !isArray(row.%s)) {\n return ``;\n }\n return row.%s.map((tagKey) => {\n return h(\n NTag,\n {\n style: {\n marginRight: '6px',\n },\n type: getOptionTag(options.value.%s, tagKey),\n bordered: false,\n },\n {\n default: () => getOptionLabel(options.value.%s, tagKey),\n }\n );\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n if (isNullObject(row.%s) || !isArray(row.%s)) {\n return ``;\n }\n return row.%s.map((tagKey) => {\n return h(\n NTag,\n {\n style: {\n marginRight: '6px',\n },\n type: getOptionTag(options.value.%s, tagKey),\n bordered: false,\n },\n {\n default: () => getOptionLabel(options.value.%s, tagKey),\n }\n );\n });\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, field.TsName, field.TsName, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
in.options.Step.ImportModel.NaiveUI = append(in.options.Step.ImportModel.NaiveUI, "NTag")
in.options.Step.ImportModel.UtilsIs = append(in.options.Step.ImportModel.UtilsIs, "isNullObject")
in.options.Step.ImportModel.UtilsHotGo = append(in.options.Step.ImportModel.UtilsHotGo, []string{"getOptionLabel", "getOptionTag"}...)
case FormModeUploadImage:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n return h(%s, {\n width: 32,\n height: 32,\n src: row.%s,\n onError: errorImg,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n },\n });\n },\n },\n", field.Dc, field.TsName, "NImage", field.TsName)
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n return h(%s, {\n width: 32,\n height: 32,\n src: row.%s,\n fallbackSrc: errorImg,\n onError: errorImg,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n },\n });\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, "NImage", field.TsName)
in.options.Step.ImportModel.NaiveUI = append(in.options.Step.ImportModel.NaiveUI, "NImage")
in.options.Step.ImportModel.UtilsHotGo = append(in.options.Step.ImportModel.UtilsHotGo, "errorImg")
case FormModeUploadImages:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return row.%s.map((image) => {\n return h(%s, {\n width: 32,\n height: 32,\n src: image,\n onError: errorImg,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n 'margin-left': '2px',\n },\n });\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, "NImage")
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return row.%s.map((image) => {\n return h(%s, {\n width: 32,\n height: 32,\n src: image,\n onError: errorImg,\n style: {\n width: '32px',\n height: '32px',\n 'max-width': '100%%',\n 'max-height': '100%%',\n 'margin-left': '2px',\n },\n });\n });\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, field.TsName, field.TsName, "NImage")
in.options.Step.ImportModel.NaiveUI = append(in.options.Step.ImportModel.NaiveUI, "NImage")
in.options.Step.ImportModel.UtilsIs = append(in.options.Step.ImportModel.UtilsIs, "isArray")
in.options.Step.ImportModel.UtilsHotGo = append(in.options.Step.ImportModel.UtilsHotGo, "errorImg")
case FormModeUploadFile:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (row.%s === '') {\n return ``;\n }\n return h(\n %s,\n {\n size: 'small',\n },\n {\n default: () => getFileExt(row.%s),\n }\n );\n },\n },\n", field.Dc, field.TsName, field.TsName, "NAvatar", field.TsName)
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n if (row.%s === '') {\n return ``;\n }\n return h(\n %s,\n {\n size: 'small',\n },\n {\n default: () => getFileExt(row.%s),\n }\n );\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, field.TsName, "NAvatar", field.TsName)
in.options.Step.ImportModel.NaiveUI = append(in.options.Step.ImportModel.NaiveUI, "NAvatar")
in.options.Step.ImportModel.UtilsUrl = append(in.options.Step.ImportModel.UtilsUrl, "getFileExt")
case FormModeUploadFiles:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return row.%s.map((attachfile) => {\n return h(\n %s,\n {\n size: 'small',\n style: {\n 'margin-left': '2px',\n },\n },\n {\n default: () => getFileExt(attachfile),\n }\n );\n });\n },\n },\n", field.Dc, field.TsName, field.TsName, field.TsName, "NAvatar")
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n if (isNullObject(row.%s)) {\n return ``;\n }\n return row.%s.map((attachfile) => {\n return h(\n %s,\n {\n size: 'small',\n style: {\n 'margin-left': '2px',\n },\n },\n {\n default: () => getFileExt(attachfile),\n }\n );\n });\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, field.TsName, field.TsName, "NAvatar")
in.options.Step.ImportModel.NaiveUI = append(in.options.Step.ImportModel.NaiveUI, "NAvatar")
in.options.Step.ImportModel.UtilsIs = append(in.options.Step.ImportModel.UtilsIs, "isNullObject")
in.options.Step.ImportModel.UtilsUrl = append(in.options.Step.ImportModel.UtilsUrl, "getFileExt")
case FormModeSwitch:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n width: 100,\n render(row) {\n return h(%s, {\n value: row.%s === 1,\n checked: '开启',\n unchecked: '关闭',\n disabled: !hasPermission(['%s']),\n onUpdateValue: function (e) {\n console.log('onUpdateValue e:' + JSON.stringify(e));\n row.%s = e ? 1 : 2;\n Switch({ %s: row.%s, key: '%s', value: row.%s }).then((_res) => {\n $message.success('操作成功');\n });\n },\n });\n },\n },\n", field.Dc, field.TsName, "NSwitch", field.TsName, "/"+in.options.ApiPrefix+"/switch", field.TsName, in.pk.TsName, in.pk.TsName, convert.CamelCaseToUnderline(field.TsName), field.TsName)
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n return h(%s, {\n value: row.%s === 1,\n checked: '开启',\n unchecked: '关闭',\n disabled: !hasPermission(['%s']),\n onUpdateValue: function (e) {\n console.log('onUpdateValue e:' + JSON.stringify(e));\n row.%s = e ? 1 : 2;\n Switch({ %s: row.%s, key: '%s', value: row.%s }).then((_res) => {\n $message.success('操作成功');\n });\n },\n });\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, "NSwitch", field.TsName, "/"+in.options.ApiPrefix+"/switch", field.TsName, in.pk.TsName, in.pk.TsName, convert.CamelCaseToUnderline(field.TsName), field.TsName)
in.options.Step.ImportModel.NaiveUI = append(in.options.Step.ImportModel.NaiveUI, "NSwitch")
case FormModeRate:
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n render(row) {\n return h(%s, {\n allowHalf: true,\n readonly: true,\n defaultValue: row.%s,\n });\n },\n },\n", field.Dc, field.TsName, "NRate", field.TsName)
component = fmt.Sprintf(" {\n title: '%s',\n key: '%s',\n align: '%v',\n width: %v,\n render(row) {\n return h(%s, {\n allowHalf: true,\n readonly: true,\n defaultValue: row.%s,\n });\n },\n },\n", field.Dc, field.TsName, field.Align, field.Width, "NRate", field.TsName)
in.options.Step.ImportModel.NaiveUI = append(in.options.Step.ImportModel.NaiveUI, "NRate")
default:
component = defaultComponent
@@ -336,6 +442,5 @@ func (l *gCurd) generateWebModelColumnsEach(buffer *bytes.Buffer, in *CurdPrevie
buffer.WriteString(component)
}
return
}

View File

@@ -44,25 +44,25 @@ func (l *gCurd) generateWebViewItem(ctx context.Context, in *CurdPreviewInput) s
component = defaultComponent
case FormModeRadio, FormModeSelect:
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-tag\n :type=\"getOptionTag(options.%s, formValue?.%s)\"\n size=\"small\"\n class=\"min-left-space\"\n >{{ getOptionLabel(options.%s, formValue?.%s) }}</n-tag\n >\n </n-descriptions-item>", field.Dc, in.options.dictMap[field.TsName], field.TsName, in.options.dictMap[field.TsName], field.TsName)
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-tag :type=\"getOptionTag(options.%s, formValue?.%s)\" size=\"small\" class=\"min-left-space\">{{ getOptionLabel(options.%s, formValue?.%s) }}</n-tag>\n </n-descriptions-item>", field.Dc, in.options.dictMap[field.TsName], field.TsName, in.options.dictMap[field.TsName], field.TsName)
case FormModeCheckbox, FormModeSelectMultiple:
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <template v-for=\"(item, key) in formValue?.%s\" :key=\"key\">\n <n-tag\n :type=\"getOptionTag(options.%s, item)\"\n size=\"small\"\n class=\"min-left-space\"\n >{{ getOptionLabel(options.%s, item) }}</n-tag\n >\n </template>\n </n-descriptions-item>", field.Dc, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <template v-for=\"(item, key) in formValue?.%s\" :key=\"key\">\n <n-tag :type=\"getOptionTag(options.%s, item)\" size=\"small\" class=\"min-left-space\">{{ getOptionLabel(options.%s, item) }}</n-tag>\n </template>\n </n-descriptions-item>", field.Dc, field.TsName, in.options.dictMap[field.TsName], in.options.dictMap[field.TsName])
case FormModeUploadImage:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"formValue.%s\"\n /></n-descriptions-item>", field.Dc, field.TsName)
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"formValue.%s\"/></n-descriptions-item>", field.Dc, field.TsName)
case FormModeUploadImages:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <n-image-group>\n <n-space>\n <span v-for=\"(item, key) in formValue?.%s\" :key=\"key\">\n <n-image style=\"margin-left: 10px; height: 100px; width: 100px\" :src=\"item\" />\n </span>\n </n-space>\n </n-image-group>\n </n-descriptions-item>", field.Dc, field.TsName)
case FormModeUploadFile:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <div\n class=\"upload-card\"\n v-show=\"formValue.%s !== ''\"\n @click=\"download(formValue.%s)\"\n >\n <div class=\"upload-card-item\" style=\"height: 100px; width: 100px\">\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\">{{ getFileExt(formValue.%s) }}</n-avatar>\n </div>\n </div>\n </div>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName, field.TsName, field.TsName)
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <div class=\"upload-card\" v-show=\"formValue.%s !== ''\" @click=\"download(formValue.%s)\">\n <div class=\"upload-card-item\" style=\"height: 100px; width: 100px\">\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\">{{ getFileExt(formValue.%s) }}</n-avatar>\n </div>\n </div>\n </div>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName, field.TsName, field.TsName)
case FormModeUploadFiles:
component = fmt.Sprintf("<n-descriptions-item>\n <template #label>%s</template>\n <div class=\"upload-card\">\n <n-space style=\"gap: 0px 0px\">\n <div\n class=\"upload-card-item\"\n style=\"height: 100px; width: 100px\"\n v-for=\"(item, key) in formValue.%s\"\n :key=\"key\"\n >\n <div class=\"upload-card-item-info\">\n <div class=\"img-box\">\n <n-avatar :style=\"fileAvatarCSS\" @click=\"download(item)\">{{\n getFileExt(item)\n }}</n-avatar>\n </div>\n </div>\n </div>\n </n-space>\n </div>\n </n-descriptions-item>", field.Dc, field.TsName)
case FormModeSwitch:
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-switch v-model:value=\"formValue.%s\" :unchecked-value=\"2\" :checked-value=\"1\" :disabled=\"true\"\n /></n-descriptions-item>", field.Dc, field.TsName)
component = fmt.Sprintf("<n-descriptions-item label=\"%s\">\n <n-switch v-model:value=\"formValue.%s\" :unchecked-value=\"2\" :checked-value=\"1\" :disabled=\"true\"/></n-descriptions-item>", field.Dc, field.TsName)
case FormModeRate:
component = fmt.Sprintf("<n-descriptions-item label=\"%s\"\n ><n-rate readonly :default-value=\"formValue.%s\"\n /></n-descriptions-item>", field.Dc, field.TsName)

View File

@@ -0,0 +1,7 @@
package gohtml
const (
defaultIndentString = " "
startIndent = 0
defaultLastElement = "</html>"
)

View File

@@ -0,0 +1,2 @@
// Package gohtml provides an HTML formatting function.
package gohtml

View File

@@ -0,0 +1,7 @@
package gohtml
// An element represents an HTML element.
type element interface {
isInline() bool
write(*formattedBuffer, bool) bool
}

View File

@@ -0,0 +1,37 @@
package gohtml
import (
"bytes"
"strconv"
"strings"
)
// Format parses the input HTML string, formats it and returns the result.
func Format(s string) string {
return parse(strings.NewReader(s)).html()
}
// FormatBytes parses input HTML as bytes, formats it and returns the result.
func FormatBytes(b []byte) []byte {
return parse(bytes.NewReader(b)).bytes()
}
// Format parses the input HTML string, formats it and returns the result with line no.
func FormatWithLineNo(s string) string {
return AddLineNo(Format(s))
}
func AddLineNo(s string) string {
lines := strings.Split(s, "\n")
maxLineNoStrLen := len(strconv.Itoa(len(lines)))
bf := &bytes.Buffer{}
for i, line := range lines {
lineNoStr := strconv.Itoa(i + 1)
if i > 0 {
bf.WriteString("\n")
}
bf.WriteString(strings.Repeat(" ", maxLineNoStrLen-len(lineNoStr)) + lineNoStr + " " + line)
}
return bf.String()
}

View File

@@ -0,0 +1,54 @@
package gohtml
import (
"bytes"
"regexp"
)
// Column to wrap lines to (disabled by default)
var LineWrapColumn = 0
// Maxmimum characters a long word can extend past LineWrapColumn without wrapping
var LineWrapMaxSpillover = 5
// An htmlDocument represents an HTML document.
type htmlDocument struct {
elements []element
}
// html generates an HTML source code and returns it.
func (htmlDoc *htmlDocument) html() string {
str := string(htmlDoc.bytes())
str = replaceMultipleNewlinesWithSpaceAndTabs(str)
return str
}
func replaceMultipleNewlinesWithSpaceAndTabs(input string) string {
re := regexp.MustCompile(`\n\s*\n+`)
formattedString := re.ReplaceAllString(input, "\n")
return formattedString
}
// bytes reads from htmlDocument's internal array of elements and returns HTML source code
func (htmlDoc *htmlDocument) bytes() []byte {
bf := &formattedBuffer{
buffer: &bytes.Buffer{},
lineWrapColumn: LineWrapColumn,
lineWrapMaxSpillover: LineWrapMaxSpillover,
indentString: defaultIndentString,
indentLevel: startIndent,
}
isPreviousNodeInline := true
for _, child := range htmlDoc.elements {
isPreviousNodeInline = child.write(bf, isPreviousNodeInline)
}
return bf.buffer.Bytes()
}
// append appends an element to the htmlDocument.
func (htmlDoc *htmlDocument) append(e element) {
htmlDoc.elements = append(htmlDoc.elements, e)
}

View File

@@ -0,0 +1,127 @@
package gohtml
import (
"golang.org/x/net/html"
"io"
"regexp"
"strings"
)
// parse parses a stirng and converts it into an html.
func parse(r io.Reader) *htmlDocument {
htmlDoc := &htmlDocument{}
tokenizer := html.NewTokenizer(r)
for {
if errorToken, _, _ := parseToken(tokenizer, htmlDoc, nil); errorToken {
break
}
}
return htmlDoc
}
// Function that identifies which tags will be treated as containing preformatted
// content. Such tags will have the formatting of all its contents preserved
// unchanged.
// The opening tag html.Token is passed to this function.
// By default, only <pre> and <textarea> tags are considered preformatted.
var IsPreformatted = func(token html.Token) bool {
return token.Data == "pre" || token.Data == "textarea"
}
func parseToken(tokenizer *html.Tokenizer, htmlDoc *htmlDocument, parent *tagElement) (bool, bool, string) {
tokenType := tokenizer.Next()
raw := string(tokenizer.Raw())
switch tokenType {
case html.ErrorToken:
return true, false, ""
case html.TextToken:
text := string(tokenizer.Raw())
if strings.TrimSpace(text) == "" && (parent == nil || !parent.isRaw) {
break
}
textElement := &textElement{text: text, parent: parent}
appendElement(htmlDoc, parent, textElement)
case html.StartTagToken:
raw := string(tokenizer.Raw())
token := tokenizer.Token()
tagElement := &tagElement{
tagName: string(token.Data),
startTagRaw: raw,
isRaw: IsPreformatted(token) || (parent != nil && parent.isRaw),
parent: parent,
}
appendElement(htmlDoc, parent, tagElement)
for {
errorToken, parentEnded, unsetEndTag := parseToken(tokenizer, htmlDoc, tagElement)
if errorToken {
return true, false, ""
}
if parentEnded {
if unsetEndTag != "" {
return false, false, unsetEndTag
}
break
}
if unsetEndTag != "" {
tagName := setEndTagRaw(tokenizer, tagElement, unsetEndTag)
return false, false, tagName
}
}
case html.EndTagToken:
tagName := setEndTagRaw(tokenizer, parent, getTagName(tokenizer))
return false, true, tagName
case html.DoctypeToken, html.CommentToken:
tagElement := &tagElement{
tagName: getTagName(tokenizer),
startTagRaw: string(tokenizer.Raw()),
isRaw: parent != nil && parent.isRaw,
parent: parent,
}
appendElement(htmlDoc, parent, tagElement)
case html.SelfClosingTagToken:
tagElement := &tagElement{
tagName: getTagName(tokenizer),
startTagRaw: raw,
isRaw: parent != nil && parent.isRaw,
parent: parent,
}
appendElement(htmlDoc, parent, tagElement)
}
return false, false, ""
}
// appendElement appends the element to the htmlDocument or parent tagElement.
func appendElement(htmlDoc *htmlDocument, parent *tagElement, e element) {
if parent != nil {
parent.appendChild(e)
} else {
htmlDoc.append(e)
}
}
// getTagName gets a tagName from tokenizer.
func getTagName(tokenizer *html.Tokenizer) string {
tagName, _ := tokenizer.TagName()
return string(tagName)
}
// setEndTagRaw sets an endTagRaw to the parent.
func setEndTagRaw(tokenizer *html.Tokenizer, parent *tagElement, tagName string) string {
if parent != nil && parent.tagName == tagName {
parent.endTagRaw = `</` + fMustCompile(parent.startTagRaw) + `>` //string(tokenizer.Raw())
return ""
}
return tagName
}
func fMustCompile(input string) (result string) {
re := regexp.MustCompile(`<([A-Za-z-]+)[\s\S]*?>`)
match := re.FindStringSubmatch(input)
if len(match) > 1 {
result = match[1]
} else {
result = input
}
return
}

View File

@@ -0,0 +1,145 @@
package gohtml
import (
"bytes"
)
// A tagElement represents a tag element of an HTML document.
type tagElement struct {
tagName string
startTagRaw string
endTagRaw string
parent *tagElement
children []element
isRaw bool
isChildrenInlineCache *bool
}
// Enable condensing a tag with only inline children onto a single line, or
// completely inlining it with sibling nodes.
// Tags to be treated as inline can be set in `InlineTags`.
// Only inline tags will be completely inlined, while other condensable tags
// will be given their own dedicated (single) line.
var Condense bool
// Tags that are considered inline tags.
// Note: Text nodes are always considered to be inline
var InlineTags = map[string]bool{
"a": true,
"code": true,
"em": true,
"span": true,
"strong": true,
}
// Maximum length of an opening inline tag before it's un-inlined
var InlineTagMaxLength = 40
func (e *tagElement) isInline() bool {
if e.isRaw || !InlineTags[e.tagName] || len(e.startTagRaw) > InlineTagMaxLength {
return false
}
return e.isChildrenInline()
}
func (e *tagElement) isChildrenInline() bool {
if !Condense {
return false
}
if e.isChildrenInlineCache != nil {
return *e.isChildrenInlineCache
}
isInline := true
for _, child := range e.children {
isInline = isInline && child.isInline()
}
e.isChildrenInlineCache = &isInline
return isInline
}
// write writes a tag to the buffer.
func (e *tagElement) write(bf *formattedBuffer, isPreviousNodeInline bool) bool {
if e.isRaw {
if e.parent != nil && !e.parent.isRaw {
bf.writeLineFeed()
bf.writeIndent()
bf.rawMode = true
defer func() {
bf.rawMode = false
}()
}
bf.writeToken(e.startTagRaw, formatterTokenType_Tag)
for _, child := range e.children {
child.write(bf, true)
}
bf.writeToken(e.endTagRaw, formatterTokenType_Tag)
return false
}
if e.isChildrenInline() && (e.endTagRaw != "" || e.isInline()) {
// Write the condensed output to a separate buffer, in case it doesn't work out
condensedBuffer := *bf
condensedBuffer.buffer = &bytes.Buffer{}
if bf.buffer.Len() > 0 && (!isPreviousNodeInline || !e.isInline()) {
condensedBuffer.writeLineFeed()
}
condensedBuffer.writeToken(e.startTagRaw, formatterTokenType_Tag)
if !isPreviousNodeInline && e.endTagRaw != "" {
condensedBuffer.indentLevel++
}
for _, child := range e.children {
child.write(&condensedBuffer, true)
}
if e.endTagRaw != "" {
condensedBuffer.writeToken(e.endTagRaw, formatterTokenType_Tag)
if !isPreviousNodeInline {
condensedBuffer.indentLevel--
}
}
if e.isInline() || bytes.IndexAny(condensedBuffer.buffer.Bytes()[1:], "\n") == -1 {
// If we're an inline tag, or there were no newlines were in the buffer,
// replace the original with the condensed version
condensedBuffer.buffer = bytes.NewBuffer(bytes.Join([][]byte{
bf.buffer.Bytes(), condensedBuffer.buffer.Bytes(),
}, []byte{}))
*bf = condensedBuffer
return e.isInline()
}
}
if bf.buffer.Len() > 0 {
bf.writeLineFeed()
}
bf.writeToken(e.startTagRaw, formatterTokenType_Tag)
if e.endTagRaw != "" {
bf.indentLevel++
}
isPreviousNodeInline = false
for _, child := range e.children {
isPreviousNodeInline = child.write(bf, isPreviousNodeInline)
}
if e.endTagRaw != "" {
if len(e.children) > 0 {
bf.writeLineFeed()
}
bf.indentLevel--
bf.writeToken(e.endTagRaw, formatterTokenType_Tag)
}
return false
}
// appendChild append an element to the element's children.
func (e *tagElement) appendChild(child element) {
e.children = append(e.children, child)
}

View File

@@ -0,0 +1,43 @@
package gohtml
import (
"regexp"
"strings"
)
// A textElement represents a text element of an HTML document.
type textElement struct {
text string
parent *tagElement
}
func (e *textElement) isInline() bool {
// Text nodes are always considered to be inline
return true
}
// write writes a text to the buffer.
func (e *textElement) write(bf *formattedBuffer, isPreviousNodeInline bool) bool {
text := unifyLineFeed(e.text)
if e.parent != nil && e.parent.isRaw {
bf.writeToken(text, formatterTokenType_Text)
return true
}
if !isPreviousNodeInline {
bf.writeLineFeed()
}
// Collapse leading and trailing spaces
text = regexp.MustCompile(`^\s+|\s+$`).ReplaceAllString(text, " ")
lines := strings.Split(text, "\n")
for l, line := range lines {
if l > 0 {
bf.writeLineFeed()
}
for _, word := range strings.Split(line, " ") {
bf.writeToken(word, formatterTokenType_Text)
}
}
return true
}

View File

@@ -0,0 +1,101 @@
package gohtml
import (
"bytes"
"strings"
"unicode"
)
type formatterTokenType int
const (
formatterTokenType_Nothing formatterTokenType = iota
formatterTokenType_Tag
formatterTokenType_Text
)
type formattedBuffer struct {
buffer *bytes.Buffer
rawMode bool
indentString string
indentLevel int
lineWrapColumn int
lineWrapMaxSpillover int
curLineLength int
prevTokenType formatterTokenType
}
func (bf *formattedBuffer) writeLineFeed() {
if !bf.rawMode {
// Strip trailing newlines
bf.buffer = bytes.NewBuffer(bytes.TrimRightFunc(
bf.buffer.Bytes(),
func(r rune) bool {
return r != '\n' && unicode.IsSpace(r)
},
))
}
bf.buffer.WriteString("\n")
bf.curLineLength = 0
bf.prevTokenType = formatterTokenType_Nothing
}
func (bf *formattedBuffer) writeIndent() {
bf.buffer.WriteString(strings.Repeat(bf.indentString, bf.indentLevel))
bf.curLineLength += len(bf.indentString) * bf.indentLevel
}
func (bf *formattedBuffer) writeToken(token string, kind formatterTokenType) {
if bf.rawMode {
bf.buffer.WriteString(token)
bf.curLineLength += len(token)
return
}
if bf.prevTokenType == formatterTokenType_Nothing && strings.TrimSpace(token) == "" {
// It's a whitespace token, but we already have indentation which functions
// the same, so we ignore it
return
}
toWrite := token
if kind == formatterTokenType_Text && bf.prevTokenType == formatterTokenType_Text {
toWrite = " " + token
}
if bf.prevTokenType != formatterTokenType_Nothing && bf.lineWrapColumn > 0 {
switch {
case bf.curLineLength > bf.lineWrapColumn:
// Current line is too long
fallthrough
case bf.curLineLength+len(toWrite) > bf.lineWrapColumn+bf.lineWrapMaxSpillover:
// Current line + new token is too long even with allowed spillover
fallthrough
case bf.curLineLength+len(toWrite) > bf.lineWrapColumn &&
bf.curLineLength > bf.lineWrapColumn-bf.lineWrapMaxSpillover:
// Current line + new token is too long and doesn't quality for spillover
bf.writeLineFeed()
bf.writeToken(token, kind)
return
}
}
if bf.curLineLength == 0 {
bf.writeIndent()
}
bf.buffer.WriteString(toWrite)
bf.curLineLength += len(toWrite)
bf.prevTokenType = kind
}
// unifyLineFeed unifies line feeds.
func unifyLineFeed(s string) string {
return strings.Replace(strings.Replace(s, "\r\n", "\n", -1), "\r", "\n", -1)
}

View File

@@ -0,0 +1,33 @@
package gohtml
import (
"bytes"
"io"
)
// A Writer represents a formatted HTML source codes writer.
type Writer struct {
writer io.Writer
lastElement string
bf *bytes.Buffer
}
// SetLastElement set the lastElement to the Writer.
func (wr *Writer) SetLastElement(lastElement string) *Writer {
wr.lastElement = lastElement
return wr
}
// Write writes the parameter.
func (wr *Writer) Write(p []byte) (n int, err error) {
n, _ = wr.bf.Write(p) // (*bytes.Buffer).Write never produces an error
if bytes.HasSuffix(p, []byte(wr.lastElement)) {
_, err = wr.writer.Write([]byte(Format(wr.bf.String()) + "\n"))
}
return n, err
}
// NewWriter generates a Writer and returns it.
func NewWriter(wr io.Writer) *Writer {
return &Writer{writer: wr, lastElement: defaultLastElement, bf: &bytes.Buffer{}}
}

View File

@@ -7,6 +7,7 @@ package views
import (
"context"
"fmt"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
@@ -14,11 +15,18 @@ import (
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"golang.org/x/tools/imports"
"hotgo/internal/consts"
"hotgo/internal/library/hggen/views/gohtml"
"hotgo/internal/model"
"hotgo/internal/model/input/sysin"
"hotgo/utility/convert"
"hotgo/utility/simple"
"hotgo/utility/validate"
"os"
"regexp"
"strings"
"unicode"
)
// parseServFunName 解析业务服务名称
@@ -30,19 +38,6 @@ func (l *gCurd) parseServFunName(templateGroup, varName string) string {
return templateGroup + varName
}
// getPkField 获取主键
func (l *gCurd) getPkField(in *CurdPreviewInput) *sysin.GenCodesColumnListModel {
if len(in.masterFields) == 0 {
panic("getPkField masterFields uninitialized.")
}
for _, field := range in.masterFields {
if IsIndexPK(field.Index) {
return field
}
}
return nil
}
// hasEffectiveJoin 存在有效的关联表
func hasEffectiveJoins(joins []*CurdOptionsJoin) bool {
for _, join := range joins {
@@ -220,3 +215,107 @@ func ParseDBConfigNodeLink(node *gdb.ConfigNode) *gdb.ConfigNode {
}
return node
}
// ImportWebMethod 导入前端方法
func ImportWebMethod(vs []string) string {
vs = convert.UniqueSlice(vs)
str := "{ " + strings.Join(vs, ", ") + " }"
str = strings.TrimSuffix(str, ", ")
return str
}
// CheckTreeTableFields 检查树表字段
func CheckTreeTableFields(columns []*sysin.GenCodesColumnListModel) (err error) {
var fields = []string{"pid", "level", "tree"}
for _, v := range columns {
if validate.InSlice(fields, v.Name) {
fields = convert.RemoveSlice(fields, v.Name)
}
}
if len(fields) > 0 {
err = gerror.Newf("树表必须包含[%v]字段", strings.Join(fields, "、"))
return err
}
return
}
// CheckIllegalName 检查命名是否合理
func CheckIllegalName(errPrefix string, names ...string) (err error) {
for _, name := range names {
name = strings.ToLower(name)
match, _ := regexp.MatchString("^[a-z_][a-z0-9_]*$", name)
if !match {
err = gerror.Newf("%v存在格式不正确必须全部小写且由字母、数字和下划线组成:%v", errPrefix, name)
return
}
if strings.HasSuffix(name, "test") {
err = gerror.Newf("%v当中不能以`test`结尾:%v", errPrefix, name)
return
}
if StartsWithDigit(name) {
err = gerror.Newf("%v当中不能以阿拉伯数字开头:%v", errPrefix, name)
return
}
}
return
}
func StartsWithDigit(s string) bool {
r := []rune(s)
if len(r) > 0 {
return unicode.IsDigit(r[0])
}
return false
}
// IsPidName 是否是树表的pid字段
func IsPidName(name string) bool {
return name == "pid"
}
func ToTSArray(vs []string) string {
formattedStrings := make([]string, len(vs))
for i, str := range vs {
formattedStrings[i] = fmt.Sprintf("'%s'", str)
}
return fmt.Sprintf("[%s]", strings.Join(formattedStrings, ", "))
}
func FormatGo(ctx context.Context, name, code string) (string, error) {
path := GetTempGeneratePath(ctx) + "/" + name
if err := gfile.PutContents(path, code); err != nil {
return "", err
}
res, err := imports.Process(path, []byte(code), nil)
if err != nil {
err = gerror.Newf(`FormatGo error format "%s" go files: %v`, path, err)
return "", err
}
return string(res), nil
}
func FormatVue(code string) string {
endTag := `</template>`
vueLen := gstr.PosR(code, endTag)
vueCode := code[:vueLen+len(endTag)]
tsCode := code[vueLen+len(endTag):]
vueCode = gohtml.Format(vueCode)
tsCode = FormatTs(tsCode)
return vueCode + tsCode
}
func FormatTs(code string) string {
code = replaceEmptyLinesWithSpace(code)
return code + "\n"
}
func replaceEmptyLinesWithSpace(input string) string {
re := regexp.MustCompile(`\n\s*\n`)
result := re.ReplaceAllString(input, "\n\n")
return result
}
func GetTempGeneratePath(ctx context.Context) string {
return gfile.Abs(gfile.Temp() + "/hotgo-generate/" + simple.AppName(ctx))
}

View File

@@ -38,6 +38,39 @@ func GenJoinOnRelation(masterTable, masterField, joinTable, alias, onField strin
return []string{joinTable, alias, relation}
}
func JoinFields(ctx context.Context, entity interface{}, dao daoInstance, as string) (fs string) {
entityFs, err := convert.GetEntityFieldTags(entity)
if err != nil {
return
}
if len(entityFs) == 0 {
return ""
}
fields, err := dao.Ctx(ctx).TableFields(dao.Table())
if err != nil {
return
}
var columns []string
for _, v := range entityFs {
if !gstr.HasPrefix(v, as) {
continue
}
field := gstr.CaseSnakeFirstUpper(gstr.StrEx(v, as))
if _, ok := fields[field]; ok {
columns = append(columns, fmt.Sprintf("`%s`.`%s` as `%s`", dao.Table(), field, v))
}
}
if len(columns) > 0 {
return gstr.Implode(",", convert.UniqueSlice(columns))
}
return
}
// GenJoinSelect 生成关联表select
// 这里会将实体中的字段驼峰转为下划线于数据库进行匹配,意味着数据库字段必须全部是小写字母+下划线的格式
func GenJoinSelect(ctx context.Context, entity interface{}, dao daoInstance, joins []*Join) (allFields string, err error) {

View File

@@ -0,0 +1,92 @@
// 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/consts"
"hotgo/utility/tree"
)
// TenantRelation 租户关系
type TenantRelation struct {
DeptType string // 部门类型
TenantId int64 // 租户ID
MerchantId int64 // 商户ID
UserId int64 // 用户ID
}
// GetTenantRelation 获取租户关系
func GetTenantRelation(ctx context.Context, memberId int64) (tr *TenantRelation, err error) {
data, err := g.Model("hg_admin_member u").Ctx(ctx).
LeftJoin("hg_admin_dept d", "u.dept_id=d.id").
Fields("u.tree,d.type").
Where("u.id", memberId).One()
if err != nil {
return nil, err
}
if data.IsEmpty() {
err = gerror.Newf("未找到用户[%v]的租户关系,该用户不存在", memberId)
return
}
ids := tree.GetIds(data["tree"].String())
getRelationId := func(deptType string) (int64, error) {
id, err := g.Model("hg_admin_member u").Ctx(ctx).
LeftJoin("hg_admin_dept d", "u.dept_id=d.id").
Fields("u.id").
WhereIn("u.id", ids).Where("d.type", deptType).
OrderAsc("u.level"). // 确保是第一关系
Limit(1).
Value()
if err != nil {
return 0, err
}
if id.Int64() < 1 {
err = gerror.Newf("未找到有效的租户关系,memberId:%v,deptType:%v", memberId, deptType)
return 0, err
}
return id.Int64(), nil
}
tr = new(TenantRelation)
tr.DeptType = data["type"].String()
switch tr.DeptType {
// 公司
case consts.DeptTypeCompany:
return
// 租户
case consts.DeptTypeTenant:
tr.TenantId = memberId
// 商户
case consts.DeptTypeMerchant:
tr.TenantId, err = getRelationId(consts.DeptTypeTenant)
if err != nil {
return nil, err
}
tr.MerchantId = memberId
// 用户
case consts.DeptTypeUser:
tr.TenantId, err = getRelationId(consts.DeptTypeTenant)
if err != nil {
return nil, err
}
tr.MerchantId, err = getRelationId(consts.DeptTypeMerchant)
if err != nil {
return nil, err
}
tr.UserId = memberId
default:
err = gerror.Newf("未找到用户[%]的租户关系,部门类型[%v] 无效", memberId, tr.DeptType)
return nil, err
}
return
}

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