package service import ( "context" "errors" "fmt" "net/url" "octopus/internal/dal" "octopus/internal/dal/model" "octopus/internal/dal/query" "octopus/internal/schema" "time" "github.com/casdoor/casdoor-go-sdk/casdoorsdk" "github.com/rs/xid" "gorm.io/gen/field" "gorm.io/gorm" ) func ListDocs(ctx context.Context, auth *casdoorsdk.User, param *schema.ListDocQuery) ([]*model.Doc, int64, error) { base := query.Doc. Where(query.Doc.OrgID.Eq(auth.Owner)). Preload(query.Doc.Folder) if param.FolderIDs != nil { base = base.Where(query.Doc.FolderID.In(*param.FolderIDs...)) } if orders := param.GetOrderByFields(query.Doc); len(orders) != 0 { base = base.Order(orders...) } return base.FindByPage(param.GetOffset(), param.GetLimit()) } func CreateDoc(ctx context.Context, auth *casdoorsdk.User, param *schema.CreateDoc) (*model.Doc, error) { storage := dal.GetStorage() // 检查oss对象 stat, exists, err := storage.ObjectStats(ctx, param.ObjectName) if err != nil { return nil, fmt.Errorf("failed to get object stats: %w", err) } if !exists { return nil, fmt.Errorf("object not exists") } // 检查文件夹 folder, err := GetDocFolder(ctx, auth, param.FolderID) if err != nil { return nil, err } // 将对象从临时地址移动到新地址 newObjectName := fmt.Sprintf("%s/%s/%s", auth.Owner, time.Now().UTC().Format(time.DateOnly), param.Name) if err := storage.MoveObject(ctx, param.ObjectName, newObjectName); err != nil { return nil, fmt.Errorf("failed to move object: %w", err) } doc := model.Doc{ Base: model.Base{OrgID: auth.Owner}, Name: param.Name, IsDeletable: true, IsEditable: true, FolderID: param.FolderID, ObjectName: newObjectName, UploadedAt: stat.LastModified, CreatedBy: auth.Id, Folder: folder, } if err := query.Doc.Create(&doc); err != nil { return nil, fmt.Errorf("failed to create doc: %w", err) } return &doc, nil } func GetDoc(ctx context.Context, auth *casdoorsdk.User, id string) (*model.Doc, error) { doc, err := query.Doc. Where( query.Doc.OrgID.Eq(auth.Owner), query.Doc.ID.Eq(id), ). Preload(query.Doc.Folder). Take() if errors.Is(err, gorm.ErrRecordNotFound) { return nil, fmt.Errorf("specified doc not exists") } if err != nil { return nil, err } return doc, nil } func UpdateDoc(ctx context.Context, auth *casdoorsdk.User, id string, body *schema.UpdateDoc) (*model.Doc, error) { if _, err := GetDoc(ctx, auth, id); err != nil { return nil, fmt.Errorf("failed to get doc: %w", err) } var updates []field.AssignExpr if body.Name != nil { updates = append(updates, query.Doc.Name.Value(*body.Name)) } if body.FolderID != nil { if _, err := GetDocFolder(ctx, auth, *body.FolderID); err != nil { return nil, fmt.Errorf("failed to get doc folder: %w", err) } updates = append(updates, query.Doc.FolderID.Value(*body.FolderID)) } if _, err := query.Doc.UpdateColumnSimple(updates...); err != nil { return nil, fmt.Errorf("failed to update doc: %w", err) } return GetDoc(ctx, auth, id) } func DeleteDoc(ctx context.Context, auth *casdoorsdk.User, id string) error { doc, err := GetDoc(ctx, auth, id) if err != nil { return fmt.Errorf("failed to get doc: %w", err) } if err := dal.GetStorage().DeleteObject(ctx, doc.ObjectName); err != nil { return fmt.Errorf("failed to delete object: %w", err) } _, err = query.Doc.Where(query.Doc.OrgID.Eq(auth.Owner), query.Doc.ID.Eq(id)).Delete() if err != nil { return fmt.Errorf("failed to delete doc: %w", err) } return nil } func DeleteDocBatch(ctx context.Context, auth *casdoorsdk.User, param *schema.DocsBatchDelete) *schema.DocBatchResults { results := make(schema.DocBatchResults, 0, len(param.IDs)) // NOTE: 后面应该需要优化一下 for _, docID := range param.IDs { err := DeleteDoc(ctx, auth, docID) if err != nil { results = append(results, schema.DocBatchResult{ID: docID, Success: false, Error: err.Error()}) } else { results = append(results, schema.DocBatchResult{ID: docID, Success: true}) } } return &results } func UpdateDocBatch(ctx context.Context, auth *casdoorsdk.User, param *schema.DocsBatchUpdate) *schema.DocBatchResults { results := make(schema.DocBatchResults, 0, len(param.IDs)) // NOTE: 后面应该需要优化一下 for _, docID := range param.IDs { _, err := UpdateDoc(ctx, auth, docID, &schema.UpdateDoc{FolderID: param.FolderID}) if err != nil { results = append(results, schema.DocBatchResult{ID: docID, Success: false, Error: err.Error()}) } else { results = append(results, schema.DocBatchResult{ID: docID, Success: true}) } } return &results } func CreateUploadURL(ctx context.Context, auth *casdoorsdk.User, param *schema.CreateUploadURL) (u *url.URL, objectName string, err error) { tmpObjectName := fmt.Sprintf("/tmp/%s/%s-%s", auth.Owner, xid.New(), param.FileName) u, err = dal.GetStorage().PresignedPutObject(ctx, tmpObjectName, time.Hour) if err != nil { return nil, "", fmt.Errorf("failed to create presigned url: %w", err) } return u, tmpObjectName, nil }