update
This commit is contained in:
@@ -18,6 +18,7 @@ import (
|
||||
"portal-mini-go/internal/pkg/errors"
|
||||
"portal-mini-go/internal/pkg/storage"
|
||||
"portal-mini-go/internal/pkg/types"
|
||||
"portal-mini-go/internal/repository/file"
|
||||
)
|
||||
|
||||
// 文件相关业务错误(业务码沿用现有 40xxx/41xxx/50xxx 段)。
|
||||
@@ -31,6 +32,7 @@ type FileRepository interface {
|
||||
Create(ctx context.Context, f *model.File) error
|
||||
GetByID(ctx context.Context, id uint64) (*model.File, error)
|
||||
Delete(ctx context.Context, id uint64) error
|
||||
List(ctx context.Context, filter file.ListFilter) ([]model.File, int64, error)
|
||||
}
|
||||
|
||||
// Service 文件上传业务服务。
|
||||
@@ -114,6 +116,33 @@ func (s *Service) Get(ctx context.Context, id uint64) (*model.File, error) {
|
||||
return s.repo.GetByID(ctx, id)
|
||||
}
|
||||
|
||||
// ListReq 文件列表查询条件。
|
||||
type ListReq struct {
|
||||
UploaderType string // 上传者类型(admin/ma),空表示不限
|
||||
UploaderID uint64 // 上传者主键,0 表示不限
|
||||
Keyword string // 模糊匹配 origin_name 或 filename
|
||||
Page int // 页码,从 1 开始
|
||||
Size int // 每页条数
|
||||
}
|
||||
|
||||
// List 分页查询文件,缺省第 1 页、每页 20 条。
|
||||
func (s *Service) List(ctx context.Context, req ListReq) ([]model.File, int64, error) {
|
||||
page, size := req.Page, req.Size
|
||||
if page <= 0 {
|
||||
page = 1
|
||||
}
|
||||
if size <= 0 {
|
||||
size = 20
|
||||
}
|
||||
return s.repo.List(ctx, file.ListFilter{
|
||||
UploaderType: req.UploaderType,
|
||||
UploaderID: req.UploaderID,
|
||||
Keyword: req.Keyword,
|
||||
Page: page,
|
||||
Size: size,
|
||||
})
|
||||
}
|
||||
|
||||
// Download 返回文件读取流与元数据;调用方负责关闭流。
|
||||
func (s *Service) Download(ctx context.Context, id uint64) (io.ReadCloser, *model.File, error) {
|
||||
f, err := s.repo.GetByID(ctx, id)
|
||||
|
||||
@@ -12,16 +12,17 @@ import (
|
||||
"portal-mini-go/internal/model"
|
||||
"portal-mini-go/internal/pkg/config"
|
||||
"portal-mini-go/internal/pkg/storage"
|
||||
"portal-mini-go/internal/repository/file"
|
||||
filesvc "portal-mini-go/internal/service/file"
|
||||
)
|
||||
|
||||
// --- 测试替身 ---
|
||||
|
||||
type fakeStorage struct {
|
||||
putErr error
|
||||
gotKey string
|
||||
putErr error
|
||||
gotKey string
|
||||
gotSize int64
|
||||
data map[string][]byte
|
||||
data map[string][]byte
|
||||
}
|
||||
|
||||
func newFakeStorage() *fakeStorage { return &fakeStorage{data: map[string][]byte{}} }
|
||||
@@ -50,12 +51,16 @@ func (s *fakeStorage) Delete(_ context.Context, key string) error {
|
||||
func (s *fakeStorage) URL(key string) string { return "/files/static/" + key }
|
||||
|
||||
type fakeRepo struct {
|
||||
created *model.File
|
||||
byID *model.File
|
||||
getErr error
|
||||
createErr error
|
||||
delErr error
|
||||
deletedID uint64
|
||||
created *model.File
|
||||
byID *model.File
|
||||
getErr error
|
||||
createErr error
|
||||
delErr error
|
||||
deletedID uint64
|
||||
listed []model.File
|
||||
listTotal int64
|
||||
listErr error
|
||||
listFilter file.ListFilter
|
||||
}
|
||||
|
||||
func (r *fakeRepo) Create(_ context.Context, f *model.File) error { r.created = f; return r.createErr }
|
||||
@@ -66,11 +71,18 @@ func (r *fakeRepo) GetByID(_ context.Context, id uint64) (*model.File, error) {
|
||||
return r.byID, nil
|
||||
}
|
||||
func (r *fakeRepo) Delete(_ context.Context, id uint64) error { r.deletedID = id; return r.delErr }
|
||||
func (r *fakeRepo) List(_ context.Context, f file.ListFilter) ([]model.File, int64, error) {
|
||||
r.listFilter = f
|
||||
if r.listErr != nil {
|
||||
return nil, 0, r.listErr
|
||||
}
|
||||
return r.listed, r.listTotal, nil
|
||||
}
|
||||
|
||||
// 编译期接口断言。
|
||||
var (
|
||||
_ filesvc.FileRepository = (*fakeRepo)(nil)
|
||||
_ storage.Storage = (*fakeStorage)(nil)
|
||||
_ storage.Storage = (*fakeStorage)(nil)
|
||||
)
|
||||
|
||||
func newSvc(cfg config.UploadConfig, store *fakeStorage, repo *fakeRepo) *filesvc.Service {
|
||||
@@ -192,3 +204,27 @@ func TestDelete(t *testing.T) {
|
||||
require.Equal(t, uint64(9), repo.deletedID)
|
||||
require.Empty(t, store.data)
|
||||
}
|
||||
|
||||
func TestList(t *testing.T) {
|
||||
want := []model.File{{ID: 1, OriginName: "a.png"}, {ID: 2, OriginName: "b.jpg"}}
|
||||
repo := &fakeRepo{listed: want, listTotal: 2}
|
||||
svc := newSvc(config.UploadConfig{}, newFakeStorage(), repo)
|
||||
|
||||
got, total, err := svc.List(context.Background(), filesvc.ListReq{Keyword: "png", Page: 2, Size: 15})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, int64(2), total)
|
||||
require.Equal(t, want, got)
|
||||
require.Equal(t, "png", repo.listFilter.Keyword)
|
||||
require.Equal(t, 2, repo.listFilter.Page)
|
||||
require.Equal(t, 15, repo.listFilter.Size)
|
||||
}
|
||||
|
||||
func TestList_Defaults(t *testing.T) {
|
||||
repo := &fakeRepo{listed: nil, listTotal: 0}
|
||||
svc := newSvc(config.UploadConfig{}, newFakeStorage(), repo)
|
||||
|
||||
_, _, err := svc.List(context.Background(), filesvc.ListReq{})
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, 1, repo.listFilter.Page, "缺省页码应为 1")
|
||||
require.Equal(t, 20, repo.listFilter.Size, "缺省每页应为 20")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user