diff --git a/api/v1/system/big_upload.go b/api/v1/system/big_upload.go deleted file mode 100644 index 53f688b..0000000 --- a/api/v1/system/big_upload.go +++ /dev/null @@ -1,38 +0,0 @@ -package system - -import ( - "github.com/gogf/gf/v2/frame/g" - "github.com/tiger1103/gfast/v3/library/upload_chunk" -) - -// 上传文件 -type BigUploadReq struct { - g.Meta `path:"/bigUpload/upload" tags:"系统后台/后台大文件上传" method:"post" summary:"上传文件"` - upload_chunk.UploadReq -} - -type BigUploadRes struct { - upload_chunk.UpLoadRes -} - -// 上传文件检查 -type BigUploadCheckReq struct { - g.Meta `path:"/bigUpload/upload" tags:"系统后台/后台大文件上传" method:"get" summary:"上传文件检查"` - upload_chunk.UploadReq -} - -type BigUploadCheckRes struct { - upload_chunk.CheckRes - Identifier string `json:"identifier"` // 标识 - TotalChunks int `json:"totalChunks"` // 分片总数 -} - -// 上传文件合并 -type BigUploadMergeReq struct { - g.Meta `path:"/bigUpload/uploadMerge" tags:"系统后台/后台大文件上传" method:"post" summary:"上传文件合并"` - upload_chunk.UploadReq -} - -type BigUploadMergeRes struct { - upload_chunk.MergeRes -} diff --git a/api/v1/system/sys_attachment.go b/api/v1/system/sys_attachment.go new file mode 100644 index 0000000..56d6736 --- /dev/null +++ b/api/v1/system/sys_attachment.go @@ -0,0 +1,89 @@ +// ========================================================================== +// GFast自动生成api操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: api/v1/system/sys_attachment.go +// 生成人:gfast +// desc:附件管理相关参数 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package system + +import ( + "github.com/gogf/gf/v2/frame/g" + commonApi "github.com/tiger1103/gfast/v3/api/v1/common" + "github.com/tiger1103/gfast/v3/internal/app/common/model" +) + +// SysAttachmentSearchReq 分页请求参数 +type SysAttachmentSearchReq struct { + g.Meta `path:"/list" tags:"附件管理" method:"get" summary:"附件管理列表"` + commonApi.Author + model.SysAttachmentSearchReq +} + +// SysAttachmentSearchRes 列表返回结果 +type SysAttachmentSearchRes struct { + g.Meta `mime:"application/json"` + *model.SysAttachmentSearchRes +} + +// SysAttachmentAddReq 添加操作请求参数 +type SysAttachmentAddReq struct { + g.Meta `path:"/add" tags:"附件管理" method:"post" summary:"附件管理添加"` + commonApi.Author + *model.SysAttachmentAddReq +} + +// SysAttachmentAddRes 添加操作返回结果 +type SysAttachmentAddRes struct { + commonApi.EmptyRes +} + +// SysAttachmentEditReq 修改操作请求参数 +type SysAttachmentEditReq struct { + g.Meta `path:"/edit" tags:"附件管理" method:"put" summary:"附件管理修改"` + commonApi.Author + *model.SysAttachmentEditReq +} + +// SysAttachmentEditRes 修改操作返回结果 +type SysAttachmentEditRes struct { + commonApi.EmptyRes +} + +// SysAttachmentGetReq 获取一条数据请求 +type SysAttachmentGetReq struct { + g.Meta `path:"/get" tags:"附件管理" method:"get" summary:"获取附件管理信息"` + commonApi.Author + Id int64 `p:"id" v:"required#主键必须"` //通过主键获取 +} + +// SysAttachmentGetRes 获取一条数据结果 +type SysAttachmentGetRes struct { + g.Meta `mime:"application/json"` + *model.SysAttachmentInfoRes +} + +// SysAttachmentDeleteReq 删除数据请求 +type SysAttachmentDeleteReq struct { + g.Meta `path:"/delete" tags:"附件管理" method:"delete" summary:"删除附件管理"` + commonApi.Author + Ids []int64 `p:"ids" v:"required#主键必须"` //通过主键删除 +} + +// SysAttachmentDeleteRes 删除数据返回 +type SysAttachmentDeleteRes struct { + commonApi.EmptyRes +} + +// 附件管理状态修改(状态) +type SysAttachmentStatusSwitchReq struct { + g.Meta `path:"/changeStatus" tags:"附件管理" method:"put" summary:"修改状态"` + commonApi.Author + Id int64 `p:"id" v:"required#主键必须"` //通过主键修改 + Status bool `p:"status" v:"required#状态必须"` //通过主键获取 +} +type SysAttachmentStatusSwitchRes struct { + commonApi.EmptyRes +} diff --git a/api/v1/system/sys_auth_rule.go b/api/v1/system/sys_auth_rule.go index bf028c7..986d0e6 100644 --- a/api/v1/system/sys_auth_rule.go +++ b/api/v1/system/sys_auth_rule.go @@ -30,7 +30,7 @@ type RuleAddReq struct { g.Meta `path:"/menu/add" tags:"系统后台/菜单管理" method:"post" summary:"添加菜单"` commonApi.Author MenuType uint `p:"menuType" v:"min:0|max:2#菜单类型最小值为:min|菜单类型最大值为:max"` - Pid uint `p:"parentId" v:"min:0"` + Pid uint `p:"pid" v:"min:0"` Name string `p:"name" v:"required#请填写规则名称"` Title string `p:"menuName" v:"required|length:1,100#请填写标题|标题长度在:min到:max位"` Icon string `p:"icon"` @@ -80,7 +80,7 @@ type RuleUpdateReq struct { commonApi.Author Id uint `p:"id" v:"required#id必须"` MenuType uint `p:"menuType" v:"min:0|max:2#菜单类型最小值为:min|菜单类型最大值为:max"` - Pid uint `p:"parentId" v:"min:0"` + Pid uint `p:"pid" v:"min:0"` Name string `p:"name" v:"required#请填写规则名称"` Title string `p:"menuName" v:"required|length:1,100#请填写标题|标题长度在:min到:max位"` Icon string `p:"icon"` diff --git a/api/v1/system/sys_big_file.go b/api/v1/system/sys_big_file.go deleted file mode 100644 index 1a37c11..0000000 --- a/api/v1/system/sys_big_file.go +++ /dev/null @@ -1,66 +0,0 @@ -package system - -import ( - "github.com/gogf/gf/v2/frame/g" - commonApi "github.com/tiger1103/gfast/v3/api/v1/common" - "github.com/tiger1103/gfast/v3/internal/app/system/model/entity" -) - -type BigFileSearchReq struct { - g.Meta `path:"/bigFile/list" tags:"大文件管理" method:"get" summary:"大文件管理"` - Name string `p:"name"` //文件名称 - commonApi.PageReq -} - -type BigFileSearchRes struct { - g.Meta `mime:"application/json"` - List []*entity.BigFile `json:"list"` - commonApi.ListRes -} - -type BigFileForm struct { - Name string `p:"name" v:"required#文件名称必须"` - Size int `p:"size" v:"required#文件大小必须"` - Path string `p:"path" v:"required#文件路径必须"` - FullPath string `p:"fullPath"` - MimeType string `p:"mimeType"` - Source int `p:"source"` - Describe string `p:"describe"` - Md5 string `p:"md5"` -} - -type BigFileGetReq struct { - g.Meta `path:"/bigFile/get" tags:"系统后台/大文件管理" method:"get" summary:"获取大文件信息"` - Id uint64 `p:"id"` -} - -type BigFileGetRes struct { - g.Meta `mime:"application/json"` - entity.BigFile -} - -type BigFileAddReq struct { - g.Meta `path:"/bigFile/add" tags:"系统后台/大文件管理" method:"post" summary:"大文件新增"` - BigFileForm -} - -type BigFileAddRes struct { -} - -type BigFileEditReq struct { - g.Meta `path:"/bigFile/edit" tags:"系统后台/大文件管理" method:"put" summary:"大文件新增"` - Id uint64 `p:"id" v:"required|min:1#主键ID不能为空|主键ID参数错误"` - Name string `p:"name" v:"required#标题必须"` - Describe string `p:"describe"` -} - -type BigFileEditRes struct { -} - -type BigFileDeleteReq struct { - g.Meta `path:"/bigFile/delete" tags:"系统后台/大文件管理" method:"delete" summary:"大文件删除"` - Ids []uint64 `p:"ids"` -} - -type BigFileDeleteRes struct { -} diff --git a/api/v1/system/sys_role.go b/api/v1/system/sys_role.go index 332a07c..8f2b484 100644 --- a/api/v1/system/sys_role.go +++ b/api/v1/system/sys_role.go @@ -56,7 +56,7 @@ type RoleAddRes struct { type RoleGetReq struct { g.Meta `path:"/role/get" tags:"系统后台/角色管理" method:"get" summary:"获取角色信息"` commonApi.Author - Id uint `p:"id" v:"required#角色id不能为空""` + Id uint `p:"id" v:"required#角色id不能为空"` } type RoleGetRes struct { diff --git a/api/v1/system/ueditor.go b/api/v1/system/ueditor.go index 28773f0..c17820f 100644 --- a/api/v1/system/ueditor.go +++ b/api/v1/system/ueditor.go @@ -26,6 +26,8 @@ type UEditorReq struct { Action string `p:"action"` Callback string `p:"callback"` File *ghttp.UploadFile `p:"upfile" type:"file"` + Start int `p:"start"` + Size int `p:"size"` } type UEditorRes struct { diff --git a/api/v1/system/upload.go b/api/v1/system/upload.go index b35b09a..679722b 100644 --- a/api/v1/system/upload.go +++ b/api/v1/system/upload.go @@ -3,6 +3,8 @@ package system import ( "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" + "github.com/tiger1103/gfast/v3/api/v1/common" + "github.com/tiger1103/gfast/v3/internal/app/common/model" ) // 单图上传 @@ -19,7 +21,7 @@ type UploadSingleFileReq struct { type UploadSingleRes struct { g.Meta `mime:"application/json"` - UploadResponse + *model.UploadResponse } // 多图上传 @@ -34,12 +36,30 @@ type UploadMultipleFileReq struct { File ghttp.UploadFiles `p:"file" type:"file" dc:"选择上传文件" v:"required#上传文件必须"` } -type UploadMultipleRes []*UploadResponse +type UploadMultipleRes []*model.UploadResponse type UploadResponse struct { - Size int64 `json:"size" dc:"文件大小"` - Path string `json:"path" dc:"文件相对路径"` - FullPath string `json:"fullPath" dc:"文件绝对路径"` - Name string `json:"name" dc:"文件名称"` - Type string `json:"type" dc:"文件类型"` + *model.UploadResponse +} + +type CheckMultipartReq struct { + g.Meta `path:"/upload/checkMultipart" tags:"系统后台/后台文件上传" method:"post" summary:"检查分片"` + common.Author + *model.CheckMultipartReq +} + +type CheckMultipartRes struct { + g.Meta `mime:"application/json"` + *model.CheckMultipartRes +} + +type UploadPartReq struct { + g.Meta `path:"/upload/uploadPart" tags:"系统后台/后台文件上传" method:"post" summary:"分片上传"` + common.Author + *model.UploadPartReq +} + +type UploadPartRes struct { + g.Meta `mime:"application/json"` + *model.UploadPartRes } diff --git a/go.mod b/go.mod index 75238c1..20cae83 100644 --- a/go.mod +++ b/go.mod @@ -10,10 +10,10 @@ require ( github.com/apache/rocketmq-client-go/v2 v2.1.1 github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef github.com/casbin/casbin/v2 v2.42.0 - github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.4 - github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.4 - github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.4 - github.com/gogf/gf/v2 v2.7.4 + github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.0 + github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.0 + github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.0 + github.com/gogf/gf/v2 v2.8.0 github.com/gorilla/websocket v1.5.3 github.com/mojocn/base64Captcha v1.3.6 github.com/mssola/user_agent v0.5.3 @@ -22,10 +22,11 @@ require ( github.com/shirou/gopsutil/v3 v3.23.2 github.com/sony/sonyflake v1.2.0 github.com/tencentyun/cos-go-sdk-v5 v0.7.34 - github.com/tiger1103/gfast-cache v1.0.7 - github.com/tiger1103/gfast-token v1.0.7 + github.com/tiger1103/gfast-cache v1.0.8 + github.com/tiger1103/gfast-token v1.0.8 github.com/wenlng/go-captcha v1.2.5 github.com/xuri/excelize/v2 v2.7.1 + golang.org/x/net v0.28.0 golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d ) @@ -104,7 +105,6 @@ require ( golang.org/x/crypto v0.27.0 // indirect golang.org/x/image v0.16.0 // indirect golang.org/x/mod v0.17.0 // indirect - golang.org/x/net v0.28.0 // indirect golang.org/x/sync v0.8.0 // indirect golang.org/x/sys v0.25.0 // indirect golang.org/x/term v0.24.0 // indirect diff --git a/go.sum b/go.sum index f033908..27dc020 100644 --- a/go.sum +++ b/go.sum @@ -69,14 +69,14 @@ 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-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/gogf/gf/contrib/drivers/mysql/v2 v2.7.4 h1:Rhv48tVnl+o5qyd1hTLxKStWT7MEqP0zrEXKa/t4VLg= -github.com/gogf/gf/contrib/drivers/mysql/v2 v2.7.4/go.mod h1:V6eAZVlFWv4AgDK7VzLbwMZiOygcu/374Rcyhv9hSEM= -github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.4 h1:6eaV81MUtE7NUqYR95wOLQcdZ+OlLxn2GEs+rN+wtrM= -github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.7.4/go.mod h1:JjZO8Ic5UxnFVtEY4cDkpFQQ1tx7pX7ZAQnlJ8ux0Kc= -github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.4 h1:7KS3/mBBLfROPUKjIa8M7umxzajqBA27/CIhWdKAxNc= -github.com/gogf/gf/contrib/nosql/redis/v2 v2.7.4/go.mod h1:B1/0sQcdCpGfpiljng2osL2hoGZkpOXPa+CAvzdoYMw= -github.com/gogf/gf/v2 v2.7.4 h1:cGHUBO5Jr8ty21GN5EO+S2rFYhprdcqnwS7PnWL7+t4= -github.com/gogf/gf/v2 v2.7.4/go.mod h1:EBXneAg/wes86rfeh68XC0a2JBNQylmT7Sp6/8Axk88= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.0 h1:Foyx+sGaHAfLXxbTc4xULyO+jaPmQO7puq2rius0pIQ= +github.com/gogf/gf/contrib/drivers/mysql/v2 v2.8.0/go.mod h1:JuRwELQEatN+KrcumDhSd5nEysyD8Dh3voXjjuKs+Gk= +github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.0 h1:4BVMHFtMGc+l0T+QjDFQsc09fIX4qf0zPWKsb+wxVpI= +github.com/gogf/gf/contrib/drivers/pgsql/v2 v2.8.0/go.mod h1:nZ5VGwXMT4GRow6IK/1VVcPArQtukcF+49kNOwvZT98= +github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.0 h1:12l4LDn/ENMwG//tl6ICXfrAY+9vRy4kzi23H1MSkCI= +github.com/gogf/gf/contrib/nosql/redis/v2 v2.8.0/go.mod h1:8Jp8s33CX4yPajGv5NVUlYHPi5Pru81HUKQv+ccS4/o= +github.com/gogf/gf/v2 v2.8.0 h1:CgNDoLFQCBxQaWOoGMzgU068T+tm0t/eNUgLV2wPJag= +github.com/gogf/gf/v2 v2.8.0/go.mod h1:6iYuZZ+A0ZcH8+4MDS/P0SvTPCvKzRvyAsY1kbkJYJc= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE= @@ -235,10 +235,10 @@ 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 v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tiger1103/gfast-cache v1.0.7 h1:ocGP7Z7BKpk2OPfNBhOGyuWOKwyDZxtqmqL1GiGGTaw= -github.com/tiger1103/gfast-cache v1.0.7/go.mod h1:ZTR64Ad6YHM2fehOg9yE3ysdWxq+aAxXKpmTlVCB2nw= -github.com/tiger1103/gfast-token v1.0.7 h1:xvFN4tQecaHghrAnb/DzcRk8jQjLwn3Tk3GirR/vcoE= -github.com/tiger1103/gfast-token v1.0.7/go.mod h1:gHgyf+25+tt4AbfrAtC+EM/SgM55wgPkLQiksLP/5+4= +github.com/tiger1103/gfast-cache v1.0.8 h1:RK8VM3mS+H/D2uvhgNJnHtU2E7RuIlwW0yKvBQzuaHg= +github.com/tiger1103/gfast-cache v1.0.8/go.mod h1:SNNHfEexumeIXSKz7f/ais+Fi97+TeJvT3r92MqlNk0= +github.com/tiger1103/gfast-token v1.0.8 h1:hRNoGna8ji2lPZjMnpaJgZxh2EP3oAVFUSxEaMy79dY= +github.com/tiger1103/gfast-token v1.0.8/go.mod h1:gHgyf+25+tt4AbfrAtC+EM/SgM55wgPkLQiksLP/5+4= github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= diff --git a/internal/app/common/consts/upload.go b/internal/app/common/consts/upload.go index 22a8143..3a94391 100644 --- a/internal/app/common/consts/upload.go +++ b/internal/app/common/consts/upload.go @@ -8,4 +8,7 @@ const ( FileSizeKey = "sys.uploadFile.fileSize" CheckFileTypeImg = "img" // 文件类型(图片) CheckFileTypeFile = "file" // 文件类型(任意) + + UploadDriverLocal = 0 // 本地上传 + ) diff --git a/internal/app/common/dao/internal/sys_attachment.go b/internal/app/common/dao/internal/sys_attachment.go new file mode 100644 index 0000000..c85899f --- /dev/null +++ b/internal/app/common/dao/internal/sys_attachment.go @@ -0,0 +1,103 @@ +// ========================================================================== +// GFast自动生成dao internal操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/dao/internal/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package internal + +import ( + "context" + + "github.com/gogf/gf/v2/database/gdb" + "github.com/gogf/gf/v2/frame/g" +) + +// SysAttachmentDao is the manager for logic model data accessing and custom defined data operations functions management. +type SysAttachmentDao 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 SysAttachmentColumns // Columns is the short type for Columns, which contains all the column names of Table for convenient usage. +} + +// SysAttachmentColumns defines and stores column names for table sys_attachment. +type SysAttachmentColumns struct { + Id string // 文件ID + AppId string // 应用ID + Drive string // 上传驱动 + Name string // 文件原始名 + Kind string // 上传类型 + MimeType string // 扩展类型 + Path string // 本地路径 + Size string // 文件大小 + Ext string // 扩展名 + Md5 string // md5校验码 + CreatedBy string // 上传人ID + Status string // 状态 + CreatedAt string // 创建时间 + UpdatedAt string // 修改时间 +} + +var sysAttachmentColumns = SysAttachmentColumns{ + Id: "id", + AppId: "app_id", + Drive: "drive", + Name: "name", + Kind: "kind", + MimeType: "mime_type", + Path: "path", + Size: "size", + Ext: "ext", + Md5: "md5", + CreatedBy: "created_by", + Status: "status", + CreatedAt: "created_at", + UpdatedAt: "updated_at", +} + +// NewSysAttachmentDao creates and returns a new DAO object for table data access. +func NewSysAttachmentDao() *SysAttachmentDao { + return &SysAttachmentDao{ + group: "default", + table: "sys_attachment", + columns: sysAttachmentColumns, + } +} + +// DB retrieves and returns the underlying raw database management object of current DAO. +func (dao *SysAttachmentDao) DB() gdb.DB { + return g.DB(dao.group) +} + +// Table returns the table name of current dao. +func (dao *SysAttachmentDao) Table() string { + return dao.table +} + +// Columns returns all column names of current dao. +func (dao *SysAttachmentDao) Columns() SysAttachmentColumns { + return dao.columns +} + +// Group returns the configuration group name of database of current dao. +func (dao *SysAttachmentDao) Group() string { + return dao.group +} + +// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. +func (dao *SysAttachmentDao) 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 *SysAttachmentDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { + return dao.Ctx(ctx).Transaction(ctx, f) +} diff --git a/internal/app/common/dao/sys_attachment.go b/internal/app/common/dao/sys_attachment.go new file mode 100644 index 0000000..4b00474 --- /dev/null +++ b/internal/app/common/dao/sys_attachment.go @@ -0,0 +1,29 @@ +// ========================================================================== +// GFast自动生成dao操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/dao/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package dao + +import ( + "github.com/tiger1103/gfast/v3/internal/app/common/dao/internal" +) + +// sysAttachmentDao is the manager for logic model data accessing and custom defined data operations functions management. +// You can define custom methods on it to extend its functionality as you wish. +type sysAttachmentDao struct { + *internal.SysAttachmentDao +} + +var ( + // SysAttachment is globally public accessible object for table tools_gen_table operations. + SysAttachment = sysAttachmentDao{ + internal.NewSysAttachmentDao(), + } +) + +// Fill with you ideas below. diff --git a/internal/app/common/logic/bigUpload/big_upload.go b/internal/app/common/logic/bigUpload/big_upload.go deleted file mode 100644 index 9229c31..0000000 --- a/internal/app/common/logic/bigUpload/big_upload.go +++ /dev/null @@ -1,74 +0,0 @@ -/* -* @desc:大文件上传 -* @company:云南奇讯科技有限公司 -* @Author: yixiaohu -* @Date: 2022/9/27 16:25 - */ - -package bigUpload - -import ( - "context" - "github.com/tiger1103/gfast/v3/api/v1/system" - "github.com/tiger1103/gfast/v3/internal/app/common/service" - "github.com/tiger1103/gfast/v3/library/upload_chunk" -) - -func init() { - service.RegisterBigUpload(New()) -} - -func New() service.IBigUpload { - return &sBigUpload{} -} - -type sBigUpload struct{} - -// Upload 上传分片文件 -func (s *sBigUpload) Upload(ctx context.Context, req *system.BigUploadReq) (res *system.BigUploadRes, err error) { - uploadChunk := &upload_chunk.UploadChunk{} - result, err := uploadChunk.Upload(req.UploadReq) - if err != nil { - return - } - res = new(system.BigUploadRes) - res.UpLoadRes = *result - return -} - -// UploadCheck 上传文件检查 -func (s *sBigUpload) UploadCheck(ctx context.Context, req *system.BigUploadCheckReq) (res *system.BigUploadCheckRes, err error) { - uploadChunk := &upload_chunk.UploadChunk{} - result, err := uploadChunk.CheckChunk(req.UploadReq) - if err != nil { - return - } - //res = new(common.BigUploadCheckRes) - //res.CheckRes = *result - - res = &system.BigUploadCheckRes{ - CheckRes: *result, - Identifier: req.Identifier, - TotalChunks: req.TotalChunks, - } - return -} - -// UploadMerge 上传文件合并 -func (s *sBigUpload) UploadMerge(ctx context.Context, req *system.BigUploadMergeReq) (res *system.BigUploadRes, err error) { - uploadChunk := &upload_chunk.UploadChunk{} - result, err := uploadChunk.MergeChunk(req.UploadReq) - if err != nil { - return - } - res = &system.BigUploadRes{ - UpLoadRes: upload_chunk.UpLoadRes{ - BaseRes: result.BaseRes, - NeedMerge: false, - Identifier: req.Identifier, - TotalChunks: req.TotalChunks, - }, - } - - return -} diff --git a/internal/app/common/logic/logic.go b/internal/app/common/logic/logic.go index 4bcaf29..1da824b 100644 --- a/internal/app/common/logic/logic.go +++ b/internal/app/common/logic/logic.go @@ -5,12 +5,12 @@ package logic import ( - _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/bigUpload" _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/cache" _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/captcha" _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/eventBus" _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/middleware" _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/snowIDGen" + _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/sysAttachment" _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/sysConfig" _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/sysDictData" _ "github.com/tiger1103/gfast/v3/internal/app/common/logic/sysDictType" diff --git a/internal/app/common/logic/sysAttachment/sys_attachment.go b/internal/app/common/logic/sysAttachment/sys_attachment.go new file mode 100644 index 0000000..2c9ac3c --- /dev/null +++ b/internal/app/common/logic/sysAttachment/sys_attachment.go @@ -0,0 +1,300 @@ +// ========================================================================== +// GFast自动生成logic操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/logic/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package sysAttachment + +import ( + "context" + "github.com/gogf/gf/v2/container/gset" + "github.com/gogf/gf/v2/frame/g" + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/text/gstr" + "github.com/gogf/gf/v2/util/gconv" + "github.com/tiger1103/gfast/v3/internal/app/common/dao" + "github.com/tiger1103/gfast/v3/internal/app/common/model" + "github.com/tiger1103/gfast/v3/internal/app/common/model/do" + "github.com/tiger1103/gfast/v3/internal/app/common/service" + "github.com/tiger1103/gfast/v3/internal/app/system/consts" + "github.com/tiger1103/gfast/v3/library/liberr" +) + +var fileKind = map[string]*gset.StrSet{ + //图片 + "image": gset.NewStrSetFrom([]string{ + "jpeg", + "jpg", + "png", + "gif", + "webp", + "cr2", + "tif", + "bmp", + "heif", + "jxr", + "psd", + "ico", + "dwg", + }), + //文档 + "doc": gset.NewStrSetFrom([]string{ + "doc", + "docx", + "dot", + "xls", + "xlt", + "xlsx", + "xltx", + "ppt", + "pptx", + "pdf", + "txt", + "csv", + "html", + "xml", + "pptm", + "pot", + "wpd", + "md", + "json", + "yaml", + "markdown", + "asciidoc", + "xsl", + "wps", + "sxi", + "sti", + "odp", + }), + //视频 + "video": gset.NewStrSetFrom([]string{ + "mp4", + "m4v", + "mkv", + "webm", + "mov", + "avi", + "wmv", + "mpg", + "flv", + "3gp", + }), + //音频 + "audio": gset.NewStrSetFrom([]string{ + "mid", + "mp3", + "m4a", + "ogg", + "flac", + "wav", + "amr", + "aac", + "aiff", + }), + //压缩包 + "zip": gset.NewStrSetFrom([]string{ + "zip", + "rar", + "tar", + "gz", + "7z", + "tar.gz", + }), + //其它 + "other": gset.NewStrSetFrom([]string{ + "dwf", + "ics", + "vcard", + "apk", + "ipa", + }), +} + +func init() { + service.RegisterSysAttachment(New()) +} + +func New() service.ISysAttachment { + return &sSysAttachment{} +} + +type sSysAttachment struct{} +type AddHandler = func(ctx context.Context) (err error) + +func (s *sSysAttachment) List(ctx context.Context, req *model.SysAttachmentSearchReq) (listRes *model.SysAttachmentSearchRes, err error) { + listRes = new(model.SysAttachmentSearchRes) + err = g.Try(ctx, func(ctx context.Context) { + m := dao.SysAttachment.Ctx(ctx).WithAll() + if req.AppId != "" { + m = m.Where(dao.SysAttachment.Columns().AppId+" = ?", req.AppId) + } + if req.Drive != "" { + m = m.Where(dao.SysAttachment.Columns().Drive+" = ?", req.Drive) + } + if req.Name != "" { + m = m.Where(dao.SysAttachment.Columns().Name+" like ?", "%"+req.Name+"%") + } + if req.Kind != "" { + m = m.Where(dao.SysAttachment.Columns().Kind+" = ?", req.Kind) + } + if req.MimeType != "" { + m = m.Where(dao.SysAttachment.Columns().MimeType+" like ?", "%"+req.MimeType+"%") + } + if req.Status != "" { + m = m.Where(dao.SysAttachment.Columns().Status+" = ?", gconv.Bool(req.Status)) + } + if req.CreatedAt != nil && len(req.CreatedAt) > 0 { + if req.CreatedAt[0] != "" { + m = m.Where(dao.SysAttachment.Columns().UpdatedAt+" >= ?", gconv.Time(req.CreatedAt[0])) + } + if len(req.CreatedAt) > 1 && req.CreatedAt[1] != "" { + m = m.Where(dao.SysAttachment.Columns().UpdatedAt+" < ?", gconv.Time(req.CreatedAt[1])) + } + } + listRes.Total, err = m.Count() + liberr.ErrIsNil(ctx, err, "获取总行数失败") + if req.PageNum == 0 { + req.PageNum = 1 + } + listRes.CurrentPage = req.PageNum + if req.PageSize == 0 { + req.PageSize = consts.PageSize + } + order := "updated_at desc,id desc" + if req.OrderBy != "" { + order = req.OrderBy + } + var res []*model.SysAttachmentListRes + err = m.Page(req.PageNum, req.PageSize).Order(order).Scan(&res) + liberr.ErrIsNil(ctx, err, "获取数据失败") + listRes.List = make([]*model.SysAttachmentListRes, len(res)) + for k, v := range res { + listRes.List[k] = &model.SysAttachmentListRes{ + Id: v.Id, + AppId: v.AppId, + Drive: v.Drive, + Name: v.Name, + Kind: v.Kind, + Path: v.Path, + Size: v.Size, + Ext: v.Ext, + Status: v.Status, + CreatedAt: v.CreatedAt, + UpdatedAt: v.UpdatedAt, + } + } + }) + return +} + +func (s *sSysAttachment) GetById(ctx context.Context, id int64) (res *model.SysAttachmentInfoRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + err = dao.SysAttachment.Ctx(ctx).WithAll().Where(dao.SysAttachment.Columns().Id, id).Scan(&res) + liberr.ErrIsNil(ctx, err, "获取信息失败") + }) + return +} + +func (s *sSysAttachment) GetByMd5(ctx context.Context, md5 string) (res *model.SysAttachmentInfoRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + err = dao.SysAttachment.Ctx(ctx).WithAll().Where(dao.SysAttachment.Columns().Md5, md5).Scan(&res) + liberr.ErrIsNil(ctx, err, "获取信息失败") + if res != nil { + _, _ = dao.SysAttachment.Ctx(ctx).Unscoped().WherePri(res.Id).Update(do.SysAttachment{ + UpdatedAt: gtime.Now(), + }) + } + }) + return +} + +func (s *sSysAttachment) AddUpload(ctx context.Context, req *model.UploadResponse, attr *model.SysAttachmentAddAttribute) (err error) { + ext := gstr.SubStrRune(req.Name, gstr.PosRRune(req.Name, ".")+1, gstr.LenRune(req.Name)-1) + err = s.Add(ctx, &model.SysAttachmentAddReq{ + AppId: attr.AppId, + Drive: attr.Driver, + Name: req.Name, + Kind: s.getFileKind(ext), + MimeType: req.Type, + Path: req.Path, + Size: req.Size, + Ext: ext, + Md5: attr.Md5, + Status: true, + CreatedBy: attr.UserId, + }) + return +} + +func (s *sSysAttachment) Add(ctx context.Context, req *model.SysAttachmentAddReq) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + _, err = dao.SysAttachment.Ctx(ctx).Insert(do.SysAttachment{ + AppId: req.AppId, + Drive: req.Drive, + Name: req.Name, + Kind: req.Kind, + MimeType: req.MimeType, + Path: req.Path, + Size: req.Size, + Ext: req.Ext, + Md5: req.Md5, + Status: req.Status, + CreatedBy: req.CreatedBy, + }) + liberr.ErrIsNil(ctx, err, "添加失败") + }) + return +} + +func (s *sSysAttachment) Edit(ctx context.Context, req *model.SysAttachmentEditReq) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + _, err = dao.SysAttachment.Ctx(ctx).WherePri(req.Id).Update(do.SysAttachment{ + AppId: req.AppId, + Drive: req.Drive, + Name: req.Name, + Kind: req.Kind, + MimeType: req.MimeType, + Path: req.Path, + Size: req.Size, + Ext: req.Ext, + Md5: req.Md5, + Status: req.Status, + }) + liberr.ErrIsNil(ctx, err, "修改失败") + }) + return +} + +func (s *sSysAttachment) Delete(ctx context.Context, ids []int64) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + _, err = dao.SysAttachment.Ctx(ctx).Delete(dao.SysAttachment.Columns().Id+" in (?)", ids) + liberr.ErrIsNil(ctx, err, "删除失败") + }) + return +} + +// 附件管理状态修改(状态) +func (s *sSysAttachment) ChangeStatus(ctx context.Context, id int64, status bool) (err error) { + err = g.Try(ctx, func(ctx context.Context) { + _, err = dao.SysAttachment.Ctx(ctx).WherePri(id). + Update(do.SysAttachment{ + Status: status, + }) + liberr.ErrIsNil(ctx, err, "修改失败") + }) + return +} + +func (s *sSysAttachment) getFileKind(ext string) string { + for k, v := range fileKind { + if v.ContainsI(ext) { + return k + } + } + return "other" +} diff --git a/internal/app/common/logic/upload/upload.go b/internal/app/common/logic/upload/upload.go index b42548e..a310044 100644 --- a/internal/app/common/logic/upload/upload.go +++ b/internal/app/common/logic/upload/upload.go @@ -9,6 +9,8 @@ package upload import ( "context" + "crypto/md5" + "encoding/hex" "errors" "fmt" "github.com/gogf/gf/v2/errors/gerror" @@ -17,11 +19,14 @@ import ( "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" - "github.com/tiger1103/gfast/v3/api/v1/system" "github.com/tiger1103/gfast/v3/internal/app/common/consts" + "github.com/tiger1103/gfast/v3/internal/app/common/model" "github.com/tiger1103/gfast/v3/internal/app/common/model/entity" "github.com/tiger1103/gfast/v3/internal/app/common/service" + "github.com/tiger1103/gfast/v3/library/libUtils" + "github.com/tiger1103/gfast/v3/library/liberr" "github.com/tiger1103/gfast/v3/library/upload" + "io" ) func init() { @@ -35,42 +40,68 @@ func New() service.IUpload { type sUpload struct{} // UploadFiles 上传多文件 -func (s *sUpload) UploadFiles(ctx context.Context, files []*ghttp.UploadFile, checkFileType string, source int) (result system.UploadMultipleRes, err error) { +func (s *sUpload) UploadFiles(ctx context.Context, files []*ghttp.UploadFile, checkFileType string, source int, userId uint64, appId string) (result []*model.UploadResponse, err error) { for _, item := range files { - f, e := s.UploadFile(ctx, item, checkFileType, source) + f, e := s.UploadFile(ctx, item, checkFileType, source, userId, appId) if e != nil { return } - result = append(result, &f) + result = append(result, f) } return } // UploadFile 上传单文件 -func (s *sUpload) UploadFile(ctx context.Context, file *ghttp.UploadFile, checkFileType string, source int) (result system.UploadResponse, err error) { +func (s *sUpload) UploadFile(ctx context.Context, + file *ghttp.UploadFile, checkFileType string, source int, + userId uint64, appId string) (result *model.UploadResponse, err error) { + err = g.Try(ctx, func(ctx context.Context) { + // 检查文件类型 + err = s.CheckType(ctx, checkFileType, file.Filename) + liberr.ErrIsNil(ctx, err) - // 检查文件类型 - err = s.CheckType(ctx, checkFileType, file) - if err != nil { - return - } - - // 检查文件大小 - err = s.CheckSize(ctx, checkFileType, file) - if err != nil { - return - } - - uploader := upload.GetUploader(upload.UploaderType(source)) - if uploader == nil { - err = errors.New("没有找到上传适配器") - return - } - return uploader.Upload(ctx, file) + // 检查文件大小 + err = s.CheckSize(ctx, checkFileType, file.Size) + liberr.ErrIsNil(ctx, err) + //判断该文件是否已经上传过,上传过则不再上传 + var ( + md5 = "" + existsFile *model.SysAttachmentInfoRes + ) + md5, err = s.computeMD5(file) + liberr.ErrIsNil(ctx, err) + existsFile, err = service.SysAttachment().GetByMd5(ctx, md5) + liberr.ErrIsNil(ctx, err, "获取文件信息失败") + if existsFile != nil { + result = &model.UploadResponse{ + Size: existsFile.Size, + Path: existsFile.Path, + FullPath: libUtils.GetDomain(ctx, true) + "/" + existsFile.Path, + Name: existsFile.Name, + Type: existsFile.MimeType, + } + return + } + uploader := upload.GetUploader(upload.UploaderType(source)) + if uploader == nil { + liberr.ErrIsNil(ctx, errors.New("没有找到上传适配器")) + } + result, err = uploader.Upload(ctx, file) + liberr.ErrIsNil(ctx, err) + //保存上传文件到数据库 + err = service.SysAttachment().AddUpload(ctx, result, &model.SysAttachmentAddAttribute{ + Md5: md5, + Driver: gconv.Uint(source), + UserId: userId, + AppId: appId, + }) + liberr.ErrIsNil(ctx, err) + }) + return } // CheckSize 检查上传文件大小 -func (s *sUpload) CheckSize(ctx context.Context, checkFileType string, file *ghttp.UploadFile) (err error) { +func (s *sUpload) CheckSize(ctx context.Context, checkFileType string, fileSize int64) (err error) { var ( configSize *entity.SysConfig @@ -95,7 +126,7 @@ func (s *sUpload) CheckSize(ctx context.Context, checkFileType string, file *ght } var rightSize bool - rightSize, err = s.checkSize(configSize.ConfigValue, file.Size) + rightSize, err = s.checkSize(configSize.ConfigValue, fileSize) if err != nil { return } @@ -107,7 +138,7 @@ func (s *sUpload) CheckSize(ctx context.Context, checkFileType string, file *ght } // CheckType 检查上传文件类型 -func (s *sUpload) CheckType(ctx context.Context, checkFileType string, file *ghttp.UploadFile) (err error) { +func (s *sUpload) CheckType(ctx context.Context, checkFileType string, fileName string) (err error) { var ( configType *entity.SysConfig @@ -130,7 +161,7 @@ func (s *sUpload) CheckType(ctx context.Context, checkFileType string, file *ght return errors.New(fmt.Sprintf("文件检查类型错误:%s|%s", consts.CheckFileTypeFile, consts.CheckFileTypeImg)) } - rightType := s.checkFileType(file.Filename, configType.ConfigValue) + rightType := s.checkFileType(fileName, configType.ConfigValue) if !rightType { err = gerror.New("上传文件类型错误,只能包含后缀为:" + configType.ConfigValue + "的文件。") return @@ -199,3 +230,80 @@ func (s *sUpload) getStaticPath(ctx context.Context) string { } return "" } + +// computeMD5 计算给定文件的 MD5 值 +func (s *sUpload) computeMD5(upFile *ghttp.UploadFile) (string, error) { + file, err := upFile.Open() + if err != nil { + return "", err + } + defer file.Close() + + // 创建一个新的 MD5 哈希对象 + hash := md5.New() + + // 逐块读取文件内容并更新哈希 + if _, err := io.Copy(hash, file); err != nil { + return "", err + } + + // 将 MD5 值转换为十六进制字符串 + return hex.EncodeToString(hash.Sum(nil)), nil +} + +func (s *sUpload) CheckMultipart(ctx context.Context, req *model.CheckMultipartReq) (res *model.CheckMultipartRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + // 检查文件类型 + err = s.CheckType(ctx, req.UploadType, req.FileName) + liberr.ErrIsNil(ctx, err) + + // 检查文件大小 + err = s.CheckSize(ctx, req.UploadType, req.Size) + liberr.ErrIsNil(ctx, err) + //检查文件是否已经上传 + var existsFile *model.SysAttachmentInfoRes + existsFile, err = service.SysAttachment().GetByMd5(ctx, req.Md5) + liberr.ErrIsNil(ctx, err, "获取文件信息失败") + res = new(model.CheckMultipartRes) + if existsFile != nil { + res.Attachment = &model.UploadResponse{ + Size: existsFile.Size, + Path: existsFile.Path, + FullPath: libUtils.GetDomain(ctx, true) + "/" + existsFile.Path, + Name: existsFile.Name, + Type: existsFile.MimeType, + } + return + } + + uploader := upload.GetUploader(upload.UploaderType(req.DriverType)) + if uploader == nil { + liberr.ErrIsNil(ctx, errors.New("没有找到上传适配器")) + } + res, err = uploader.CheckMultipart(ctx, req) + liberr.ErrIsNil(ctx, err) + }) + return +} + +func (s *sUpload) UploadPart(ctx context.Context, req *model.UploadPartReq) (res *model.UploadPartRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + uploader := upload.GetUploader(upload.UploaderType(req.DriverType)) + if uploader == nil { + liberr.ErrIsNil(ctx, errors.New("没有找到上传适配器")) + } + res, err = uploader.UploadPart(ctx, req) + liberr.ErrIsNil(ctx, err) + //保存上传文件到数据库 + if res != nil && res.Finish { + err = service.SysAttachment().AddUpload(ctx, res.Attachment, &model.SysAttachmentAddAttribute{ + Md5: req.Md5, + Driver: gconv.Uint(req.DriverType), + UserId: req.UserId, + AppId: req.AppId, + }) + liberr.ErrIsNil(ctx, err) + } + }) + return +} diff --git a/internal/app/common/model/do/sys_attachment.go b/internal/app/common/model/do/sys_attachment.go new file mode 100644 index 0000000..c7e8b00 --- /dev/null +++ b/internal/app/common/model/do/sys_attachment.go @@ -0,0 +1,34 @@ +// ========================================================================== +// GFast自动生成model entity操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/model/entity/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package do + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" +) + +// SysAttachment is the golang structure for table sys_attachment. +type SysAttachment struct { + gmeta.Meta `orm:"table:sys_attachment, do:true"` + Id interface{} `orm:"id,primary" json:"id"` // 文件ID + AppId interface{} `orm:"app_id" json:"appId"` // 应用ID + Drive interface{} `orm:"drive" json:"drive"` // 上传驱动 + Name interface{} `orm:"name" json:"name"` // 文件原始名 + Kind interface{} `orm:"kind" json:"kind"` // 上传类型 + MimeType interface{} `orm:"mime_type" json:"mimeType"` // 扩展类型 + Path interface{} `orm:"path" json:"path"` // 本地路径 + Size interface{} `orm:"size" json:"size"` // 文件大小 + Ext interface{} `orm:"ext" json:"ext"` // 扩展名 + Md5 interface{} `orm:"md5" json:"md5"` // md5校验码 + CreatedBy interface{} `orm:"created_by" json:"createdBy"` // 上传人ID + Status interface{} `orm:"status" json:"status"` // 状态 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 修改时间 +} diff --git a/internal/app/common/model/entity/sys_attachment.go b/internal/app/common/model/entity/sys_attachment.go new file mode 100644 index 0000000..bc7fc09 --- /dev/null +++ b/internal/app/common/model/entity/sys_attachment.go @@ -0,0 +1,34 @@ +// ========================================================================== +// GFast自动生成model entity操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/model/entity/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package entity + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" +) + +// SysAttachment is the golang structure for table sys_attachment. +type SysAttachment struct { + gmeta.Meta `orm:"table:sys_attachment"` + Id int64 `orm:"id,primary" json:"id"` // 文件ID + AppId string `orm:"app_id" json:"appId"` // 应用ID + Drive string `orm:"drive" json:"drive"` // 上传驱动 + Name string `orm:"name" json:"name"` // 文件原始名 + Kind string `orm:"kind" json:"kind"` // 上传类型 + MimeType string `orm:"mime_type" json:"mimeType"` // 扩展类型 + Path string `orm:"path" json:"path"` // 本地路径 + Size int64 `orm:"size" json:"size"` // 文件大小 + Ext string `orm:"ext" json:"ext"` // 扩展名 + Md5 string `orm:"md5" json:"md5"` // md5校验码 + CreatedBy int64 `orm:"created_by" json:"createdBy"` // 上传人ID + Status bool `orm:"status" json:"status"` // 状态 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt"` // 修改时间 +} diff --git a/internal/app/common/model/sys_attachment.go b/internal/app/common/model/sys_attachment.go new file mode 100644 index 0000000..f1c307b --- /dev/null +++ b/internal/app/common/model/sys_attachment.go @@ -0,0 +1,110 @@ +// ========================================================================== +// GFast自动生成model操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/model/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package model + +import ( + "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/util/gmeta" +) + +// SysAttachmentInfoRes is the golang structure for table sys_attachment. +type SysAttachmentInfoRes struct { + gmeta.Meta `orm:"table:sys_attachment"` + Id int64 `orm:"id,primary" json:"id" dc:"文件ID"` // 文件ID + AppId string `orm:"app_id" json:"appId" dc:"应用ID"` // 应用ID + Drive uint `orm:"drive" json:"drive" dc:"上传驱动"` // 上传驱动 + Name string `orm:"name" json:"name" dc:"文件原始名"` // 文件原始名 + Kind string `orm:"kind" json:"kind" dc:"上传类型"` // 上传类型 + MimeType string `orm:"mime_type" json:"mimeType" dc:"扩展类型"` // 扩展类型 + Path string `orm:"path" json:"path" dc:"本地路径"` // 本地路径 + Size int64 `orm:"size" json:"size" dc:"文件大小"` // 文件大小 + Ext string `orm:"ext" json:"ext" dc:"扩展名"` // 扩展名 + Md5 string `orm:"md5" json:"md5" dc:"md5校验码"` // md5校验码 + CreatedBy int64 `orm:"created_by" json:"createdBy" dc:"上传人ID"` // 上传人ID + CreatedUser LinkUserRes `orm:"with:id=created_by" json:"createdUser"` + Status bool `orm:"status" json:"status" dc:"状态"` // 状态 + CreatedAt *gtime.Time `orm:"created_at" json:"createdAt" dc:"创建时间"` // 创建时间 + UpdatedAt *gtime.Time `orm:"updated_at" json:"updatedAt" dc:"修改时间"` // 修改时间 +} + +type LinkUserRes struct { + gmeta.Meta `orm:"table:sys_user"` + Id uint64 `orm:"id" json:"id"` + UserNickname string `orm:"user_nickname" json:"userNickname"` +} + +type SysAttachmentListRes struct { + Id int64 `json:"id" dc:"文件ID"` + AppId string `json:"appId" dc:"应用ID"` + Drive uint `json:"drive" dc:"上传驱动"` + Name string `json:"name" dc:"文件原始名"` + Kind string `json:"kind" dc:"上传类型"` + Path string `json:"path" dc:"本地路径"` + Size int64 `json:"size" dc:"文件大小"` + Ext string `json:"ext" dc:"扩展名"` + Status bool `json:"status" dc:"状态"` + CreatedAt *gtime.Time `json:"createdAt" dc:"创建时间"` + UpdatedAt *gtime.Time `json:"updatedAt" dc:"修改时间"` +} + +// SysAttachmentSearchReq 分页请求参数 +type SysAttachmentSearchReq struct { + PageReq + AppId string `p:"appId" dc:"应用ID"` //应用ID + Drive string `p:"drive" dc:"上传驱动"` //上传驱动 + Name string `p:"name" dc:"文件原始名"` //文件原始名 + Kind string `p:"kind" dc:"上传类型"` //上传类型 + MimeType string `p:"mimeType" dc:"扩展类型"` //扩展类型 + Status string `p:"status" v:"status@boolean#状态需为true/false" dc:"状态"` //状态 + CreatedAt []string `p:"createdAt" v:"createdAt@datetime-array#创建时间需为YYYY-MM-DD hh:mm:ss格式" dc:"创建时间"` //创建时间 +} + +// SysAttachmentSearchRes 列表返回结果 +type SysAttachmentSearchRes struct { + ListRes + List []*SysAttachmentListRes `json:"list"` +} + +// SysAttachmentAddReq 添加操作请求参数 +type SysAttachmentAddReq struct { + AppId string `p:"appId" v:"required#应用ID不能为空" dc:"应用ID"` + Drive uint `p:"drive" dc:"上传驱动"` + Name string `p:"name" v:"required#文件原始名不能为空" dc:"文件原始名"` + Kind string `p:"kind" dc:"上传类型"` + MimeType string `p:"mimeType" dc:"扩展类型"` + Path string `p:"path" dc:"本地路径"` + Size int64 `p:"size" dc:"文件大小"` + Ext string `p:"ext" dc:"扩展名"` + Md5 string `p:"md5" dc:"md5校验码"` + Status bool `p:"status" v:"required#状态不能为空" dc:"状态"` + CreatedBy uint64 +} + +type SysAttachmentAddAttribute struct { + Md5 string + Driver uint + UserId uint64 + AppId string +} + +// SysAttachmentEditReq 修改操作请求参数 +type SysAttachmentEditReq struct { + Id int64 `p:"id" v:"required#主键ID不能为空" dc:"文件ID"` + AppId uint `p:"appId" v:"required#应用ID不能为空" dc:"应用ID"` + Drive string `p:"drive" dc:"上传驱动"` + Name string `p:"name" v:"required#文件原始名不能为空" dc:"文件原始名"` + Kind string `p:"kind" dc:"上传类型"` + MimeType string `p:"mimeType" dc:"扩展类型"` + Path string `p:"path" dc:"本地路径"` + Size int64 `p:"size" dc:"文件大小"` + Ext string `p:"ext" dc:"扩展名"` + Md5 string `p:"md5" dc:"md5校验码"` + Status bool `p:"status" v:"required#状态不能为空" dc:"状态"` +} diff --git a/internal/app/common/model/upload.go b/internal/app/common/model/upload.go index 65a27e1..be8bded 100644 --- a/internal/app/common/model/upload.go +++ b/internal/app/common/model/upload.go @@ -7,9 +7,60 @@ package model +import ( + "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gtime" +) + type UpFile struct { Name string `json:"name"` Url string `json:"url"` FileType string `json:"fileType"` Size uint64 `json:"size"` } + +type UploadResponse struct { + Size int64 `json:"size" dc:"文件大小"` + Path string `json:"path" dc:"文件相对路径"` + FullPath string `json:"fullPath" dc:"文件绝对路径"` + Name string `json:"name" dc:"文件名称"` + Type string `json:"type" dc:"文件类型"` +} + +// CheckMultipartReq 检查文件分片 +type CheckMultipartReq struct { + UploadType string `p:"uploadType" dc:"文件类型"` + FileName string `p:"fileName" dc:"文件名称"` + Size int64 `p:"size" dc:"文件大小"` + Md5 string `p:"md5" dc:"文件md5值"` + ShardsCount int `p:"shardsCount" dc:"分片数量"` + DriverType int //上传驱动 + UserId uint64 + AppId string +} + +type CheckMultipartRes struct { + Attachment *UploadResponse `json:"attachment" dc:"附件"` + WaitUploadIndex []int `json:"waitUploadIndex" dc:"等待上传的分片索引"` + Progress float64 `json:"progress" dc:"上传进度"` +} + +// UploadPartReq 分片上传 +type UploadPartReq struct { + *CheckMultipartReq + Index int `p:"index" dc:"分片索引"` + File *ghttp.UploadFile `p:"file" type:"file" dc:"分片文件"` +} + +type UploadPartRes struct { + Attachment *UploadResponse `json:"attachment" dc:"附件"` + Finish bool `json:"finish" dc:"是否完成"` +} + +// MultipartProgress 分片进度 +type MultipartProgress struct { + UploadId string `json:"uploadId"` // 上传事件ID + ShardCount int `json:"shardCount"` // 分片数量 + UploadedIndex []int `json:"uploadedIndex"` // 已上传的分片索引 + CreatedAt *gtime.Time `json:"createdAt"` // 创建时间 +} diff --git a/internal/app/common/service/big_upload.go b/internal/app/common/service/big_upload.go deleted file mode 100644 index c246ad2..0000000 --- a/internal/app/common/service/big_upload.go +++ /dev/null @@ -1,30 +0,0 @@ -// ================================================================================ -// Code generated by GoFrame CLI tool. DO NOT EDIT. -// You can delete these comments if you wish manually maintain this interface file. -// ================================================================================ - -package service - -import ( - "context" - "github.com/tiger1103/gfast/v3/api/v1/system" -) - -type IBigUpload interface { - Upload(ctx context.Context, req *system.BigUploadReq) (res *system.BigUploadRes, err error) - UploadCheck(ctx context.Context, req *system.BigUploadCheckReq) (res *system.BigUploadCheckRes, err error) - UploadMerge(ctx context.Context, req *system.BigUploadMergeReq) (res *system.BigUploadRes, err error) -} - -var localBigUpload IBigUpload - -func BigUpload() IBigUpload { - if localBigUpload == nil { - panic("implement not found for interface IBigUpload, forgot register?") - } - return localBigUpload -} - -func RegisterBigUpload(i IBigUpload) { - localBigUpload = i -} diff --git a/internal/app/common/service/sys_attachment.go b/internal/app/common/service/sys_attachment.go new file mode 100644 index 0000000..af687ee --- /dev/null +++ b/internal/app/common/service/sys_attachment.go @@ -0,0 +1,40 @@ +// ========================================================================== +// GFast自动生成service操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/service/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package service + +import ( + "context" + "github.com/tiger1103/gfast/v3/internal/app/common/model" +) + +type ISysAttachment interface { + List(ctx context.Context, req *model.SysAttachmentSearchReq) (res *model.SysAttachmentSearchRes, err error) + GetById(ctx context.Context, Id int64) (res *model.SysAttachmentInfoRes, err error) + GetByMd5(ctx context.Context, md5 string) (res *model.SysAttachmentInfoRes, err error) + AddUpload(ctx context.Context, req *model.UploadResponse, attr *model.SysAttachmentAddAttribute) (err error) + Add(ctx context.Context, req *model.SysAttachmentAddReq) (err error) + Edit(ctx context.Context, req *model.SysAttachmentEditReq) (err error) + Delete(ctx context.Context, Id []int64) (err error) + // 附件管理状态修改(状态) + ChangeStatus(ctx context.Context, id int64, status bool) (err error) +} + +var localSysAttachment ISysAttachment + +func SysAttachment() ISysAttachment { + if localSysAttachment == nil { + panic("implement not found for interface ISysAttachment, forgot register?") + } + return localSysAttachment +} + +func RegisterSysAttachment(i ISysAttachment) { + localSysAttachment = i +} diff --git a/internal/app/common/service/upload.go b/internal/app/common/service/upload.go index ac17829..c938370 100644 --- a/internal/app/common/service/upload.go +++ b/internal/app/common/service/upload.go @@ -7,16 +7,18 @@ package service import ( "context" - "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/tiger1103/gfast/v3/internal/app/common/model" "github.com/gogf/gf/v2/net/ghttp" ) type IUpload interface { - UploadFiles(ctx context.Context, files []*ghttp.UploadFile, checkFileType string, source int) (result system.UploadMultipleRes, err error) - UploadFile(ctx context.Context, file *ghttp.UploadFile, checkFileType string, source int) (result system.UploadResponse, err error) - CheckSize(ctx context.Context, checkFileType string, file *ghttp.UploadFile) (err error) - CheckType(ctx context.Context, checkFileType string, file *ghttp.UploadFile) (err error) + UploadFiles(ctx context.Context, files []*ghttp.UploadFile, checkFileType string, source int, userId uint64, appId string) (result []*model.UploadResponse, err error) + UploadFile(ctx context.Context, file *ghttp.UploadFile, checkFileType string, source int, userId uint64, appId string) (result *model.UploadResponse, err error) + CheckSize(ctx context.Context, checkFileType string, fileSize int64) (err error) + CheckType(ctx context.Context, checkFileType string, fileName string) (err error) + CheckMultipart(ctx context.Context, req *model.CheckMultipartReq) (res *model.CheckMultipartRes, err error) + UploadPart(ctx context.Context, req *model.UploadPartReq) (res *model.UploadPartRes, err error) } var localUpload IUpload diff --git a/internal/app/system/consts/consts.go b/internal/app/system/consts/consts.go index 30c142f..ff0b71e 100644 --- a/internal/app/system/consts/consts.go +++ b/internal/app/system/consts/consts.go @@ -17,4 +17,7 @@ const ( WebsocketTypeTokenUpdated = "tokenUpdated" // WebsocketTypeNotice websocket通知类型-系统通知 WebsocketTypeNotice = "notice" + + // UploadAppId 上传应用ID + UploadAppId = "system" ) diff --git a/internal/app/system/controller/big_file.go b/internal/app/system/controller/big_file.go deleted file mode 100644 index d74bb4f..0000000 --- a/internal/app/system/controller/big_file.go +++ /dev/null @@ -1,38 +0,0 @@ -package controller - -import ( - "context" - "github.com/tiger1103/gfast/v3/api/v1/system" - "github.com/tiger1103/gfast/v3/internal/app/system/service" -) - -type bigFile struct{} - -var BigFile = new(bigFile) - -func (c *bigFile) List(ctx context.Context, req *system.BigFileSearchReq) (res *system.BigFileSearchRes, err error) { - return service.BigFile().List(ctx, req) -} - -// Add 添加系统参数 -func (c *bigFile) Add(ctx context.Context, req *system.BigFileAddReq) (res *system.BigFileAddRes, err error) { - err = service.BigFile().Add(ctx, req, service.Context().GetUserId(ctx)) - return -} - -// Get 获取文件信息 -func (c *bigFile) Get(ctx context.Context, req *system.BigFileGetReq) (res *system.BigFileGetRes, err error) { - return service.BigFile().Get(ctx, req.Id) -} - -// Edit 修改系统参数 -func (c *bigFile) Edit(ctx context.Context, req *system.BigFileEditReq) (res *system.BigFileEditRes, err error) { - err = service.BigFile().Edit(ctx, req, service.Context().GetUserId(ctx)) - return -} - -// Delete 删除系统参数 -func (c *bigFile) Delete(ctx context.Context, req *system.BigFileDeleteReq) (res *system.BigFileDeleteRes, err error) { - err = service.BigFile().Delete(ctx, req.Ids) - return -} diff --git a/internal/app/system/controller/big_upload.go b/internal/app/system/controller/big_upload.go deleted file mode 100644 index 3031275..0000000 --- a/internal/app/system/controller/big_upload.go +++ /dev/null @@ -1,45 +0,0 @@ -package controller - -import ( - "context" - "github.com/gogf/gf/v2/frame/g" - "github.com/tiger1103/gfast/v3/api/v1/system" - "github.com/tiger1103/gfast/v3/internal/app/common/service" -) - -var BigUpload = new(bigUploadController) - -type bigUploadController struct{} - -// 上传分片文件 -func (c *bigUploadController) Upload(ctx context.Context, req *system.BigUploadReq) (res *system.BigUploadRes, err error) { - r := g.RequestFromCtx(ctx) - req = new(system.BigUploadReq) - err = req.Bind(r.Request) - if err != nil { - return - } - return service.BigUpload().Upload(ctx, req) -} - -// 上传文件检查 -func (c *bigUploadController) UploadCheck(ctx context.Context, req *system.BigUploadCheckReq) (res *system.BigUploadCheckRes, err error) { - r := g.RequestFromCtx(ctx) - req = new(system.BigUploadCheckReq) - err = req.Bind(r.Request) - if err != nil { - return - } - return service.BigUpload().UploadCheck(ctx, req) -} - -// 上传文件合并 -func (c *bigUploadController) UploadMerge(ctx context.Context, req *system.BigUploadMergeReq) (res *system.BigUploadRes, err error) { - r := g.RequestFromCtx(ctx) - req = new(system.BigUploadMergeReq) - err = req.Bind(r.Request) - if err != nil { - return - } - return service.BigUpload().UploadMerge(ctx, req) -} diff --git a/internal/app/system/controller/sys_attachment.go b/internal/app/system/controller/sys_attachment.go new file mode 100644 index 0000000..1d296ad --- /dev/null +++ b/internal/app/system/controller/sys_attachment.go @@ -0,0 +1,67 @@ +// ========================================================================== +// GFast自动生成controller操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/controller/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package controller + +import ( + "context" + "errors" + "github.com/tiger1103/gfast/v3/api/v1/system" + commonService "github.com/tiger1103/gfast/v3/internal/app/common/service" + "github.com/tiger1103/gfast/v3/internal/app/system/service" +) + +type sysAttachmentController struct { + BaseController +} + +var SysAttachment = new(sysAttachmentController) + +// List 列表 +func (c *sysAttachmentController) List(ctx context.Context, req *system.SysAttachmentSearchReq) (res *system.SysAttachmentSearchRes, err error) { + res = new(system.SysAttachmentSearchRes) + res.SysAttachmentSearchRes, err = commonService.SysAttachment().List(ctx, &req.SysAttachmentSearchReq) + return +} + +// Get 获取附件管理 +func (c *sysAttachmentController) Get(ctx context.Context, req *system.SysAttachmentGetReq) (res *system.SysAttachmentGetRes, err error) { + res = new(system.SysAttachmentGetRes) + res.SysAttachmentInfoRes, err = commonService.SysAttachment().GetById(ctx, req.Id) + return +} + +// Add 添加附件管理 +func (c *sysAttachmentController) Add(ctx context.Context, req *system.SysAttachmentAddReq) (res *system.SysAttachmentAddRes, err error) { + req.CreatedBy = service.Context().GetUserId(ctx) + err = commonService.SysAttachment().Add(ctx, req.SysAttachmentAddReq) + return +} + +// Edit 修改附件管理 +func (c *sysAttachmentController) Edit(ctx context.Context, req *system.SysAttachmentEditReq) (res *system.SysAttachmentEditRes, err error) { + err = commonService.SysAttachment().Edit(ctx, req.SysAttachmentEditReq) + return +} + +// Delete 删除附件管理 +func (c *sysAttachmentController) Delete(ctx context.Context, req *system.SysAttachmentDeleteReq) (res *system.SysAttachmentDeleteRes, err error) { + err = commonService.SysAttachment().Delete(ctx, req.Ids) + return +} + +// 附件管理状态修改(状态) +func (c *sysAttachmentController) ChangeStatus(ctx context.Context, req *system.SysAttachmentStatusSwitchReq) (res *system.SysAttachmentStatusSwitchRes, err error) { + if !service.SysUser().AccessRule(ctx, service.Context().GetUserId(ctx), "api/v1/system/sysAttachment/edit") { + err = errors.New("没有修改权限") + return + } + err = commonService.SysAttachment().ChangeStatus(ctx, req.Id, req.Status) + return +} diff --git a/internal/app/system/controller/sys_user.go b/internal/app/system/controller/sys_user.go index ba01734..e9901df 100644 --- a/internal/app/system/controller/sys_user.go +++ b/internal/app/system/controller/sys_user.go @@ -2,6 +2,7 @@ package controller import ( "context" + "github.com/gogf/gf/v2/util/gconv" "github.com/tiger1103/gfast/v3/api/v1/system" "github.com/tiger1103/gfast/v3/internal/app/system/model" "github.com/tiger1103/gfast/v3/internal/app/system/model/entity" @@ -136,6 +137,6 @@ func (c *userController) GetUserSelector(ctx context.Context, req *system.UserSe // GetByIds 根据id 获取用户信息 func (c *userController) GetByIds(ctx context.Context, req *system.UserByIdsReq) (res *system.UserByIdsRes, err error) { res = new(system.UserByIdsRes) - res.UserList, err = service.SysUser().GetUsers(ctx, req.Ids) + res.UserList, err = service.SysUser().GetUsers(ctx, gconv.Interfaces(req.Ids)) return } diff --git a/internal/app/system/controller/ueditor.go b/internal/app/system/controller/ueditor.go index 25c4c60..e571c37 100644 --- a/internal/app/system/controller/ueditor.go +++ b/internal/app/system/controller/ueditor.go @@ -15,8 +15,13 @@ import ( "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/util/gconv" "github.com/tiger1103/gfast/v3/api/v1/system" - "github.com/tiger1103/gfast/v3/internal/app/common/consts" - "github.com/tiger1103/gfast/v3/internal/app/common/service" + commonConsts "github.com/tiger1103/gfast/v3/internal/app/common/consts" + "github.com/tiger1103/gfast/v3/internal/app/common/model" + commonService "github.com/tiger1103/gfast/v3/internal/app/common/service" + "github.com/tiger1103/gfast/v3/internal/app/system/consts" + "github.com/tiger1103/gfast/v3/internal/app/system/service" + "github.com/tiger1103/gfast/v3/library/libUtils" + "math" ) var UEditor = new(uEditorController) @@ -49,13 +54,43 @@ func (c *uEditorController) action(ctx context.Context, req *system.UEditorReq) //上传视频 上传文件 case "uploadvideo", "uploadfile": c.uEditorUpload(ctx, req.File, "file") - //列出图片 列出文件 - case "listimage", "listfile": + //列出图片 + case "listimage": + var ( + list g.List + total interface{} = 0 + ) + list, total, err = c.getFileList(ctx, req.Start, req.Size, "image") + if err != nil { + r.Response.WriteJson(g.Map{ + "state": err.Error(), + }) + r.Exit() + } r.Response.WriteJson(g.Map{ "state": "SUCCESS", - "total": 0, - "start": 0, - "list": g.Slice{}, + "total": total, + "start": req.Start, + "list": list, + }) + //列出文件 + case "listfile": + var ( + list g.List + total interface{} = 0 + ) + list, total, err = c.getFileList(ctx, req.Start, req.Size, "") + if err != nil { + r.Response.WriteJson(g.Map{ + "state": err.Error(), + }) + r.Exit() + } + r.Response.WriteJson(g.Map{ + "state": "SUCCESS", + "total": total, + "start": req.Start, + "list": list, }) //抓取远端图片 case "catchimage": @@ -67,6 +102,7 @@ func (c *uEditorController) action(ctx context.Context, req *system.UEditorReq) "state": "请求地址出错", }) } + r.Exit() return } @@ -172,15 +208,15 @@ func (c *uEditorController) ueditorConfig(ctx context.Context, callback string) // ueditor上传图片 func (c *uEditorController) uEditorUpload(ctx context.Context, upFile *ghttp.UploadFile, fType string) { var ( - info system.UploadResponse + info *model.UploadResponse err error r = g.RequestFromCtx(ctx) ) v, _ := g.Cfg().Get(ctx, "upload.default") if fType == "image" { - info, err = service.Upload().UploadFile(ctx, upFile, consts.CheckFileTypeImg, v.Int()) + info, err = commonService.Upload().UploadFile(ctx, upFile, commonConsts.CheckFileTypeImg, v.Int(), service.Context().Get(ctx).User.Id, consts.UploadAppId) } else if fType == "file" { - info, err = service.Upload().UploadFile(ctx, upFile, consts.CheckFileTypeFile, v.Int()) + info, err = commonService.Upload().UploadFile(ctx, upFile, commonConsts.CheckFileTypeFile, v.Int(), service.Context().Get(ctx).User.Id, consts.UploadAppId) } if err != nil { @@ -197,3 +233,37 @@ func (c *uEditorController) uEditorUpload(ctx context.Context, upFile *ghttp.Upl } r.Exit() } + +func (c *uEditorController) getFileList(ctx context.Context, start int, size int, kind string) (list g.List, total interface{}, err error) { + var res *model.SysAttachmentSearchRes + pageNum := gconv.Int(math.Ceil(gconv.Float64(start)/gconv.Float64(size)) + 1) + res, err = commonService.SysAttachment().List(ctx, &model.SysAttachmentSearchReq{ + PageReq: model.PageReq{ + PageNum: pageNum, + PageSize: size, + }, + Kind: kind, + Status: "true", + }) + if err != nil { + return + } + if res != nil { + total = res.Total + list = make(g.List, len(res.List)) + for k, v := range res.List { + path := "" + if v.Drive == commonConsts.UploadDriverLocal { + path = libUtils.GetDomain(ctx, true) + "/" + v.Path + } else { + path = v.Path + } + list[k] = g.Map{ + "url": path, + "mtime": v.UpdatedAt.Timestamp(), + } + } + + } + return +} diff --git a/internal/app/system/controller/upload.go b/internal/app/system/controller/upload.go index b5472c8..b3a77e5 100644 --- a/internal/app/system/controller/upload.go +++ b/internal/app/system/controller/upload.go @@ -4,8 +4,10 @@ import ( "context" "github.com/gogf/gf/v2/frame/g" "github.com/tiger1103/gfast/v3/api/v1/system" - "github.com/tiger1103/gfast/v3/internal/app/common/consts" - "github.com/tiger1103/gfast/v3/internal/app/common/service" + commonConsts "github.com/tiger1103/gfast/v3/internal/app/common/consts" + commonService "github.com/tiger1103/gfast/v3/internal/app/common/service" + "github.com/tiger1103/gfast/v3/internal/app/system/consts" + "github.com/tiger1103/gfast/v3/internal/app/system/service" ) var Upload = new(uploadController) @@ -16,26 +18,28 @@ type uploadController struct{} func (c *uploadController) SingleImg(ctx context.Context, req *system.UploadSingleImgReq) (res *system.UploadSingleRes, err error) { file := req.File v, _ := g.Cfg().Get(ctx, "upload.default") - response, err := service.Upload().UploadFile(ctx, file, consts.CheckFileTypeImg, v.Int()) + response, err := commonService.Upload().UploadFile(ctx, file, commonConsts.CheckFileTypeImg, v.Int(), service.Context().Get(ctx).User.Id, consts.UploadAppId) if err != nil { return } res = &system.UploadSingleRes{ UploadResponse: response, } - // 上传第三方 return } // 上传多图 -func (c *uploadController) MultipleImg(ctx context.Context, req *system.UploadMultipleImgReq) (res *system.UploadMultipleRes, err error) { +func (c *uploadController) MultipleImg(ctx context.Context, req *system.UploadMultipleImgReq) (res system.UploadMultipleRes, err error) { files := req.File - v, _ := g.Cfg().Get(ctx, "upload.default") - mf, err := service.Upload().UploadFiles(ctx, files, consts.CheckFileTypeImg, v.Int()) + res, err = commonService.Upload().UploadFiles(ctx, + files, + commonConsts.CheckFileTypeImg, + g.Cfg().MustGet(ctx, "upload.default").Int(), + service.Context().Get(ctx).User.Id, + consts.UploadAppId) if err != nil { return } - res = &mf return } @@ -43,7 +47,7 @@ func (c *uploadController) MultipleImg(ctx context.Context, req *system.UploadMu func (c *uploadController) SingleFile(ctx context.Context, req *system.UploadSingleFileReq) (res *system.UploadSingleRes, err error) { file := req.File v, _ := g.Cfg().Get(ctx, "upload.default") - response, err := service.Upload().UploadFile(ctx, file, consts.CheckFileTypeFile, v.Int()) + response, err := commonService.Upload().UploadFile(ctx, file, commonConsts.CheckFileTypeFile, v.Int(), service.Context().Get(ctx).User.Id, consts.UploadAppId) if err != nil { return } @@ -54,13 +58,36 @@ func (c *uploadController) SingleFile(ctx context.Context, req *system.UploadSin } // 上传多文件 -func (c *uploadController) MultipleFile(ctx context.Context, req *system.UploadMultipleFileReq) (res *system.UploadMultipleRes, err error) { +func (c *uploadController) MultipleFile(ctx context.Context, req *system.UploadMultipleFileReq) (res system.UploadMultipleRes, err error) { files := req.File - v, _ := g.Cfg().Get(ctx, "upload.default") - mf, err := service.Upload().UploadFiles(ctx, files, consts.CheckFileTypeFile, v.Int()) + res, err = commonService.Upload().UploadFiles(ctx, + files, + commonConsts.CheckFileTypeFile, + g.Cfg().MustGet(ctx, "upload.default").Int(), + service.Context().Get(ctx).User.Id, + consts.UploadAppId) if err != nil { return } - res = &mf + return +} + +func (c *uploadController) CheckMultipart(ctx context.Context, req *system.CheckMultipartReq) (res *system.CheckMultipartRes, err error) { + req.DriverType = g.Cfg().MustGet(ctx, "upload.default").Int() + req.UploadType = commonConsts.CheckFileTypeFile + req.UserId = service.Context().Get(ctx).User.Id + req.AppId = consts.UploadAppId + res = new(system.CheckMultipartRes) + res.CheckMultipartRes, err = commonService.Upload().CheckMultipart(ctx, req.CheckMultipartReq) + return +} + +func (c *uploadController) UploadPart(ctx context.Context, req *system.UploadPartReq) (res *system.UploadPartRes, err error) { + res = new(system.UploadPartRes) + req.DriverType = g.Cfg().MustGet(ctx, "upload.default").Int() + req.UploadType = commonConsts.CheckFileTypeFile + req.UserId = service.Context().Get(ctx).User.Id + req.AppId = consts.UploadAppId + res.UploadPartRes, err = commonService.Upload().UploadPart(ctx, req.UploadPartReq) return } diff --git a/internal/app/system/dao/big_file.go b/internal/app/system/dao/big_file.go deleted file mode 100644 index f7db449..0000000 --- a/internal/app/system/dao/big_file.go +++ /dev/null @@ -1,27 +0,0 @@ -// ================================================================================= -// This is auto-generated by GoFrame CLI tool only once. Fill this file as you wish. -// ================================================================================= - -package dao - -import ( - "github.com/tiger1103/gfast/v3/internal/app/system/dao/internal" -) - -// internalBigFileDao is internal type for wrapping internal DAO implements. -type internalBigFileDao = *internal.BigFileDao - -// bigFileDao is the data access object for table big_file. -// You can define custom methods on it to extend its functionality as you wish. -type bigFileDao struct { - internalBigFileDao -} - -var ( - // BigFile is globally public accessible object for table big_file operations. - BigFile = bigFileDao{ - internal.NewBigFileDao(), - } -) - -// Fill with you ideas below. diff --git a/internal/app/system/dao/internal/big_file.go b/internal/app/system/dao/internal/big_file.go deleted file mode 100644 index 4f60cb0..0000000 --- a/internal/app/system/dao/internal/big_file.go +++ /dev/null @@ -1,98 +0,0 @@ -// ========================================================================== -// Code generated by GoFrame CLI tool. DO NOT EDIT. -// ========================================================================== - -package internal - -import ( - "context" - "github.com/gogf/gf/v2/database/gdb" - "github.com/gogf/gf/v2/frame/g" -) - -// BigFileDao is the data access object for table big_file. -type BigFileDao 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 BigFileColumns // columns contains all the column names of Table for convenient usage. -} - -// BigFileColumns defines and stores column names for table big_file. -type BigFileColumns struct { - Id string // - Name string // 文件名称 - Size string // 文件大小 - Path string // 文件相对路径 - FullPath string // 文件绝对路径 - MimeType string // 文件类型 - Source string // 文件来源 0 - 本地,1 - 腾讯云 2 - 七牛云 - Describe string // 描述 - Md5 string // md5 - CreatedBy string // - UpdatedBy string // - CreatedAt string // - UpdatedAt string // - DeletedAt string // -} - -// bigFileColumns holds the columns for table big_file. -var bigFileColumns = BigFileColumns{ - Id: "id", - Name: "name", - Size: "size", - Path: "path", - FullPath: "full_path", - MimeType: "mime_type", - Source: "source", - Describe: "describe", - Md5: "md5", - CreatedBy: "created_by", - UpdatedBy: "updated_by", - CreatedAt: "created_at", - UpdatedAt: "updated_at", - DeletedAt: "deleted_at", -} - -// NewBigFileDao creates and returns a new DAO object for table data access. -func NewBigFileDao() *BigFileDao { - return &BigFileDao{ - group: "default", - table: "big_file", - columns: bigFileColumns, - } -} - -// DB retrieves and returns the underlying raw database management object of current DAO. -func (dao *BigFileDao) DB() gdb.DB { - return g.DB(dao.group) -} - -// Table returns the table name of current dao. -func (dao *BigFileDao) Table() string { - return dao.table -} - -// Columns returns all column names of current dao. -func (dao *BigFileDao) Columns() BigFileColumns { - return dao.columns -} - -// Group returns the configuration group name of database of current dao. -func (dao *BigFileDao) Group() string { - return dao.group -} - -// Ctx creates and returns the Model for current DAO, It automatically sets the context for current operation. -func (dao *BigFileDao) 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 *BigFileDao) Transaction(ctx context.Context, f func(ctx context.Context, tx gdb.TX) error) (err error) { - return dao.Ctx(ctx).Transaction(ctx, f) -} diff --git a/internal/app/system/logic/sysNotice/sys_notice.go b/internal/app/system/logic/sysNotice/sys_notice.go index e6df3d2..c42b72a 100644 --- a/internal/app/system/logic/sysNotice/sys_notice.go +++ b/internal/app/system/logic/sysNotice/sys_notice.go @@ -10,12 +10,14 @@ package logic import ( + "bytes" "context" "database/sql" "errors" "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/os/gtime" + "github.com/gogf/gf/v2/text/gstr" "github.com/gogf/gf/v2/util/gconv" "github.com/tiger1103/gfast/v3/internal/app/system/consts" "github.com/tiger1103/gfast/v3/internal/app/system/dao" @@ -25,6 +27,9 @@ import ( "github.com/tiger1103/gfast/v3/internal/app/system/service" "github.com/tiger1103/gfast/v3/library/libWebsocket" "github.com/tiger1103/gfast/v3/library/liberr" + "golang.org/x/net/html" + "golang.org/x/net/html/atom" + "strings" ) func init() { @@ -144,10 +149,79 @@ func (s *sSysNotice) ListShow(ctx context.Context, req *model.SysNoticeSearchReq err = m.Page(req.PageNum, req.PageSize).Fields("" + "n.*,nr.id IS NOT NULL as isRead").Order(order).Scan(&res) liberr.ErrIsNil(ctx, err, "获取数据失败") + if req.IsTrim { + for k, v := range res { + v.Content = s.extractTextFromHTML(v.Content) + if gstr.LenRune(v.Content) > 90 { + res[k].Content = gstr.SubStrRune(v.Content, 0, 90) + "..." + } + } + } listRes.List = res }) return } + +// extractParagraphsFromHTML extracts text from all

