feat: docs api design
This commit is contained in:
106
internal/schema/base.go
Normal file
106
internal/schema/base.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package schema
|
||||
|
||||
const (
|
||||
maxPageSize = 1000
|
||||
defaultPageSize = 10
|
||||
)
|
||||
|
||||
type PageableQuery struct {
|
||||
Size *int `query:"size" oai:"description=返回数据数量;default=10;maximum=1000"`
|
||||
Offset *int `query:"offset" oai:"description=数据偏移量;default=0"`
|
||||
}
|
||||
|
||||
func (p *PageableQuery) GetLimit() int {
|
||||
if p.Size == nil {
|
||||
return defaultPageSize
|
||||
}
|
||||
if *p.Size >= maxPageSize {
|
||||
return maxPageSize
|
||||
}
|
||||
return *p.Size
|
||||
}
|
||||
|
||||
func (p *PageableQuery) GetOffset() int {
|
||||
if p.Offset == nil {
|
||||
return 0
|
||||
}
|
||||
return *p.Offset
|
||||
}
|
||||
|
||||
type SortField struct {
|
||||
Field string
|
||||
Asc bool
|
||||
}
|
||||
type SortableQuery struct {
|
||||
SortBy *[]string `query:"sort_by" oai:"description=排序字段, 如: +id,-created_at,test 表示依次按照id正序,created_at倒序,test正序"`
|
||||
}
|
||||
|
||||
func (s *SortableQuery) GetOrderField() []SortField {
|
||||
if s.SortBy == nil {
|
||||
return nil
|
||||
}
|
||||
fields := make([]SortField, 0, len(*s.SortBy))
|
||||
for _, v := range *s.SortBy {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
switch v[0] {
|
||||
case '+':
|
||||
fields = append(fields, SortField{Field: v[1:], Asc: true})
|
||||
case '-':
|
||||
fields = append(fields, SortField{Field: v[1:], Asc: false})
|
||||
default:
|
||||
fields = append(fields, SortField{Field: v, Asc: true})
|
||||
}
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
type SortableBody struct {
|
||||
SortBy *[]string `json:"sort_by" oai:"description=排序字段, 如: id desc/asc"`
|
||||
}
|
||||
|
||||
func (s *SortableBody) GetOrderField() []SortField {
|
||||
if s.SortBy == nil {
|
||||
return nil
|
||||
}
|
||||
fields := make([]SortField, 0, len(*s.SortBy))
|
||||
for _, v := range *s.SortBy {
|
||||
if v == "" {
|
||||
continue
|
||||
}
|
||||
switch v[0] {
|
||||
case '+':
|
||||
fields = append(fields, SortField{Field: v[1:], Asc: true})
|
||||
case '-':
|
||||
fields = append(fields, SortField{Field: v[1:], Asc: false})
|
||||
default:
|
||||
fields = append(fields, SortField{Field: v, Asc: true})
|
||||
}
|
||||
}
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
type PageableBody struct {
|
||||
Size *int `json:"size" oai:"description=返回数据数量;default=10;maximum=1000"`
|
||||
Offset *int `json:"offset" oai:"description=数据偏移量;default=0"`
|
||||
}
|
||||
|
||||
func (p *PageableBody) GetLimit() int {
|
||||
if p.Size == nil {
|
||||
return defaultPageSize
|
||||
}
|
||||
if *p.Size >= maxPageSize {
|
||||
return maxPageSize
|
||||
}
|
||||
return *p.Size
|
||||
}
|
||||
|
||||
func (p *PageableBody) GetOffset() int {
|
||||
if p.Offset == nil {
|
||||
return 0
|
||||
}
|
||||
return *p.Offset
|
||||
}
|
||||
106
internal/schema/docs.go
Normal file
106
internal/schema/docs.go
Normal file
@@ -0,0 +1,106 @@
|
||||
package schema
|
||||
|
||||
import (
|
||||
"octopus/pkg/tools"
|
||||
"time"
|
||||
|
||||
"github.com/gofiber/fiber/v2"
|
||||
)
|
||||
|
||||
type DocFolder struct {
|
||||
ID string `json:"id" oai:"description=文件夹ID"`
|
||||
IsDeletable bool `json:"is_deletable" oai:"description=文件夹是否允许被删除"`
|
||||
IsEditable bool `json:"is_editable" oai:"description=文件夹是否允许被修改"`
|
||||
CreatedAt time.Time `json:"created_at" oai:"description=创建时间"`
|
||||
UpdatedAt time.Time `json:"updated_at" oai:"description=更新时间"`
|
||||
}
|
||||
|
||||
type DocFolderID struct {
|
||||
ID string `path:"id" oai:"description=文件夹ID"`
|
||||
}
|
||||
|
||||
type CreateDocFolder struct {
|
||||
Name string `json:"name" validate:"required" oai:"description=文件夹名称"`
|
||||
ParentID string `json:"parent_id" oai:"description=父文件夹ID,空表示在根路径创建"`
|
||||
}
|
||||
|
||||
type UpdateDocFolder struct {
|
||||
Name *string `json:"name" oai:"description=修改文件夹名称"`
|
||||
ParentID *string `json:"parent_id" oai:"description=修改文件夹父级ID"`
|
||||
}
|
||||
|
||||
type GetDocFolderTree struct {
|
||||
ParentID *string `query:"parent_id" oai:"description=父文件夹ID,空表示获取根路径"`
|
||||
}
|
||||
|
||||
type DocFolderWithChildren struct {
|
||||
ID string `json:"id" oai:"description=文件夹ID,**根文件夹无ID**"`
|
||||
IsDeletable bool `json:"is_deletable" oai:"description=文件夹是否允许被删除"`
|
||||
IsEditable bool `json:"is_editable" oai:"description=文件夹是否允许被修改"`
|
||||
CreatedAt time.Time `json:"created_at" oai:"description=创建时间"`
|
||||
UpdatedAt time.Time `json:"updated_at" oai:"description=更新时间"`
|
||||
Children []*DocFolderWithChildren `json:"children" oai:"description=子文件夹"`
|
||||
}
|
||||
|
||||
type Doc struct {
|
||||
ID string `json:"id" oai:"description=文档ID"`
|
||||
Folder DocFolder `json:"folder" oai:"description=归属文件夹信息"`
|
||||
PresignedURL string `json:"presigned_url" oai:"description=文档预签名下载URL(临时下载URL)"`
|
||||
IsDeletable bool `json:"is_deletable" oai:"description=文件夹是否允许被删除"`
|
||||
IsEditable bool `json:"is_editable" oai:"description=文件夹是否允许被修改"`
|
||||
UploadedAt time.Time `json:"uploaded_at" oai:"description=上传时间"`
|
||||
CreatedAt time.Time `json:"created_at" oai:"description=创建时间"`
|
||||
UpdatedAt time.Time `json:"updated_at" oai:"description=更新时间"`
|
||||
}
|
||||
|
||||
type DocList struct {
|
||||
Items []*Doc `json:"items" oai:"description=文档列表"`
|
||||
Total int64 `json:"total" oai:"description=文档总数"`
|
||||
}
|
||||
|
||||
type DocID struct {
|
||||
ID string `path:"id" oai:"description=文档ID"`
|
||||
}
|
||||
|
||||
type CreateDoc struct {
|
||||
Name string `json:"name" validate:"required" oai:"description=文档名称"`
|
||||
FolderID string `json:"folder_id" validate:"required" oai:"description=归属文件夹ID"`
|
||||
}
|
||||
|
||||
type UpdateDoc struct {
|
||||
Name *string `json:"name" oai:"description=更新文档名称"`
|
||||
FolderID *string `json:"folder_id" oai:"description=更新归属文件夹ID"`
|
||||
}
|
||||
|
||||
type ListDocQuery struct {
|
||||
PageableQuery
|
||||
SortableQuery
|
||||
FolderIDs *[]string `query:"folder_ids" validate:"required" oai:"description=归属文件夹ID"`
|
||||
}
|
||||
|
||||
type DocsBatchDelete struct {
|
||||
IDs []string `query:"ids" validate:"required" oai:"description=批量选择文件ID列表"`
|
||||
FolderID string ` validate:"required" oai:"description=更新归属文件夹ID" json:"folder_id"`
|
||||
}
|
||||
|
||||
type DocsBatchUpdate struct {
|
||||
IDs []string `query:"ids" validate:"required" oai:"description=批量选择文件ID列表"`
|
||||
}
|
||||
|
||||
type DocActionResult struct {
|
||||
ID string `json:"id" oai:"description=文档ID"`
|
||||
Success bool `json:"success" oai:"description=操作是否成功"`
|
||||
Message *string `json:"message,omitempty" oai:"description=操作失败信息"`
|
||||
}
|
||||
|
||||
type DocsBatchResults []DocActionResult
|
||||
|
||||
func (q *ListDocQuery) Validate() error {
|
||||
sortable := tools.NewSet("uploaded_at")
|
||||
for _, s := range q.GetOrderField() {
|
||||
if !sortable.Has(s.Field) {
|
||||
return fiber.NewError(fiber.StatusBadRequest, "unsupported order field")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user