tags in the HTML, ignoring and other non-text nodes, and decodes HTML entities. +func (s *sSysNotice) extractTextFromHTML(htmlStr string) string { + // Parse the HTML + doc, err := html.Parse(strings.NewReader(htmlStr)) + if err != nil { + return htmlStr + } + + // Create a slice to store the extracted paragraphs + var paragraphs []string + + // Helper function to recursively traverse nodes and collect text content into a buffer + var collectText func(*html.Node, *bytes.Buffer) + collectText = func(n *html.Node, buf *bytes.Buffer) { + switch n.Type { + case html.TextNode: + // Append the text content to the buffer + buf.WriteString(n.Data) + case html.ElementNode: + // Recursively traverse child nodes, but ignore and other non-text-producing elements + // Note: In a more sophisticated implementation, you might want to handle other elements like
, , etc. + if n.DataAtom != atom.Img && n.DataAtom != atom.Script && n.DataAtom != atom.Style { + for c := n.FirstChild; c != nil; c = c.NextSibling { + collectText(c, buf) + } + } + } + } + + // Define a function to recursively traverse nodes and collect text from

tags + var traverseNodes func(*html.Node) + traverseNodes = func(n *html.Node) { + // Check the type of the node + switch n.Type { + case html.ElementNode: + // Check if the node is a

tag + if n.DataAtom == atom.P { + // Create a buffer to store the text content of the

tag + var textBuf bytes.Buffer + collectText(n, &textBuf) + // Decode HTML entities in the collected text and add it to the paragraphs slice + paragraphs = append(paragraphs, html.UnescapeString(strings.TrimSpace(textBuf.String()))) + } else { + // For other tags, just recursively traverse their children + for c := n.FirstChild; c != nil; c = c.NextSibling { + traverseNodes(c) + } + } + } + } + + for n := doc; n != nil; n = n.NextSibling { + if n.Type == html.DocumentNode { + traverseNodes(n.FirstChild) // Start traversal from the first child of the document node (which is usually the tag) + break + } + } + return strings.Join(paragraphs, "") +} + func (s *sSysNotice) GetById(ctx context.Context, id int64) (res *model.SysNoticeInfoRes, err error) { err = g.Try(ctx, func(ctx context.Context) { err = dao.SysNotice.Ctx(ctx).WithAll().Where(dao.SysNotice.Columns().Id, id).Scan(&res) diff --git a/internal/app/system/logic/sysUser/sys_user.go b/internal/app/system/logic/sysUser/sys_user.go index 310e753..96cc7e5 100644 --- a/internal/app/system/logic/sysUser/sys_user.go +++ b/internal/app/system/logic/sysUser/sys_user.go @@ -908,13 +908,13 @@ func (s *sSysUser) Delete(ctx context.Context, ids []int) (err error) { } // GetUsers 通过用户ids查询多个用户信息 -func (s *sSysUser) GetUsers(ctx context.Context, ids []int) (users []*model.SysUserSimpleRes, err error) { +func (s *sSysUser) GetUsers(ctx context.Context, ids []interface{}) (users []*model.SysUserSimpleRes, err error) { if len(ids) == 0 { return } - idsSet := gset.NewIntSetFrom(ids).Slice() + idsSet := gset.NewFrom(ids).Slice() err = g.Try(ctx, func(ctx context.Context) { - err = dao.SysUser.Ctx(ctx).Where(dao.SysUser.Columns().Id+" in(?)", idsSet). + err = dao.SysUser.Ctx(ctx).Where(dao.SysUser.Columns().Id, idsSet). Order(dao.SysUser.Columns().Id + " ASC").Scan(&users) }) return @@ -1182,7 +1182,7 @@ func (s *sSysUser) GetAuthDeptDataWhere(ctx context.Context, m *gdb.Model, userI deptIdArr.Add(gconv.Int64(li["id"])) } case 5: //仅本人数据权限 - whereJustMe = g.Map{deptField: userInfo.Id, createdUserField: userInfo.Id} + whereJustMe = g.Map{deptField: userInfo.DeptId, createdUserField: userInfo.Id} } } } diff --git a/internal/app/system/logic/toolsGenTable/tools_gen_table.go b/internal/app/system/logic/toolsGenTable/tools_gen_table.go index 60e82da..f0388d5 100644 --- a/internal/app/system/logic/toolsGenTable/tools_gen_table.go +++ b/internal/app/system/logic/toolsGenTable/tools_gen_table.go @@ -176,7 +176,9 @@ func (s *sToolsGenTable) SelectDbTableListByNames(ctx context.Context, tableName err := db.GetScan(ctx, &result, sqlStr) liberr.ErrIsNil(ctx, err, "获取表格信息失败") } else if s.IsPg() { - sqlStr = "select * from information_schema.tables WHERE table_schema = current_schema() " + + sqlStr = "select information_schema.tables.*,obj_description(pg_class.oid) AS table_comment " + + " from information_schema.tables JOIN pg_class ON pg_class.relname = table_name " + + " WHERE table_schema = current_schema() " + "AND table_name NOT LIKE 'tools_gen_%' " if len(tableNames) > 0 { in := gstr.TrimRight(gstr.Repeat("?,", len(tableNames)), ",") diff --git a/internal/app/system/model/do/big_file.go b/internal/app/system/model/do/big_file.go deleted file mode 100644 index 04a85d4..0000000 --- a/internal/app/system/model/do/big_file.go +++ /dev/null @@ -1,29 +0,0 @@ -// ================================================================================= -// Code generated by GoFrame CLI tool. DO NOT EDIT. -// ================================================================================= - -package do - -import ( - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gtime" -) - -// BigFile is the golang structure of table big_file for DAO operations like Where/Data. -type BigFile struct { - g.Meta `orm:"table:big_file, do:true"` - Id interface{} // - Name interface{} // 文件名称 - Size interface{} // 文件大小 - Path interface{} // 文件相对路径 - FullPath interface{} // 文件绝对路径 - MimeType interface{} // 文件类型 - Source interface{} // 文件来源 0 - 本地,1 - 腾讯云 2 - 七牛云 - Describe interface{} // 描述 - Md5 interface{} // md5 - CreatedBy interface{} // - UpdatedBy interface{} // - CreatedAt *gtime.Time // - UpdatedAt *gtime.Time // - DeletedAt *gtime.Time // -} diff --git a/internal/app/system/model/entity/big_file.go b/internal/app/system/model/entity/big_file.go deleted file mode 100644 index 4542e82..0000000 --- a/internal/app/system/model/entity/big_file.go +++ /dev/null @@ -1,27 +0,0 @@ -// ================================================================================= -// Code generated by GoFrame CLI tool. DO NOT EDIT. -// ================================================================================= - -package entity - -import ( - "github.com/gogf/gf/v2/os/gtime" -) - -// BigFile is the golang structure for table big_file. -type BigFile struct { - Id uint64 `json:"id" description:""` - Name string `json:"name" description:"文件名称"` - Size int `json:"size" description:"文件大小"` - Path string `json:"path" description:"文件相对路径"` - FullPath string `json:"fullPath" description:"文件绝对路径"` - MimeType string `json:"mimeType" description:"文件类型"` - Source int `json:"source" description:"文件来源 0 - 本地,1 - 腾讯云 2 - 七牛云"` - Describe string `json:"describe" description:"描述"` - Md5 string `json:"md5" description:"md5"` - CreatedBy uint64 `json:"createdBy" description:""` - UpdatedBy uint64 `json:"updatedBy" description:""` - CreatedAt *gtime.Time `json:"createdAt" description:""` - UpdatedAt *gtime.Time `json:"updatedAt" description:""` - DeletedAt *gtime.Time `json:"deletedAt" description:""` -} diff --git a/internal/app/system/model/sys_notice.go b/internal/app/system/model/sys_notice.go index 89fe855..70b47fe 100644 --- a/internal/app/system/model/sys_notice.go +++ b/internal/app/system/model/sys_notice.go @@ -62,6 +62,7 @@ type SysNoticeSearchReq struct { Tag string `p:"tag" v:"tag@integer#标签需为整数" dc:"标签"` //标签 Status string `p:"status" v:"status@integer#状态需为整数" dc:"状态"` //状态 CreatedAt string `p:"createdAt" v:"createdAt@datetime#创建时间需为YYYY-MM-DD hh:mm:ss格式" dc:"创建时间"` //创建时间 + IsTrim bool `p:"isTrim"` } // SysNoticeSearchRes 列表返回结果 diff --git a/internal/app/system/router/router.go b/internal/app/system/router/router.go index fc35a5c..88bc540 100644 --- a/internal/app/system/router/router.go +++ b/internal/app/system/router/router.go @@ -48,14 +48,12 @@ func (router *Router) BindController(ctx context.Context, group *ghttp.RouterGro controller.Monitor, controller.LoginLog, controller.OperLog, - controller.BigFile, controller.ToolsGenTable, controller.Personal, controller.UserOnline, - controller.Cache, // 缓存处理 - controller.Upload, // 普通文件上传 - controller.BigUpload, // 大文件上传 - controller.UEditor, //编辑器 + controller.Cache, // 缓存处理 + controller.Upload, // 普通文件上传 + controller.UEditor, //编辑器 ) //自动绑定定义的控制器 if err := libRouter.RouterAutoBind(ctx, router, group); err != nil { diff --git a/internal/app/system/router/sys_attachment.go b/internal/app/system/router/sys_attachment.go new file mode 100644 index 0000000..1418e8b --- /dev/null +++ b/internal/app/system/router/sys_attachment.go @@ -0,0 +1,25 @@ +// ========================================================================== +// GFast自动生成router操作代码。 +// 生成日期:2024-10-23 16:10:12 +// 生成路径: internal/app/system/router/sys_attachment.go +// 生成人:gfast +// desc:附件管理 +// company:云南奇讯科技有限公司 +// ========================================================================== + +package router + +import ( + "context" + + "github.com/gogf/gf/v2/net/ghttp" + "github.com/tiger1103/gfast/v3/internal/app/system/controller" +) + +func (router *Router) BindSysAttachmentController(ctx context.Context, group *ghttp.RouterGroup) { + group.Group("/sysAttachment", func(group *ghttp.RouterGroup) { + group.Bind( + controller.SysAttachment, + ) + }) +} diff --git a/internal/app/system/service/big_file.go b/internal/app/system/service/big_file.go deleted file mode 100644 index 2c68dff..0000000 --- a/internal/app/system/service/big_file.go +++ /dev/null @@ -1,101 +0,0 @@ -package service - -import ( - "context" - - "github.com/gogf/gf/v2/frame/g" - "github.com/tiger1103/gfast/v3/api/v1/system" - "github.com/tiger1103/gfast/v3/internal/app/system/dao" - "github.com/tiger1103/gfast/v3/internal/app/system/model/do" - - systemConsts "github.com/tiger1103/gfast/v3/internal/app/system/consts" - "github.com/tiger1103/gfast/v3/library/liberr" -) - -type IBigFile interface { - List(ctx context.Context, req *system.BigFileSearchReq) (res *system.BigFileSearchRes, err error) - Add(ctx context.Context, req *system.BigFileAddReq, userId uint64) (err error) - Get(ctx context.Context, id uint64) (res *system.BigFileGetRes, err error) - Edit(ctx context.Context, req *system.BigFileEditReq, userId uint64) (err error) - Delete(ctx context.Context, ids []uint64) (err error) -} - -func BigFile() IBigFile { - return new(bigFileTmpl) -} - -type bigFileTmpl struct{} - -func (s *bigFileTmpl) List(ctx context.Context, req *system.BigFileSearchReq) (res *system.BigFileSearchRes, err error) { - res = new(system.BigFileSearchRes) - err = g.Try(ctx, func(ctx context.Context) { - m := dao.BigFile.Ctx(ctx) - if req != nil { - if req.Name != "" { - m = m.Where("name like ?", "%"+req.Name+"%") - } - } - res.Total, err = m.Count() - liberr.ErrIsNil(ctx, err, "获取数据失败") - if req.PageNum == 0 { - req.PageNum = 1 - } - res.CurrentPage = req.PageNum - if req.PageSize == 0 { - req.PageSize = systemConsts.PageSize - } - - var orderBy string = "id asc" - if req.OrderBy != "" { - orderBy = req.OrderBy - } - err = m.Page(req.PageNum, req.PageSize).Order(orderBy).Scan(&res.List) - liberr.ErrIsNil(ctx, err, "获取数据失败") - }) - return -} - -func (s *bigFileTmpl) Add(ctx context.Context, req *system.BigFileAddReq, userId uint64) (err error) { - err = g.Try(ctx, func(ctx context.Context) { - _, err = dao.BigFile.Ctx(ctx).Insert(do.BigFile{ - Name: req.Name, - Size: req.Size, - Path: req.Path, - FullPath: req.FullPath, - MimeType: req.MimeType, - Source: req.Source, - Describe: req.Describe, - Md5: req.Md5, - }) - liberr.ErrIsNil(ctx, err, "添加失败") - }) - return -} - -func (s *bigFileTmpl) Get(ctx context.Context, id uint64) (res *system.BigFileGetRes, err error) { - res = new(system.BigFileGetRes) - err = g.Try(ctx, func(ctx context.Context) { - err = dao.BigFile.Ctx(ctx).WherePri(id).Scan(&res) - liberr.ErrIsNil(ctx, err, "获取数据失败") - }) - return -} - -func (s *bigFileTmpl) Edit(ctx context.Context, req *system.BigFileEditReq, userId uint64) (err error) { - err = g.Try(ctx, func(ctx context.Context) { - _, err = dao.BigFile.Ctx(ctx).WherePri(req.Id).Update(do.BigFile{ - Name: req.Name, - Describe: req.Describe, - }) - liberr.ErrIsNil(ctx, err, "修改错误") - }) - return -} - -func (s *bigFileTmpl) Delete(ctx context.Context, ids []uint64) (err error) { - err = g.Try(ctx, func(ctx context.Context) { - _, err = dao.BigFile.Ctx(ctx).WherePri(ids).Delete() - liberr.ErrIsNil(ctx, err, "删除失败") - }) - return -} diff --git a/internal/app/system/service/sys_user.go b/internal/app/system/service/sys_user.go index c743e3c..37a91f8 100644 --- a/internal/app/system/service/sys_user.go +++ b/internal/app/system/service/sys_user.go @@ -51,14 +51,14 @@ type ( ResetUserPwd(ctx context.Context, req *system.UserResetPwdReq) (err error) ChangeUserStatus(ctx context.Context, req *system.UserStatusReq) (err error) Delete(ctx context.Context, ids []int) (err error) - GetUsers(ctx context.Context, ids []int) (users []*model.SysUserSimpleRes, err error) + GetUsers(ctx context.Context, ids []interface{}) (users []*model.SysUserSimpleRes, err error) // Deprecated : 此方法已废弃,请使用更简单的GetAuthWhere方法或GetAuthDeptWhere方法 GetDataWhere(ctx context.Context, userInfo *model.ContextUser, entityData interface{}, menuId uint) (where g.Map, err error) HasAccessByDataWhere(ctx context.Context, where g.Map, uid interface{}) bool AccessRule(ctx context.Context, userId uint64, rule string) bool GetUserSelector(ctx context.Context, req *system.UserSelectorReq) (total interface{}, userList []*model.SysUserSimpleRes, err error) GetUsersByRoleId(ctx context.Context, roleId uint) (users []*model.SysUserRoleDeptRes, err error) - GetAuthWhere(ctx context.Context, m *gdb.Model, userInfo *model.ContextUser, field ...string) *gdb.Model + GetAuthWhere(ctx context.Context, m *gdb.Model, userInfo *model.ContextUser, field ...string) *gdb.Model GetAuthDeptWhere(ctx context.Context, m *gdb.Model, userInfo *model.ContextUser, field ...string) *gdb.Model } ) diff --git a/internal/cmd/cmd.go b/internal/cmd/cmd.go index e04ed44..2f43593 100644 --- a/internal/cmd/cmd.go +++ b/internal/cmd/cmd.go @@ -11,10 +11,8 @@ import ( "github.com/gogf/gf/v2/os/glog" "github.com/gogf/gf/v2/text/gstr" "github.com/tiger1103/gfast/v3/internal/consts" + "github.com/tiger1103/gfast/v3/internal/mounter" "github.com/tiger1103/gfast/v3/internal/router" - "github.com/tiger1103/gfast/v3/library/libValidate" - "github.com/tiger1103/gfast/v3/library/upload" - "github.com/tiger1103/gfast/v3/task" ) var ( @@ -26,6 +24,8 @@ var ( g.Log().SetFlags(glog.F_ASYNC | glog.F_TIME_DATE | glog.F_TIME_TIME | glog.F_FILE_LONG) g.Log().Info(ctx, gbase64.MustDecodeString(consts.Logo), "Version:", consts.Version) s := g.Server() + //调用注册已挂载相关组件 + mounter.DoMount(ctx, s) s.Group("/", func(group *ghttp.RouterGroup) { router.R.BindController(ctx, group) }) @@ -43,24 +43,12 @@ var ( } //重新配置swaggerUI静态页面--end-- enhanceOpenAPIDoc(s) - //注册相关组件 - register() s.Run() return nil }, } ) -// 相关组件注册 -func register() { - //注册上传组件 - upload.Register() - //注册自定义验证规则 - libValidate.Register() - //执行计划任务 - task.Run() -} - func enhanceOpenAPIDoc(s *ghttp.Server) { openapi := s.GetOpenApi() openapi.Config.CommonResponse = ghttp.DefaultHandlerResponse{} diff --git a/internal/consts/version.go b/internal/consts/version.go index 698c2e0..4beea58 100644 --- a/internal/consts/version.go +++ b/internal/consts/version.go @@ -9,5 +9,5 @@ package consts const ( Logo = `CiAgIF9fX19fX19fX19fXyAgICAgICAgICAgX18gCiAgLyBfX19fLyBfX19fL19fXyBfX19fX18vIC9fCiAvIC8gX18vIC9fICAvIF9fIGAvIF9fXy8gX18vCi8gL18vIC8gX18vIC8gL18vIChfXyAgKSAvXyAgClxfX19fL18vICAgIFxfXyxfL19fX18vXF9fLyAg` - Version = "3.2.32" + Version = "3.3.0" ) diff --git a/internal/mounter/mount.go b/internal/mounter/mount.go new file mode 100644 index 0000000..23d2068 --- /dev/null +++ b/internal/mounter/mount.go @@ -0,0 +1,33 @@ +/* +* @desc:组件挂载器 +* @company:云南奇讯科技有限公司 +* @Author: yixiaohu +* @Date: 2024/10/25 08:36 + */ + +package mounter + +import ( + "context" + "github.com/gogf/gf/v2/net/ghttp" + "sync" +) + +type MountHandler func(ctx context.Context, s *ghttp.Server) + +var ( + funcOptions = make([]MountHandler, 0) + fLock sync.Mutex +) + +func Mount(handler MountHandler) { + fLock.Lock() + defer fLock.Unlock() + funcOptions = append(funcOptions, handler) +} + +func DoMount(ctx context.Context, s *ghttp.Server) { + for _, fn := range funcOptions { + fn(ctx, s) + } +} diff --git a/library/libUtils/utils.go b/library/libUtils/utils.go index cf58ecd..52dc360 100644 --- a/library/libUtils/utils.go +++ b/library/libUtils/utils.go @@ -32,7 +32,7 @@ func EncryptPassword(password, salt string) string { } // GetDomain 获取当前请求接口域名 -func GetDomain(ctx context.Context) string { +func GetDomain(ctx context.Context, hasUri ...bool) string { r := g.RequestFromCtx(ctx) host := r.Header.Get("X-Forwarded-Host") if host == "" { @@ -41,10 +41,21 @@ func GetDomain(ctx context.Context) string { if host == "" { host = r.Host } + host = gstr.ReplaceByArray(host, []string{":80", "", ":443", ""}) scheme := r.Header.Get("X-Scheme") if scheme == "" { scheme = r.GetSchema() } + if len(hasUri) > 0 && hasUri[0] { + uri := r.Header.Get("X-Original-URI") + if uri != "" { + pos := gstr.PosI(uri, "/api/v1") + if pos >= 0 { + uri = gstr.SubStr(uri, 1, pos) + } + } + return fmt.Sprintf("%s://%s%s", scheme, host, uri) + } return fmt.Sprintf("%s://%s", scheme, host) } @@ -185,7 +196,7 @@ func GetType(p string) (result string, err error) { // GetFilesPath 获取附件相对路径 func GetFilesPath(ctx context.Context, fileUrl string) (path string, err error) { upType := g.Cfg().MustGet(ctx, "upload.default").Int() - if upType != 0 || (upType == 0 && !gstr.ContainsI(fileUrl, consts.UploadPath)) { + if upType != 0 || (!gstr.ContainsI(fileUrl, consts.UploadPath)) { path = fileUrl return } @@ -215,3 +226,22 @@ func SliceUnique[T comparable](slice []T) []T { } return result } + +// DiffSlice 比较两个切片,返回他们的差集 +// slice1 := []int{1, 2, 3, 4, 5} +// slice2 := []int{4, 5, 6, 7, 8} +// fmt.Println(Difference(slice1, slice2)) // Output: [1 2 3] +func DiffSlice[T comparable](s1, s2 []T) []T { + m := make(map[T]bool) + for _, item := range s1 { + m[item] = true + } + + var diff []T + for _, item := range s2 { + if _, ok := m[item]; !ok { + diff = append(diff, item) + } + } + return diff +} diff --git a/library/libValidate/custom_validations.go b/library/libValidate/custom_validations.go index 60a94aa..6a494a4 100644 --- a/library/libValidate/custom_validations.go +++ b/library/libValidate/custom_validations.go @@ -3,14 +3,22 @@ package libValidate import ( "context" "github.com/gogf/gf/v2/errors/gerror" + "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/text/gregex" "github.com/gogf/gf/v2/util/gconv" "github.com/gogf/gf/v2/util/gvalid" + "github.com/tiger1103/gfast/v3/internal/mounter" "strconv" "strings" ) +func init() { + mounter.Mount(func(ctx context.Context, s *ghttp.Server) { + Register() + }) +} + func Register() { gvalid.RegisterRule("integer-array", IntegerArray) gvalid.RegisterRule("float-array", FloatArray) diff --git a/library/upload/init.go b/library/upload/init.go index edf1004..5fb4f9b 100644 --- a/library/upload/init.go +++ b/library/upload/init.go @@ -3,20 +3,23 @@ package upload import ( "context" "github.com/gogf/gf/v2/net/ghttp" - "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/tiger1103/gfast/v3/internal/app/common/model" + "github.com/tiger1103/gfast/v3/internal/mounter" ) const ( SourceLocal UploaderType = iota // 上传到本地 SourceTencent // 上传至腾讯云 SourceQiniu // 上传到七牛云 - SourceOss // 上传到oss + SourceOss // 上传到oss ) type UploaderType int type IUpload interface { - Upload(ctx context.Context, file *ghttp.UploadFile) (result system.UploadResponse, err error) + Upload(ctx context.Context, file *ghttp.UploadFile) (result *model.UploadResponse, err error) + CheckMultipart(ctx context.Context, req *model.CheckMultipartReq) (res *model.CheckMultipartRes, err error) + UploadPart(ctx context.Context, req *model.UploadPartReq) (*model.UploadPartRes, error) } var uploadCollection map[UploaderType]IUpload @@ -46,3 +49,8 @@ func Register() { RegisterUploader(SourceQiniu, &Qiniou{}) RegisterUploader(SourceOss, &OSS{}) } +func init() { + mounter.Mount(func(ctx context.Context, s *ghttp.Server) { + Register() + }) +} diff --git a/library/upload/local.go b/library/upload/local.go index af1cbe6..24d902f 100644 --- a/library/upload/local.go +++ b/library/upload/local.go @@ -6,9 +6,17 @@ import ( "fmt" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" + "github.com/gogf/gf/v2/os/gfile" + "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/text/gstr" - "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/gogf/gf/v2/util/gconv" + "github.com/gogf/gf/v2/util/grand" "github.com/tiger1103/gfast/v3/internal/app/common/consts" + "github.com/tiger1103/gfast/v3/internal/app/common/model" + "github.com/tiger1103/gfast/v3/library/libUtils" + "github.com/tiger1103/gfast/v3/library/liberr" + "sort" + "strconv" "strings" "time" ) @@ -16,28 +24,12 @@ import ( type Local struct { } -func (s *Local) Upload(ctx context.Context, file *ghttp.UploadFile) (result system.UploadResponse, err error) { +func (s *Local) Upload(ctx context.Context, file *ghttp.UploadFile) (result *model.UploadResponse, err error) { if file == nil { err = errors.New("文件必须!") return } - r := g.RequestFromCtx(ctx) - host := r.Header.Get("X-Forwarded-Host") - scheme := r.Header.Get("X-Scheme") - if host == "" { - host = r.Host - } - if scheme == "" { - scheme = r.GetSchema() - } - uri := r.Header.Get("X-Original-URI") - if uri != "" { - pos := gstr.PosI(uri, "/api/v1") - if pos >= 0 { - uri = gstr.SubStr(uri, 1, pos) - } - } - urlPerfix := fmt.Sprintf("%s://%s/%s", scheme, host, uri) + urlPerfix := libUtils.GetDomain(ctx, true) p := strings.Trim(consts.UploadPath, "/") sp := s.getStaticPath(ctx) if sp != "" { @@ -52,11 +44,10 @@ func (s *Local) Upload(ctx context.Context, file *ghttp.UploadFile) (result syst } // 不含静态文件夹的路径 fullPath := p + "/" + nowData + "/" + fileName - - result = system.UploadResponse{ + result = &model.UploadResponse{ Size: file.Size, Path: fullPath, - FullPath: urlPerfix + fullPath, + FullPath: urlPerfix + "/" + fullPath, Name: file.Filename, Type: file.Header.Get("Content-type"), } @@ -71,3 +62,147 @@ func (s *Local) getStaticPath(ctx context.Context) string { } return "" } + +func (s *Local) CheckMultipart(ctx context.Context, req *model.CheckMultipartReq) (res *model.CheckMultipartRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + res = new(model.CheckMultipartRes) + //计算分片数 + for i := 0; i < req.ShardsCount; i++ { + res.WaitUploadIndex = append(res.WaitUploadIndex, i+1) + } + var progress *model.MultipartProgress + progress, err = s.GetMultipartProgress(ctx, req) + liberr.ErrIsNil(ctx, err) + if progress != nil && len(progress.UploadedIndex) > 0 { + res.WaitUploadIndex = libUtils.DiffSlice(progress.UploadedIndex, res.WaitUploadIndex) + } + }) + return +} + +func (s *Local) UploadPart(ctx context.Context, req *model.UploadPartReq) (res *model.UploadPartRes, err error) { + err = g.Try(ctx, func(ctx context.Context) { + pq := &model.CheckMultipartReq{ + UploadType: req.UploadType, + FileName: req.FileName, + Size: req.Size, + Md5: req.Md5, + ShardsCount: req.ShardsCount, + DriverType: req.DriverType, + UserId: req.UserId, + AppId: req.AppId, + } + var progress *model.MultipartProgress + progress, err = s.GetMultipartProgress(ctx, pq) + liberr.ErrIsNil(ctx, err) + if progress == nil { + liberr.ErrIsNil(ctx, errors.New("分片上传信息不存在")) + } + for _, i := range progress.UploadedIndex { + if req.Index == i { + liberr.ErrIsNil(ctx, errors.New("分片已上传")) + } + } + uploadId := s.GenUploadId(req.CheckMultipartReq) + fullPath := s.getPartPath(ctx, uploadId) + //保存分片 + req.File.Filename = gconv.String(req.Index) + ".part" + _, err = req.File.Save(fullPath) + liberr.ErrIsNil(ctx, err, "写入分片文件内容失败") + + res = new(model.UploadPartRes) + //已上传完毕 + if req.ShardsCount == req.Index { + res.Finish = true + //合并文件 + sp := s.getStaticPath(ctx) + if sp != "" { + sp = strings.TrimRight(sp, "/") + } + nowData := time.Now().Format("2006-01-02") + // 包含静态文件夹的路径 + sp = sp + "/" + strings.Trim(consts.UploadPath, "/") + "/" + nowData + fileName := s.GenNewFileName(req.FileName) + err = s.MergerPath(fullPath, sp+"/"+fileName) + liberr.ErrIsNil(ctx, err, "合并分片失败") + //删除临时文件 + gfile.Remove(fullPath) + path := gstr.SubStr(sp, strings.Index(sp, "/"+consts.UploadPath+"/")+1) + + res.Attachment = &model.UploadResponse{ + Size: req.Size, + Path: path + "/" + fileName, + FullPath: libUtils.GetDomain(ctx, true) + "/" + path + "/" + fileName, + Name: req.FileName, + Type: req.File.FileHeader.Header.Get("Content-type"), + } + } + }) + return +} +func (s *Local) GenNewFileName(oldFileName string) string { + ext := gfile.Ext(oldFileName) + fileName := strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6) + return strings.ToLower(fileName + ext) +} +func (s *Local) MergerPath(src string, dst string) error { + parts, err := gfile.ScanDirFile(src, "*.part") + if err != nil { + return err + } + sort.Slice(parts, func(i, j int) bool { + fileI := gfile.Basename(parts[i]) + fileJ := gfile.Basename(parts[j]) + return gconv.Int(gstr.TrimRight(fileI, ".part")) < gconv.Int(gstr.TrimRight(fileJ, ".part")) + }) + for _, file := range parts { + if err = gfile.PutBytesAppend(dst, gfile.GetBytes(file)); err != nil { + return err + } + } + return nil +} + +// GenUploadId 生成上传ID +func (s *Local) GenUploadId(req *model.CheckMultipartReq) string { + return fmt.Sprintf("%s_%d_%s_%d", req.Md5, req.UserId, req.AppId, req.DriverType) +} + +func (s *Local) getPartPath(ctx context.Context, uploadId string) string { + p := strings.Trim(consts.UploadPath, "/") + sp := s.getStaticPath(ctx) + if sp != "" { + sp = strings.TrimRight(sp, "/") + } + // 包含静态文件夹的路径 + return sp + "/" + p + "/tmp/" + uploadId +} + +// GetMultipartProgress 获取或创建分片上传事件进度 +func (s *Local) GetMultipartProgress(ctx context.Context, req *model.CheckMultipartReq) (res *model.MultipartProgress, err error) { + err = g.Try(ctx, func(ctx context.Context) { + uploadId := s.GenUploadId(req) + fullDirPath := s.getPartPath(ctx, uploadId) + res = &model.MultipartProgress{ + UploadId: uploadId, + CreatedAt: gtime.Now(), + ShardCount: req.ShardsCount, + UploadedIndex: []int{}, + } + //路径不存在说明不存在分片信息 + if !gfile.Exists(fullDirPath) { + return + } + //读取路径下的分片 + var filePath []string + filePath, err = gfile.ScanDirFile(fullDirPath, "*.part") + liberr.ErrIsNil(ctx, err, "获取分片文件失败") + for _, v := range filePath { + index := gfile.Basename(v) + index = strings.TrimSuffix(index, ".part") + i := gconv.Int(index) + res.UploadedIndex = append(res.UploadedIndex, i) + } + }) + return +} diff --git a/library/upload/oss.go b/library/upload/oss.go index 7213c74..6714e9e 100644 --- a/library/upload/oss.go +++ b/library/upload/oss.go @@ -10,12 +10,13 @@ package upload import ( "context" "github.com/aliyun/aliyun-oss-go-sdk/oss" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gfile" "github.com/gogf/gf/v2/os/gtime" "github.com/gogf/gf/v2/util/grand" - "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/tiger1103/gfast/v3/internal/app/common/model" "github.com/tiger1103/gfast/v3/library/liberr" "mime/multipart" "strconv" @@ -31,7 +32,7 @@ type OSS struct { Path string `json:"path"` } -func (s *OSS) Upload(ctx context.Context, file *ghttp.UploadFile) (result system.UploadResponse, err error) { +func (s *OSS) Upload(ctx context.Context, file *ghttp.UploadFile) (result *model.UploadResponse, err error) { err = g.Try(ctx, func(ctx context.Context) { var ( client *oss.Client @@ -57,7 +58,7 @@ func (s *OSS) Upload(ctx context.Context, file *ghttp.UploadFile) (result system schema = "https" } url := schema + "://" + s.EndPoint + "/" + name - result = system.UploadResponse{ + result = &model.UploadResponse{ Size: file.Size, Path: url, FullPath: url, @@ -91,3 +92,13 @@ func (s *OSS) getClient() (client *oss.Client, err error) { conn, time, cname, userAgent, verifySsl, redirect, crc, logLevel) return } + +func (s *OSS) CheckMultipart(ctx context.Context, req *model.CheckMultipartReq) (res *model.CheckMultipartRes, err error) { + err = gerror.New("当前驱动暂不支持分片上传!") + return +} + +func (s *OSS) UploadPart(ctx context.Context, req *model.UploadPartReq) (res *model.UploadPartRes, err error) { + err = gerror.New("当前驱动暂不支持分片上传!") + return +} diff --git a/library/upload/qiniou.go b/library/upload/qiniou.go index 58de5e7..d0f9ef4 100644 --- a/library/upload/qiniou.go +++ b/library/upload/qiniou.go @@ -2,24 +2,24 @@ package upload import ( "context" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/util/guid" "github.com/qiniu/go-sdk/v7/auth/qbox" "github.com/qiniu/go-sdk/v7/storage" - "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/tiger1103/gfast/v3/internal/app/common/model" "path" ) type Qiniou struct{} -func (s *Qiniou) Upload(ctx context.Context, file *ghttp.UploadFile) (result system.UploadResponse, err error) { - +func (s *Qiniou) Upload(ctx context.Context, file *ghttp.UploadFile) (result *model.UploadResponse, err error) { url, err := s.toQiniou(ctx, file) if err != nil { return } - result = system.UploadResponse{ + result = &model.UploadResponse{ Size: file.Size, Path: url, FullPath: url, @@ -73,3 +73,13 @@ func (s *Qiniou) toQiniou(ctx context.Context, f *ghttp.UploadFile) (url string, return url, nil } + +func (s *Qiniou) CheckMultipart(ctx context.Context, req *model.CheckMultipartReq) (res *model.CheckMultipartRes, err error) { + err = gerror.New("当前驱动暂不支持分片上传!") + return +} + +func (s *Qiniou) UploadPart(ctx context.Context, req *model.UploadPartReq) (res *model.UploadPartRes, err error) { + err = gerror.New("当前驱动暂不支持分片上传!") + return +} diff --git a/library/upload/tencent.go b/library/upload/tencent.go index d006b2b..498aedc 100644 --- a/library/upload/tencent.go +++ b/library/upload/tencent.go @@ -2,6 +2,7 @@ package upload import ( "context" + "github.com/gogf/gf/v2/errors/gerror" "github.com/gogf/gf/v2/frame/g" "github.com/gogf/gf/v2/net/ghttp" "github.com/gogf/gf/v2/os/gfile" @@ -9,7 +10,7 @@ import ( "github.com/gogf/gf/v2/util/grand" "github.com/tencentyun/cos-go-sdk-v5" "github.com/tencentyun/cos-go-sdk-v5/debug" - "github.com/tiger1103/gfast/v3/api/v1/system" + "github.com/tiger1103/gfast/v3/internal/app/common/model" "io" "net/http" "net/url" @@ -20,7 +21,7 @@ import ( type Tencent struct { } -func (s *Tencent) Upload(ctx context.Context, file *ghttp.UploadFile) (result system.UploadResponse, err error) { +func (s *Tencent) Upload(ctx context.Context, file *ghttp.UploadFile) (result *model.UploadResponse, err error) { v, err := g.Cfg().Get(ctx, "upload.tencentCOS") if err != nil { return @@ -36,7 +37,7 @@ func (s *Tencent) Upload(ctx context.Context, file *ghttp.UploadFile) (result sy name = strings.ToLower(strconv.FormatInt(gtime.TimestampNano(), 36) + grand.S(6)) name = name + gfile.Ext(file.Filename) - path := upPath + name + path := upPath + gtime.Date() + "/" + name url, _ := url.Parse(rawUrl) b := &cos.BaseURL{BucketURL: url} @@ -64,7 +65,7 @@ func (s *Tencent) Upload(ctx context.Context, file *ghttp.UploadFile) (result sy } defer f.Close() _, err = client.Object.Put(context.Background(), path, f, opt) - result = system.UploadResponse{ + result = &model.UploadResponse{ Size: file.Size, Path: rawUrl + path, FullPath: rawUrl + path, @@ -73,3 +74,13 @@ func (s *Tencent) Upload(ctx context.Context, file *ghttp.UploadFile) (result sy } return } + +func (s *Tencent) CheckMultipart(ctx context.Context, req *model.CheckMultipartReq) (res *model.CheckMultipartRes, err error) { + err = gerror.New("当前驱动暂不支持分片上传!") + return +} + +func (s *Tencent) UploadPart(ctx context.Context, req *model.UploadPartReq) (res *model.UploadPartRes, err error) { + err = gerror.New("当前驱动暂不支持分片上传!") + return +} diff --git a/library/upload_chunk/consts.go b/library/upload_chunk/consts.go deleted file mode 100644 index 7f3db40..0000000 --- a/library/upload_chunk/consts.go +++ /dev/null @@ -1,6 +0,0 @@ -package upload_chunk - -const ( - RelativePath = "big_file/" // 返回前端的相对路径 - FileName = "upfile" // 上传文件的文件名 -) diff --git a/library/upload_chunk/helper.go b/library/upload_chunk/helper.go deleted file mode 100644 index b46da79..0000000 --- a/library/upload_chunk/helper.go +++ /dev/null @@ -1,81 +0,0 @@ -package upload_chunk - -import ( - "errors" - "fmt" - "os" - "path" - "strings" -) - -// 解析文件目录,文件前缀及文件后缀 -func parseFilePath(filename string) (dir, prefix, suffix string) { - filenameall := path.Base(filename) //不含目录的文件名 - filesuffix := path.Ext(filename) // 后缀 - fileprefix := strings.TrimSuffix(filenameall, filesuffix) // 前缀 - - dir = strings.TrimRight(filename, filenameall) // 文件目录 - prefix = fileprefix // 文件前缀 - suffix = filesuffix // 文件后缀 - return -} - -// 创建文件 -func createFile(fullFilePath string) (ok bool, err error) { - ok = fileExists(fullFilePath) - if ok { - return - } - dir, _, _ := parseFilePath(fullFilePath) - if dir != "" { - err = mkDir(dir) - if err != nil { - return - } - } - newFile, err := os.Create(fullFilePath) - defer newFile.Close() - if err != nil { - return - } - return -} - -// 创建文件夹 -func mkDir(path string) (err error) { - if !fileExists(path) { - if err = os.MkdirAll(path, os.ModePerm); err != nil { - return errors.New(fmt.Sprintf(`os.MkdirAll failed for path "%s" with perm "%d" , err : %v`, path, os.ModePerm, err)) - } - return nil - } - - return -} - -// 判断所给路径是否为文件夹 -func IsDir(path string) bool { - s, err := os.Stat(path) - if err != nil { - return false - } - return s.IsDir() -} - -// 是否文件 -func IsFile(path string) bool { - return !IsDir(path) -} - -// 判断文件或文件夹是否存在 -func fileExists(path string) bool { - if stat, err := os.Stat(path); stat != nil && !os.IsNotExist(err) { - return true - } - return false -} - -// 生成分片文件名 -func getChunkFilename(identifier, chunkNumber string) string { - return fmt.Sprintf("uploader-%s.%s", identifier, chunkNumber) -} diff --git a/library/upload_chunk/option.go b/library/upload_chunk/option.go deleted file mode 100644 index 4d32fe9..0000000 --- a/library/upload_chunk/option.go +++ /dev/null @@ -1,241 +0,0 @@ -package upload_chunk - -import ( - "encoding/json" - "errors" - "io" - "mime/multipart" - "net/http" - "strconv" -) - -type checkErr func() error - -type UploadReq struct { - ChunkNumber int `json:"chunkNumber"` // 分片序列号 - ChunkSize int `json:"chunkSize"` // 分片大小 - CurrentChunkSize int `json:"currentChunkSize"` // 当前分片大小 - TotalSize int64 `json:"totalSize"` // 文件总大小 - Identifier string `json:"identifier"` // 标识 - Filename string `json:"filename"` // 文件名 - RelativePath string `json:"relativePath"` //文件夹上传的时候文件的相对路径属性 - TotalChunks int `json:"totalChunks"` // 分片总数 - File multipart.File - FileHeader *multipart.FileHeader - - verification map[interface{}][]checkErr -} - -func (u *UploadReq) verificationInit() { - if u.verification == nil { - u.verification = make(map[interface{}][]checkErr) - } -} - -func (u *UploadReq) MustChunkNumber() *UploadReq { - u.verificationInit() - u.verification["ChunkNumber"] = append(u.verification["ChunkNumber"], func() error { - if u.ChunkNumber == 0 { - return errors.New("ChunkNumber不能为空") - } - return nil - }) - - return u -} - -func (u *UploadReq) MustChunkSize() *UploadReq { - u.verificationInit() - u.verification["ChunkSize"] = append(u.verification["ChunkSize"], func() error { - if u.ChunkSize == 0 { - return errors.New("ChunkSize不能为空") - } - return nil - }) - - return u -} - -func (u *UploadReq) MustCurrentChunkSize() *UploadReq { - u.verificationInit() - u.verification["CurrentChunkSize"] = append(u.verification["CurrentChunkSize"], func() error { - if u.CurrentChunkSize == 0 { - return errors.New("CurrentChunkSize不能为空") - } - return nil - }) - return u -} - -func (u *UploadReq) MustTotalSize() *UploadReq { - u.verificationInit() - u.verification["TotalSize"] = append(u.verification["TotalSize"], func() error { - if u.TotalSize == 0 { - return errors.New("TotalSize不能为空") - } - return nil - }) - return u -} - -func (u *UploadReq) MustIdentifier() *UploadReq { - u.verificationInit() - u.verification["Identifier"] = append(u.verification["Identifier"], func() error { - if u.Identifier == "" { - return errors.New("Identifier不能为空") - } - return nil - }) - return u -} - -func (u *UploadReq) MustFilename() *UploadReq { - u.verificationInit() - u.verification["Filename"] = append(u.verification["Filename"], func() error { - if u.Filename == "" { - return errors.New("Filename不能为空") - } - return nil - }) - return u -} - -func (u *UploadReq) MustTotalChunks() *UploadReq { - u.verificationInit() - u.verification["TotalChunks"] = append(u.verification["TotalChunks"], func() error { - if u.TotalChunks == 0 { - return errors.New("TotalChunks不能为空") - } - return nil - }) - return u -} - -func (u *UploadReq) MustFile() *UploadReq { - u.verificationInit() - u.verification["File"] = append(u.verification["File"], func() error { - if u.File == nil || u.FileHeader == nil { - return errors.New("File不能为空") - } - return nil - }) - return u -} - -func (u *UploadReq) Check() (err error) { - for _, item := range u.verification { - for _, fn := range item { - err = fn() - if err != nil { - return - } - - } - } - return -} - -func (u *UploadReq) Bind(r *http.Request) (err error) { - if r.Header.Get("Content-Type") == "application/json" { - l := r.ContentLength - if l == 0 { - return - } - buf := make([]byte, l) - _, err = r.Body.Read(buf) - - if err != nil && err != io.EOF { - return - } - err = json.Unmarshal(buf, u) - if err != nil { - return - } - - } else { - chunkNumber := r.FormValue("chunkNumber") - if chunkNumber != "" { - u.ChunkNumber, _ = strconv.Atoi(chunkNumber) - } - - chunkSize := r.FormValue("chunkSize") - if chunkSize != "" { - u.ChunkSize, _ = strconv.Atoi(chunkSize) - } - - currentChunkSize := r.FormValue("currentChunkSize") - if currentChunkSize != "" { - u.CurrentChunkSize, _ = strconv.Atoi(currentChunkSize) - } - - totalSize := r.FormValue("totalSize") - if totalSize != "" { - u.TotalSize, _ = strconv.ParseInt(totalSize, 10, 64) - } - - identifier := r.FormValue("identifier") - if identifier != "" { - u.Identifier = identifier - } - - filename := r.FormValue("filename") - if filename != "" { - u.Filename = filename - } - - relativePath := r.FormValue("relativePath") - if relativePath != "" { - u.RelativePath = relativePath - } - - totalChunks := r.FormValue("totalChunks") - if totalChunks != "" { - u.TotalChunks, _ = strconv.Atoi(totalChunks) - } - } - - u.File, u.FileHeader, _ = r.FormFile(FileName) - return -} - -type BaseRes struct { - Filename string `json:"filename"` // 文件名 - TotalSize int64 `json:"totalSize"` // 文件总大小 - Url string `json:"url"` // 上传文件路径 -} - -// 返回前端的相对路径 -func (b *BaseRes) RelativePath() { - _, prefix, suffix := parseFilePath(b.Url) - b.Url = RelativePath + prefix + suffix -} - -type UpLoadRes struct { - BaseRes - NeedMerge bool `json:"needMerge"` // 是否合并文件 - Identifier string `json:"identifier"` // 标识 - TotalChunks int `json:"totalChunks"` // 分片总数 -} - -type CheckRes struct { - SkipUpload bool `json:"skipUpload"` // 秒传 - Uploaded []int `json:"uploaded"` // 已上传过的分片 - BaseRes -} - -func (r *CheckRes) HasUploaded(i int) (ok bool) { - for _, item := range r.Uploaded { - if item == i { - return true - } - } - return -} - -func (r *CheckRes) HasFirst() (ok bool) { - return r.HasUploaded(1) -} - -type MergeRes struct { - BaseRes -} diff --git a/library/upload_chunk/upload_chunk.go b/library/upload_chunk/upload_chunk.go deleted file mode 100644 index 5699fd8..0000000 --- a/library/upload_chunk/upload_chunk.go +++ /dev/null @@ -1,311 +0,0 @@ -package upload_chunk - -import ( - "errors" - "fmt" - "github.com/gogf/gf/v2/frame/g" - "github.com/gogf/gf/v2/os/gctx" - "io" - "log" - "mime/multipart" - "os" - "strconv" - "strings" - "sync" -) - -type UploadChunk struct{} - -// 检查分片 -func (u *UploadChunk) CheckChunk(uploadReq UploadReq) (result *CheckRes, err error) { - - err = uploadReq.MustIdentifier().MustTotalChunks().MustFilename().MustTotalSize().Check() - if err != nil { - return - } - identifier, totalChunks, filename, totalSize := uploadReq.Identifier, uploadReq.TotalChunks, uploadReq.Filename, uploadReq.TotalSize - - dir, prefix, suffix := parseFilePath(filename) - _, _, _ = dir, prefix, suffix - - if !strings.Contains(suffix, ".") { - err = errors.New("文件名解析错误") - return - } - - result = &CheckRes{} - - // 秒传 - resultFilePath := u.Tmp() + identifier + suffix - if fileExists(resultFilePath) { - result.SkipUpload = true - result.Url = resultFilePath - result.Filename = filename - result.TotalSize = totalSize - result.RelativePath() - return - } - - // 断点续传 - for i := 1; i <= totalChunks; i++ { - chunkFilePath := u.chunkPath(identifier, strconv.FormatInt(int64(i), 10)) - if fileExists(chunkFilePath) { - result.Uploaded = append(result.Uploaded, i) - } - } - - return -} - -// 合并文件 -func (u *UploadChunk) MergeChunk(uploadReq UploadReq) (result *MergeRes, err error) { - err = uploadReq.MustIdentifier().MustTotalChunks().MustTotalSize().MustFilename().Check() - if err != nil { - return - } - identifier, totalChunks, totalSize, filename := uploadReq.Identifier, uploadReq.TotalChunks, uploadReq.TotalSize, uploadReq.Filename - - _, _, suffix := parseFilePath(filename) - if !strings.Contains(suffix, ".") { - return nil, errors.New("文件名解析错误") - } - - // 合并后的文件 - resultFilePath := u.Tmp() + identifier + suffix - ok, err := createFile(resultFilePath) - if err != nil { - return - } - result = new(MergeRes) - // 文件已存在 - if ok { - result.Url = resultFilePath - result.Filename = filename - result.TotalSize = totalSize - result.RelativePath() - return - } - - // 检查分片文件是否完整 - ok, err = u.checkChunkAll(identifier, totalChunks, totalSize) - if err != nil { - err = fmt.Errorf("分片文件检查错误:%s", err) - return - } - - if !ok { - err = errors.New("分片文件不完整") - return - } - - var chunkSize int64 - var wg sync.WaitGroup - ch := make(chan struct{}, 10) - for i := 1; i <= totalChunks; i++ { - // 分片文件 - filePath := u.chunkPath(identifier, fmt.Sprintf("%d", i)) - if chunkSize == 0 { - fi, _ := os.Stat(filePath) - if chunkSize = fi.Size(); chunkSize == 0 { - err = errors.New("分片文件大小为0") - return - } - } - ch <- struct{}{} - wg.Add(1) - go func(i int) { - defer func() { - <-ch - wg.Done() - }() - uploadChunk := &UploadChunk{} - err = uploadChunk.mergeFile(filePath, resultFilePath, chunkSize*int64(i-1)) - if err != nil { - log.Println(err) - return - } - }(i) - } - wg.Wait() - - result.Url = resultFilePath - result.Filename = filename - result.TotalSize = totalSize - result.RelativePath() - return -} - -// 上传分片文件 -func (u *UploadChunk) Upload(uploadReq UploadReq) (result *UpLoadRes, err error) { - err = uploadReq.MustTotalChunks().MustChunkNumber().MustIdentifier().MustFile().MustTotalSize().MustFilename().Check() - if err != nil { - return - } - totalChunks, chunkNumber, identifier, upFile, filename := uploadReq.TotalChunks, uploadReq.ChunkNumber, uploadReq.Identifier, uploadReq.File, uploadReq.Filename - var fullFilePath string - if totalChunks > 1 { - // 分片文件路径 - fullFilePath = u.chunkPath(identifier, strconv.Itoa(chunkNumber)) - } else { - _, _, suffix := parseFilePath(filename) - if !strings.Contains(suffix, ".") { - return nil, errors.New("文件名解析错误") - } - fullFilePath = u.Tmp() + identifier + suffix - } - - // 创建文件 - ok, err := createFile(fullFilePath) - - if err != nil { - return - } - if ok { - // 文件已经存在 - result = &UpLoadRes{ - BaseRes: BaseRes{ - Filename: uploadReq.Filename, - TotalSize: uploadReq.TotalSize, - Url: fullFilePath, - }, - NeedMerge: totalChunks > 1, - Identifier: uploadReq.Identifier, - TotalChunks: uploadReq.TotalChunks, - } - result.RelativePath() - return - } - - // 打开分片文件 - file, err := os.OpenFile(fullFilePath, os.O_CREATE|os.O_WRONLY, 0666) - if err != nil { - return - } - defer file.Close() - // 文件偏移量 - var fi os.FileInfo - fi, err = os.Stat(fullFilePath) - if err != nil { - return - } - start := fi.Size() - // 写入分片文件 - _, err = u.writeFile(upFile, start, file, start) - if err != nil { - return - } - result = &UpLoadRes{ - BaseRes: BaseRes{ - Filename: uploadReq.Filename, - TotalSize: uploadReq.TotalSize, - Url: fullFilePath, - }, - NeedMerge: totalChunks > 1, - Identifier: uploadReq.Identifier, - TotalChunks: uploadReq.TotalChunks, - } - result.RelativePath() - return -} - -func (u *UploadChunk) Tmp() string { - return g.Cfg().MustGet(gctx.New(), "server.serverRoot").String() + "/big_file/" // 文件保存目录 -} - -// 合并文件 -func (u *UploadChunk) mergeFile(chunkFile, mergeFile string, offset int64) (err error) { - - // 合并后的文件 - file, err := os.OpenFile(mergeFile, os.O_CREATE|os.O_WRONLY, os.ModePerm) - if err != nil { - return - } - defer file.Close() - - _, err = file.Seek(offset, 0) - if err != nil { - return - } - // 分片文件 - chunkFileObj, err := os.Open(chunkFile) - if err != nil { - return - } - defer chunkFileObj.Close() - // 写入数据 - data := make([]byte, 1024, 1024) - - for { - tal, e := chunkFileObj.Read(data) - if e == io.EOF { - chunkFileObj.Close() - os.Remove(chunkFile) - break - } - _, e = file.Write(data[:tal]) - if e != nil { - return e - } - } - return -} - -// 检查分片文件是否完整 -func (u *UploadChunk) checkChunkAll(identifier string, totalChunks int, totalSize int64) (ok bool, err error) { - if identifier == "" || totalChunks == 0 { - return false, errors.New("checkChunkAll 参数错误") - } - var _totalSize int64 - for i := 1; i <= totalChunks; i++ { - filePath := u.chunkPath(identifier, fmt.Sprintf("%d", i)) - fi, e := os.Stat(filePath) - if e != nil { - return false, e - } - _totalSize += fi.Size() - } - - return _totalSize == totalSize, nil -} - -// 获取分片文件路径 -func (u *UploadChunk) chunkPath(identifier string, chunkNumber string) string { - return fmt.Sprintf("%s%s", u.Tmp(), getChunkFilename(identifier, chunkNumber)) -} - -// 检查文件完整性 -func (u *UploadChunk) verifyFileSize(fullFilePath string, size int64) (ok bool, err error) { - fi, err := os.Stat(fullFilePath) - if err != nil { - return - } - if fi.Size() == size { - return true, nil - } - return false, nil -} - -// 写入文件 -func (u *UploadChunk) writeFile(upfile multipart.File, upSeek int64, file *os.File, fSeek int64) (result int, err error) { - // 上传文件大小记录 - fileSzie := 0 - // 设置上传偏移量 - upfile.Seek(upSeek, 0) - // 设置文件偏移量 - file.Seek(fSeek, 0) - data := make([]byte, 1024, 1024) - for { - total, e := upfile.Read(data) - if e == io.EOF { - // 文件复制完毕 - break - } - l, e := file.Write(data[:total]) - if e != nil { - return 0, errors.New("文件上传失败") - } - // 记录上传长度 - fileSzie += l - } - return fileSzie, nil -} diff --git a/resource/template/vm/go/logic.template b/resource/template/vm/go/logic.template index 7a3ab7c..88f6799 100644 --- a/resource/template/vm/go/logic.template +++ b/resource/template/vm/go/logic.template @@ -18,13 +18,21 @@ package {{$structName}} {{$gstr:=false}} {{$hasLinkTable:=false}} {{$useCommonService:=false}} +{{$hasDeptSelector:=false}} +{{$usedSystemModel := false}} {{range $index, $column := .table.Columns}} -{{if eq $column.HtmlType "images" "file" "files"}} +{{if eq $column.HtmlType "images" "file" "files" "imageSelector" "fileSelector"}} {{$libUtils = true}} {{end}} -{{if and (eq $column.HtmlField "createdBy" "updatedBy" "deletedBy" "deptId") (ne $.table.ModuleName "system")}} +{{if eq $column.HtmlType "deptSelectorMultiple" "deptSelectorSingle"}} +{{$hasDeptSelector = true}} +{{end}} +{{if and (or (eq $column.HtmlField "createdBy" "updatedBy" "deletedBy" "deptId") (eq $column.HtmlType "userSelectorSingle" "userSelectorMultiple" "deptSelectorMultiple" "deptSelectorSingle")) (ne $.table.ModuleName "system")}} {{$usedSystemModule = true}} {{end}} +{{if and (eq $column.HtmlType "userSelectorSingle" "userSelectorMultiple" "deptSelectorMultiple" "deptSelectorSingle") (ne $.table.ModuleName "system")}} +{{$usedSystemModel = true}} +{{end}} {{if eq $column.HtmlType "selects" "checkbox"}} {{range $ti, $linkedTable := $.table.LinkedTables}} {{if eq $column.LinkTableClass $linkedTable.ClassName}} @@ -66,6 +74,9 @@ import ( {{if $usedSystemModule}} systemService "{{.goModName}}/internal/app/system/service" {{end}} + {{if $usedSystemModel}} + systemModel "{{.goModName}}/internal/app/system/model" + {{end}} {{if or (eq .table.TplCategory "tree") $libUtils}} "{{.goModName}}/library/libUtils" {{end}} @@ -125,7 +136,19 @@ func (s *s{{.table.ClassName}})List(ctx context.Context, req *model.{{.table.Cla m = m.Where(dao.{{$.table.ClassName}}.Columns().{{$column.GoField}}+" like ?", "%"+req.{{$column.GoField}}+"%") } {{else if eq $column.QueryType "EQ"}} - {{if eq $column.GoType "string"}} + {{if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}} + if len(req.{{$column.GoField}}) > 0 { + if systemService.ToolsGenTable().IsMysql() { + for _, v := range req.{{$column.GoField}} { + m = m.Where("JSON_CONTAINS(`{{$column.ColumnName}}`,?)", gconv.String(v)) + } + }else{ + for _, v := range req.{{$column.GoField}} { + m = m.Where(`"{{$column.ColumnName}}" @> '[?]'::jsonb`, v) + } + } + } + {{else if eq $column.GoType "string"}} if req.{{$column.GoField}} != "" { m = m.Where(dao.{{$.table.ClassName}}.Columns().{{$column.GoField}}+" = ?", {{if ne $column.FieldConversion ""}}{{$column.FieldConversion}}({{end}}req.{{$column.GoField}}{{if ne $column.FieldConversion ""}}){{end}}) } @@ -183,6 +206,17 @@ func (s *s{{.table.ClassName}})List(ctx context.Context, req *model.{{.table.Cla listRes.List = make([]*model.{{.table.ClassName}}ListRes,len(res)) for k,v:=range res{ {{range $index, $column := .table.Columns}} + {{if eq $column.HtmlType "userSelectorMultiple"}} + var linked{{$column.GoField}} []*{{if $usedSystemModel}}systemModel{{else}}model{{end}}.SysUserSimpleRes + linked{{$column.GoField}}, err = {{if $usedSystemModule}}systemService{{else}}service{{end}}.SysUser().GetUsers(ctx, gconv.Interfaces(v.{{$column.GoField}})) + liberr.ErrIsNil(ctx, err) + {{end}} + {{if eq $column.HtmlType "deptSelectorMultiple"}} + linked{{$column.GoField}} := make([]*{{if $usedSystemModel}}systemModel{{else}}model{{end}}.LinkDeptRes, len(v.{{$column.GoField}})) + for lk, lv := range v.{{$column.GoField}} { + linked{{$column.GoField}}[lk] = {{if $usedSystemModule}}systemService{{else}}service{{end}}.SysDept().GetByDept(ctx, lv) + } + {{end}} {{if eq $column.HtmlType "selects" "checkbox" "treeSelects"}} {{range $ti, $linkedTable := $.table.LinkedTables}} {{if eq $column.LinkTableClass $linkedTable.ClassName}} @@ -214,8 +248,6 @@ func (s *s{{.table.ClassName}})List(ctx context.Context, req *model.{{.table.Cla {{if and $column.IsList (eq $column.HtmlField "UpdatedBy")}} UpdatedUser:v.UpdatedUser, {{end}} - {{end}} - {{range $index, $column := .table.Columns}} {{if and $column.IsList (ne $column.HtmlField $.table.TreeCode) (ne $column.HtmlField $.table.TreeParentCode) (ne $column.HtmlField $.table.TreeName) }} {{if eq $column.HtmlType "images" "file" "files"}} {{$column.GoField}} : v.{{$column.GoField}}, @@ -228,6 +260,18 @@ func (s *s{{.table.ClassName}})List(ctx context.Context, req *model.{{.table.Cla {{end}} {{end}} {{end}} + {{if eq $column.HtmlType "userSelectorSingle"}} + Linked{{$column.GoField}} : v.Linked{{$column.GoField}}, + {{end}} + {{if eq $column.HtmlType "userSelectorMultiple"}} + Linked{{$column.GoField}} : linked{{$column.GoField}}, + {{end}} + {{if eq $column.HtmlType "deptSelectorSingle"}} + Linked{{$column.GoField}}: {{if $usedSystemModule}}systemService{{else}}service{{end}}.SysDept().GetByDept(ctx, v.{{$column.GoField}}), + {{end}} + {{if eq $column.HtmlType "deptSelectorMultiple"}} + Linked{{$column.GoField}}: linked{{$column.GoField}}, + {{end}} {{end}} {{else}} {{if not .table.IsPkListable}} @@ -257,6 +301,18 @@ func (s *s{{.table.ClassName}})List(ctx context.Context, req *model.{{.table.Cla {{end}} {{end}} {{end}} + {{if eq $column.HtmlType "userSelectorSingle"}} + Linked{{$column.GoField}} : v.Linked{{$column.GoField}}, + {{end}} + {{if eq $column.HtmlType "userSelectorMultiple"}} + Linked{{$column.GoField}} : linked{{$column.GoField}}, + {{end}} + {{if eq $column.HtmlType "deptSelectorSingle"}} + Linked{{$column.GoField}}: {{if $usedSystemModule}}systemService{{else}}service{{end}}.SysDept().GetByDept(ctx, v.{{$column.GoField}}), + {{end}} + {{if eq $column.HtmlType "deptSelectorMultiple"}} + Linked{{$column.GoField}}: linked{{$column.GoField}}, + {{end}} {{end}} {{end}} } @@ -276,7 +332,19 @@ func (s *s{{.table.ClassName}})GetExportData(ctx context.Context, req *model.{{. m = m.Where(dao.{{$.table.ClassName}}.Columns().{{$column.GoField}}+" like ?", "%"+req.{{$column.GoField}}+"%") } {{else if eq $column.QueryType "EQ"}} - {{if eq $column.GoType "string"}} + {{if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}} + if len(req.{{$column.GoField}}) > 0 { + if systemService.ToolsGenTable().IsMysql() { + for _, v := range req.{{$column.GoField}} { + m = m.Where("JSON_CONTAINS(`{{$column.ColumnName}}`,?)", gconv.String(v)) + } + }else{ + for _, v := range req.{{$column.GoField}} { + m = m.Where(`"{{$column.ColumnName}}" @> '[?]'::jsonb`, v) + } + } + } + {{else if eq $column.GoType "string"}} if req.{{$column.GoField}} != "" { m = m.Where(dao.{{$.table.ClassName}}.Columns().{{$column.GoField}}+" = ?", {{if ne $column.FieldConversion ""}}{{$column.FieldConversion}}({{end}}req.{{$column.GoField}}{{if ne $column.FieldConversion ""}}){{end}}) } @@ -384,7 +452,7 @@ func(s *s{{.table.ClassName}})Import(ctx context.Context,file *ghttp.UploadFile) {{$add = true}} {{else if and $column.IsPk $.table.UseSnowId}} {{$.table.PkColumn.GoField}}:{{$.table.PkColumn.HtmlField}}, - {{else if and (ne $column.IsPk true) (ne $column.HtmlType "imagefile") (ne $column.HtmlType "images") (ne $column.HtmlType "file") (ne $column.HtmlType "files")}} + {{else if and (ne $column.IsPk true) (ne $column.HtmlType "imagefile") (ne $column.HtmlType "images") (ne $column.HtmlType "file") (ne $column.HtmlType "files") (ne $column.HtmlType "imageSelector") (ne $column.HtmlType "fileSelector")}} {{$add = true}} {{if eq $column.GoType "int" "uint" "int64" "uint64" "bool" }} {{$column.GoField}}:gconv.Int64(d[{{$i}}]), @@ -440,13 +508,27 @@ func (s *s{{.table.ClassName}})GetBy{{$pkGoField}}(ctx context.Context, {{$.tabl err =g.Try(ctx, func(ctx context.Context){ err = dao.{{.table.ClassName}}.Ctx(ctx).WithAll().Where(dao.{{.table.ClassName}}.Columns().{{$pkGoField}}, {{$.table.PkColumn.HtmlField}}).Scan(&res) liberr.ErrIsNil(ctx,err,"获取信息失败") - {{if $.table.HasDeptId}} + {{if or $.table.HasDeptId $hasDeptSelector}} if res!=nil{ + {{if $.table.HasDeptId}} {{if $usedSystemModule}} res.DeptInfo = systemService.SysDept().GetByDept(ctx, res.DeptId) {{else}} res.DeptInfo = service.SysDept().GetByDept(ctx, res.DeptId) {{end}} + {{end}} + {{if $hasDeptSelector}} + {{range $index, $column := .table.Columns}} + {{if eq $column.HtmlType "deptSelectorSingle"}} + res.Linked{{$column.GoField}} = {{if $usedSystemModule}}systemService{{else}}service{{end}}.SysDept().GetByDept(ctx, res.{{$column.GoField}}) + {{else if eq $column.HtmlType "deptSelectorMultiple"}} + res.Linked{{$column.GoField}} = make([]*{{if $usedSystemModel}}systemModel{{else}}model{{end}}.LinkDeptRes, len(res.{{$column.GoField}})) + for k, v := range res.{{$column.GoField}} { + res.Linked{{$column.GoField}}[k] = {{if $usedSystemModule}}systemService{{else}}service{{end}}.SysDept().GetByDept(ctx, v) + } + {{end}} + {{end}} + {{end}} } {{end}} {{range $index, $column := .table.Columns}} @@ -480,7 +562,7 @@ func (s *s{{.table.ClassName}})Add(ctx context.Context, req *model.{{.table.Clas if !req.{{$column.GoField}}.IsEmpty(){ {{$column.HtmlField}}=req.{{$column.GoField}}.Join(",") } - {{else if eq $column.HtmlType "images" "file" "files"}} + {{else if eq $column.HtmlType "images" "file" "files" "imageSelector" "fileSelector"}} for _,obj:=range req.{{$column.GoField}}{ obj.Url,err = libUtils.GetFilesPath(ctx,obj.Url) liberr.ErrIsNil(ctx, err) @@ -529,7 +611,7 @@ func (s *s{{.table.ClassName}})Edit(ctx context.Context, req *model.{{.table.Cla if !req.{{$column.GoField}}.IsEmpty(){ {{$column.HtmlField}}=req.{{$column.GoField}}.Join(",") } - {{else if eq $column.HtmlType "images" "file" "files"}} + {{else if eq $column.HtmlType "images" "file" "files" "imageSelector" "fileSelector"}} for _,obj:=range req.{{$column.GoField}}{ obj.Url,err = libUtils.GetFilesPath(ctx,obj.Url) liberr.ErrIsNil(ctx, err) diff --git a/resource/template/vm/go/model.template b/resource/template/vm/go/model.template index 9583d54..2e40fd3 100644 --- a/resource/template/vm/go/model.template +++ b/resource/template/vm/go/model.template @@ -17,10 +17,10 @@ package model {{range $index,$column :=.table.Columns}} - {{if and (eq $column.HtmlField "createdBy" "updatedBy" "deptId") (ne $.table.ModuleName "system")}} + {{if and (or (eq $column.HtmlField "createdBy" "updatedBy" "deptId") (eq $column.HtmlType "userSelectorSingle" "userSelectorMultiple" "deptSelectorMultiple" "deptSelectorSingle")) (ne $.table.ModuleName "system")}} {{$hasUser = true}} {{end}} - {{if eq $column.HtmlType "imagefile" "images" "file" "files" }} + {{if eq $column.HtmlType "imagefile" "images" "file" "files" "imageSelector" "fileSelector"}} {{$hasUpFile = true}} {{end}} {{if eq $column.HtmlType "checkbox" "selects" "treeSelects"}} @@ -28,7 +28,7 @@ package model {{end}} {{end}} {{range $index,$column :=.table.EditColumns}} - {{if and (eq $column.HtmlField "createdBy" "updatedBy" "deptId") (ne $.table.ModuleName "system")}} + {{if and (or (eq $column.HtmlField "createdBy" "updatedBy" "deptId") (eq $column.HtmlType "userSelectorMultiple" "userSelectorSingle" "deptSelectorMultiple" "deptSelectorSingle")) (ne $.table.ModuleName "system")}} {{$hasUser = true}} {{end}} {{if eq $column.GoType "Time"}} @@ -54,7 +54,7 @@ import ( type {{.table.ClassName}}InfoRes struct { gmeta.Meta `orm:"table:{{.table.TableName}}"` {{range $index, $column := .table.Columns}} - {{if $column.IsPk}}{{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else}}{{$column.GoType}}{{end}} `orm:"{{$column.ColumnName}},primary" json:"{{$column.HtmlField}}{{if $.table.UseSnowId}},string{{end}}" dc:"{{$column.ColumnComment}}"` // {{$column.ColumnComment}} {{else}}{{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else}}{{$column.GoType}}{{end}} `orm:"{{$column.ColumnName}}" json:"{{$column.HtmlField}}" dc:"{{$column.ColumnComment}}"` // {{$column.ColumnComment}} {{end}} + {{if $column.IsPk}}{{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{$column.GoType}}{{end}} `orm:"{{$column.ColumnName}},primary" json:"{{$column.HtmlField}}{{if $.table.UseSnowId}},string{{end}}" dc:"{{$column.ColumnComment}}"` // {{$column.ColumnComment}} {{else}}{{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{$column.GoType}}{{end}} `orm:"{{$column.ColumnName}}" json:"{{$column.HtmlField}}" dc:"{{$column.ColumnComment}}"` // {{$column.ColumnComment}} {{end}} {{range $ti, $linkedTable := $.table.LinkedTables}} {{if eq $column.LinkTableClass $linkedTable.ClassName}} Linked{{$column.GoField}} {{if eq $column.HtmlType "selects" "checkbox" "treeSelects"}}[]{{end}}*Linked{{$.table.ClassName}}{{$linkedTable.ClassName}} `{{if not (eq $column.HtmlType "selects" "checkbox" "treeSelects")}}orm:"with:{{$column.LinkLabelId}}={{$column.ColumnName}}" {{end}}json:"linked{{$column.GoField}}"` @@ -69,6 +69,18 @@ type {{.table.ClassName}}InfoRes struct { {{if eq $column.HtmlField "updatedBy"}} UpdatedUser *{{if $hasUser}}systemModel.{{end}}LinkUserRes `orm:"with:id=updated_by" json:"updatedUser"` {{end}} + {{if eq $column.HtmlType "userSelectorSingle"}} + Linked{{$column.GoField}} *{{if $hasUser}}systemModel.{{end}}LinkUserRes `orm:"with:id={{$column.ColumnName}}" json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "userSelectorMultiple"}} + Linked{{$column.GoField}} []*{{if $hasUser}}systemModel.{{end}}LinkUserRes `orm:"with:id={{$column.ColumnName}}" json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "deptSelectorSingle"}} + Linked{{$column.GoField}} *{{if $hasUser}}systemModel.{{end}}LinkDeptRes `json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "deptSelectorMultiple"}} + Linked{{$column.GoField}} []*{{if $hasUser}}systemModel.{{end}}LinkDeptRes `json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} {{end}} } @@ -76,7 +88,7 @@ type {{.table.ClassName}}InfoRes struct { type Linked{{$.table.ClassName}}{{$linkedTable.ClassName}} struct { gmeta.Meta `orm:"table:{{$linkedTable.TableName}}"` {{range $ci, $linkedColumn := $linkedTable.RefColumns.Values}} - {{$linkedColumn.GoField}} {{if eq $linkedColumn.GoType "Time"}}*gtime.Time{{else}}{{$linkedColumn.GoType}}{{end}} `orm:"{{$linkedColumn.ColumnName}}" json:"{{$linkedColumn.HtmlField}}" dc:"{{$linkedColumn.ColumnComment}}"` // {{$linkedColumn.ColumnComment}} + {{$linkedColumn.GoField}} {{if eq $linkedColumn.GoType "Time"}}*gtime.Time{{else if eq $linkedColumn.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{$linkedColumn.GoType}}{{end}} `orm:"{{$linkedColumn.ColumnName}}" json:"{{$linkedColumn.HtmlField}}" dc:"{{$linkedColumn.ColumnComment}}"` // {{$linkedColumn.ColumnComment}} {{end}} {{if eq $linkedTable.TplCategory "tree"}} {{$linkedTable.OptionsStruct.ColumnAttr.GoField}} {{$linkedTable.OptionsStruct.ColumnAttr.GoType}} `orm:"{{$linkedTable.OptionsStruct.ColumnAttr.ColumnName}}" json:"{{$linkedTable.OptionsStruct.ColumnAttr.HtmlField}}"` @@ -90,12 +102,12 @@ type {{.table.ClassName}}ListRes struct{ {{if eq .table.TplCategory "tree"}} {{range $index, $column := .table.Columns}} {{if or (eq $column.HtmlField $.table.TreeCode) (eq $column.HtmlField $.table.TreeParentCode) (eq $column.HtmlField $.table.TreeName) }} - {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else}}{{$column.GoType}}{{end}} `json:"{{$column.HtmlField}}{{if and $column.IsPk $.table.UseSnowId}},string{{end}}" dc:"{{$column.ColumnComment}}"` + {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{$column.GoType}}{{end}} `json:"{{$column.HtmlField}}{{if and $column.IsPk $.table.UseSnowId}},string{{end}}" dc:"{{$column.ColumnComment}}"` {{end}} {{end}} {{range $index, $column := .table.Columns}} {{if and $column.IsList (ne $column.HtmlField $.table.TreeCode) (ne $column.HtmlField $.table.TreeParentCode) (ne $column.HtmlField $.table.TreeName) }} - {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else}}{{$column.GoType}}{{end}} `json:"{{$column.HtmlField}}" dc:"{{$column.ColumnComment}}"` + {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{$column.GoType}}{{end}} `json:"{{$column.HtmlField}}" dc:"{{$column.ColumnComment}}"` {{range $ti, $linkedTable := $.table.LinkedTables}} {{if eq $column.LinkTableClass $linkedTable.ClassName}} Linked{{$column.GoField}} {{if eq $column.HtmlType "selects" "checkbox" "treeSelects"}}[]{{end}}*Linked{{$.table.ClassName}}{{$linkedTable.ClassName}} `{{if not (eq $column.HtmlType "selects" "checkbox" "treeSelects")}}orm:"with:{{$column.LinkLabelId}}={{$column.ColumnName}}" {{end}}json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` @@ -111,6 +123,18 @@ type {{.table.ClassName}}ListRes struct{ UpdatedUser *{{if $hasUser}}systemModel.{{end}}LinkUserRes `orm:"with:id=updated_by" json:"updatedUser"` {{end}} {{end}} + {{if eq $column.HtmlType "userSelectorSingle"}} + Linked{{$column.GoField}} *{{if $hasUser}}systemModel.{{end}}LinkUserRes `orm:"with:id={{$column.ColumnName}}" json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "userSelectorMultiple"}} + Linked{{$column.GoField}} []*{{if $hasUser}}systemModel.{{end}}SysUserSimpleRes `json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "deptSelectorSingle"}} + Linked{{$column.GoField}} *{{if $hasUser}}systemModel.{{end}}LinkDeptRes `json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "deptSelectorMultiple"}} + Linked{{$column.GoField}} []*{{if $hasUser}}systemModel.{{end}}LinkDeptRes `json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} {{end}} {{else}} {{if not .table.IsPkListable }} @@ -126,12 +150,24 @@ type {{.table.ClassName}}ListRes struct{ {{if eq $column.HtmlField "updatedBy"}} UpdatedUser *{{if $hasUser}}systemModel.{{end}}LinkUserRes `orm:"with:id=updated_by" json:"updatedBy"` {{end}} - {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else}}{{$column.GoType}}{{end}} `json:"{{$column.HtmlField}}{{if and $column.IsPk $.table.UseSnowId}},string{{end}}" dc:"{{$column.ColumnComment}}"` + {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{$column.GoType}}{{end}} `json:"{{$column.HtmlField}}{{if and $column.IsPk $.table.UseSnowId}},string{{end}}" dc:"{{$column.ColumnComment}}"` {{range $ti, $linkedTable := $.table.LinkedTables}} {{if eq $column.LinkTableClass $linkedTable.ClassName}} Linked{{$column.GoField}} {{if eq $column.HtmlType "selects" "checkbox" "treeSelects"}}[]{{end}}*Linked{{$.table.ClassName}}{{$linkedTable.ClassName}} `{{if not (eq $column.HtmlType "selects" "checkbox" "treeSelects")}}orm:"with:{{$column.LinkLabelId}}={{$column.ColumnName}}" {{end}}json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` {{end}} {{end}} + {{if eq $column.HtmlType "userSelectorSingle"}} + Linked{{$column.GoField}} *{{if $hasUser}}systemModel.{{end}}LinkUserRes `orm:"with:id={{$column.ColumnName}}" json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "userSelectorMultiple"}} + Linked{{$column.GoField}} []*{{if $hasUser}}systemModel.{{end}}SysUserSimpleRes `json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "deptSelectorSingle"}} + Linked{{$column.GoField}} *{{if $hasUser}}systemModel.{{end}}LinkDeptRes `json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} + {{if eq $column.HtmlType "deptSelectorMultiple"}} + Linked{{$column.GoField}} []*{{if $hasUser}}systemModel.{{end}}LinkDeptRes `json:"linked{{$column.GoField}}" dc:"{{$column.ColumnComment}}"` + {{end}} {{end}} {{end}} } @@ -143,7 +179,7 @@ type {{.table.ClassName}}SearchReq struct { comModel.PageReq {{end}} {{range $index, $column := .table.QueryColumns}} - {{$column.GoField}} {{if eq $column.GoType "Time" "int" "int64" "uint" "uint64" "float" "float64" "bool"}}{{if eq $column.QueryType "BETWEEN"}}[]{{end}}string{{else}}{{if eq $column.QueryType "BETWEEN"}}[]{{end}}{{$column.GoType}}{{end}} `p:"{{$column.HtmlField}}"{{if ne $column.FieldValidation ""}} v:"{{$column.FieldValidation}}"{{end}} dc:"{{$column.ColumnComment}}"` //{{$column.ColumnComment}} + {{$column.GoField}} {{if eq $column.GoType "Time" "int" "int64" "uint" "uint64" "float" "float64" "bool"}}{{if eq $column.QueryType "BETWEEN"}}[]{{end}}string{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{if eq $column.QueryType "BETWEEN"}}[]{{end}}{{$column.GoType}}{{end}} `p:"{{$column.HtmlField}}"{{if ne $column.FieldValidation ""}} v:"{{$column.FieldValidation}}"{{end}} dc:"{{$column.ColumnComment}}"` //{{$column.ColumnComment}} {{end}} } @@ -172,7 +208,7 @@ type {{.table.ClassName}}AddReq struct { {{.table.PkColumn.GoField}} {{.table.PkColumn.GoType}} `p:"{{.table.PkColumn.HtmlField}}" v:"required#主键ID不能为空" dc:"{{.table.PkColumn.ColumnComment}}"` {{end}} {{range $index, $column := .table.EditColumns}} - {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "images" "file" "files"}}[]*comModel.UpFile{{else if eq $column.HtmlType "checkbox" "selects" "treeSelects"}}garray.StrArray{{else}}{{$column.GoType}}{{end}} `p:"{{$column.HtmlField}}" {{if $column.IsRequired}}v:"required#{{$column.ColumnComment}}不能为空"{{end}} dc:"{{$column.ColumnComment}}"` + {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "images" "file" "files" "imageSelector" "fileSelector"}}[]*comModel.UpFile{{else if eq $column.HtmlType "checkbox" "selects" "treeSelects"}}garray.StrArray{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{$column.GoType}}{{end}} `p:"{{$column.HtmlField}}" {{if $column.IsRequired}}v:"required#{{$column.ColumnComment}}不能为空"{{end}} dc:"{{$column.ColumnComment}}"` {{end}} {{if .table.HasCreatedBy}} CreatedBy uint64 @@ -187,7 +223,7 @@ type {{.table.ClassName}}AddReq struct { type {{.table.ClassName}}EditReq struct { {{.table.PkColumn.GoField}} {{.table.PkColumn.GoType}} `p:"{{.table.PkColumn.HtmlField}}" v:"required#主键ID不能为空" dc:"{{.table.PkColumn.ColumnComment}}"` {{range $index, $column := .table.EditColumns}} - {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "images" "file" "files"}}[]*comModel.UpFile{{else if eq $column.HtmlType "checkbox" "selects" "treeSelects"}}garray.StrArray{{else}}{{$column.GoType}}{{end}} `p:"{{$column.HtmlField}}" {{if $column.IsRequired}}v:"required#{{$column.ColumnComment}}不能为空"{{end}} dc:"{{$column.ColumnComment}}"` + {{$column.GoField}} {{if eq $column.GoType "Time"}}*gtime.Time{{else if eq $column.HtmlType "images" "file" "files" "imageSelector" "fileSelector"}}[]*comModel.UpFile{{else if eq $column.HtmlType "checkbox" "selects" "treeSelects"}}garray.StrArray{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}[]uint64{{else}}{{$column.GoType}}{{end}} `p:"{{$column.HtmlField}}" {{if $column.IsRequired}}v:"required#{{$column.ColumnComment}}不能为空"{{end}} dc:"{{$column.ColumnComment}}"` {{end}} {{if .table.HasUpdatedBy}} UpdatedBy uint64 diff --git a/resource/template/vm/ts/model.template b/resource/template/vm/ts/model.template index 9108426..a360051 100644 --- a/resource/template/vm/ts/model.template +++ b/resource/template/vm/ts/model.template @@ -7,7 +7,7 @@ export interface {{.table.ClassName}}TableColumns { {{end}} {{range $index, $column := .table.Columns}} {{if and $column.IsList (ne $column.HtmlField $.table.TreeCode) (ne $column.HtmlField $.table.TreeParentCode) (ne $column.HtmlField $.table.TreeName) }} - {{$column.HtmlField}}:{{if and (eq $column.HtmlType "images" "file" "files" "checkbox" "selects" "treeSelects") (eq $column.DictType "")}}any[]{{else}}{{$column.TsType}}{{end}}; // {{$column.ColumnComment}} + {{$column.HtmlField}}:{{if and (eq $column.HtmlType "images" "file" "files" "checkbox" "selects" "treeSelects" "imageSelector" "fileSelector") (eq $column.DictType "")}}any[]{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}number[]{{else}}{{$column.TsType}}{{end}}; // {{$column.ColumnComment}} {{end}} {{range $ti, $linkedTable := $.table.LinkedTables}} {{if eq $column.LinkTableClass $linkedTable.ClassName}} @@ -23,7 +23,7 @@ export interface {{.table.ClassName}}TableColumns { {{if eq $column.HtmlField "createdBy" "updatedBy"}} {{$column.HtmlField}}:string; // {{$column.ColumnComment}} {{else}} - {{$column.HtmlField}}:{{if and (eq $column.HtmlType "images" "file" "files" "checkbox" "selects" "treeSelects") (eq $column.DictType "")}}any[]{{else}}{{$column.TsType}}{{end}}; // {{$column.ColumnComment}} + {{$column.HtmlField}}:{{if and (eq $column.HtmlType "images" "file" "files" "checkbox" "selects" "treeSelects" "imageSelector" "fileSelector") (eq $column.DictType "")}}any[]{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}number[]{{else}}{{$column.TsType}}{{end}}; // {{$column.ColumnComment}} {{end}} {{range $ti, $linkedTable := $.table.LinkedTables}} {{if eq $column.LinkTableClass $linkedTable.ClassName}} @@ -40,12 +40,24 @@ export interface {{.table.ClassName}}TableColumns { //// export interface {{.table.ClassName}}InfoData { {{range $index, $column := .table.Columns}} - {{if $column.IsPk}}{{$column.HtmlField}}:{{if eq $column.HtmlType "images" "file" "files" "checkbox" "selects" "treeSelects"}}any[]{{else if eq $column.HtmlType "switch"}}boolean{{else if eq $column.HtmlType "keyValue"}}{key:string,value:any}[]{{else}}{{$column.TsType}}|undefined{{end}}; // {{$column.ColumnComment}} {{else}}{{$column.HtmlField}}:{{if eq $column.HtmlType "images" "file" "files" "checkbox" "selects" "treeSelects"}}any[]{{else if eq $column.HtmlType "switch"}}boolean{{else if eq $column.HtmlType "keyValue"}}{key:string,value:any}[]{{else}}{{$column.TsType}}|undefined{{end}}; // {{$column.ColumnComment}} {{end}} + {{if $column.IsPk}}{{$column.HtmlField}}:{{if eq $column.HtmlType "images" "file" "files" "checkbox" "selects" "treeSelects" "imageSelector" "fileSelector"}}any[]{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}number[]{{else if eq $column.HtmlType "switch"}}boolean{{else if eq $column.HtmlType "keyValue"}}{key:string,value:any}[]{{else}}{{$column.TsType}}|undefined{{end}}; // {{$column.ColumnComment}} {{else}}{{$column.HtmlField}}:{{if eq $column.HtmlType "images" "file" "files" "checkbox" "selects" "treeSelects" "imageSelector" "fileSelector"}}any[]{{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}number[]{{else if eq $column.HtmlType "switch"}}boolean{{else if eq $column.HtmlType "keyValue"}}{key:string,value:any}[]{{else}}{{$column.TsType}}|undefined{{end}}; // {{$column.ColumnComment}} {{end}} {{range $ti, $linkedTable := $.table.LinkedTables}} {{if eq $column.LinkTableClass $linkedTable.ClassName}} linked{{$column.GoField}}?:Linked{{$.table.ClassName}}{{$linkedTable.ClassName}}{{if eq $column.HtmlType "checkbox" "selects" "treeSelects"}}[]{{end}}; // {{$column.ColumnComment}} {{end}} {{end}} + {{if eq $column.HtmlType "userSelectorSingle"}} + linked{{$column.GoField}} : LinkedUserData|null; + {{end}} + {{if eq $column.HtmlType "userSelectorMultiple"}} + linked{{$column.GoField}} : LinkedUserData[]; + {{end}} + {{if eq $column.HtmlType "deptSelectorSingle"}} + linked{{$column.GoField}} : LinkedDeptData|null; + {{end}} + {{if eq $column.HtmlType "deptSelectorMultiple"}} + linked{{$column.GoField}} : LinkedDeptData[]; + {{end}} {{end}} {{range $ti, $linkedTable := .table.LinkedTables}} linked{{$.table.ClassName}}{{$linkedTable.ClassName}}?:Linked{{$.table.ClassName}}{{$linkedTable.ClassName}}; @@ -56,7 +68,7 @@ export interface {{.table.ClassName}}InfoData { //// export interface Linked{{$.table.ClassName}}{{$linkedTable.ClassName}} { {{range $ci, $linkedColumn := $linkedTable.RefColumns.Values}} - {{$linkedColumn.HtmlField}}:{{if eq $linkedColumn.HtmlType "images" "file" "files"}}any[]{{else}}{{$linkedColumn.TsType}}|undefined{{end}}; // {{$linkedColumn.ColumnComment}} + {{$linkedColumn.HtmlField}}:{{if eq $linkedColumn.HtmlType "images" "file" "files" "imageSelector" "fileSelector"}}any[]{{else if eq $linkedColumn.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}}number[]{{else}}{{$linkedColumn.TsType}}|undefined{{end}}; // {{$linkedColumn.ColumnComment}} {{end}} } {{end}} @@ -74,6 +86,8 @@ export interface {{.table.ClassName}}TableDataState { {{range $index, $column := .table.QueryColumns}} {{if eq $column.QueryType "BETWEEN"}} {{$column.HtmlField}}: {{$column.TsType}}[]; + {{else if eq $column.HtmlType "userSelectorMultiple" "deptSelectorMultiple"}} + {{$column.HtmlField}}: number[]; {{else}} {{$column.HtmlField}}: {{$column.TsType}}|undefined; {{end}}{{end}} @@ -82,6 +96,31 @@ export interface {{.table.ClassName}}TableDataState { }; } +{{$hasUserSelector := false}} +{{$hasDeptSelector := false}} +{{range $index, $column := .table.Columns}} + {{if eq $column.HtmlType "userSelectorMultiple" "userSelectorSingle"}} + {{$hasUserSelector = true}} + {{end}} + {{if eq $column.HtmlType "deptSelectorMultiple" "deptSelectorSingle"}} + {{$hasDeptSelector = true}} + {{end}} +{{end}} +{{if $hasUserSelector}} +//// +export interface LinkedDeptData { + deptId:number; + deptName:string; +} +{{end}} +{{if $hasDeptSelector}} +//// +export interface LinkedUserData { + id:number; + userNickname:string; +} +{{end}} + //// export interface {{.table.ClassName}}EditState{ loading:boolean; diff --git a/resource/template/vm/vue/detail-vue.template b/resource/template/vm/vue/detail-vue.template index 760d382..a3463af 100644 --- a/resource/template/vm/vue/detail-vue.template +++ b/resource/template/vm/vue/detail-vue.template @@ -154,6 +154,69 @@ :href="proxy.getUpFileUrl(item.url)" target="_blank">{{"{{"}}item.name{{"}}"}} + {{else if eq $column.HtmlType "imageSelector"}} + + +

+ +
+ + {{else if eq $column.HtmlType "fileSelector"}} + + +
+ {{"{{"}}item.name{{"}}"}} +
+
+ {{else if eq $column.HtmlType "userSelectorSingle"}} + + + {{"{{"}} formData.linked{{$column.GoField}}?formData.linked{{$column.GoField}}.userNickname:'' {{"}}"}} + + {{else if eq $column.HtmlType "deptSelectorSingle"}} + + + {{"{{"}} formData.linked{{$column.GoField}}?formData.linked{{$column.GoField}}.deptName:'' {{"}}"}} + + {{else if eq $column.HtmlType "userSelectorMultiple"}} + + + {{"{{"}} formData.linked{{$column.GoField}}?formData.linked{{$column.GoField}}.map((res:any)=>{return res.userNickname}).join(','):'' {{"}}"}} + + {{else if eq $column.HtmlType "deptSelectorMultiple"}} + + + {{"{{"}} formData.linked{{$column.GoField}}?formData.linked{{$column.GoField}}.map((res:any)=>{return res.deptName}).join(','):'' {{"}}"}} + {{else if eq $column.HtmlType "keyValue"}}