后端重构

This commit is contained in:
Yvan
2026-01-08 19:28:58 +08:00
parent 8800c069d9
commit 9cb6b965e0
49 changed files with 4907 additions and 14 deletions
@@ -0,0 +1,85 @@
package example
import (
"context"
"errors"
"time"
)
// AttachmentCategory 附件分类实体
type AttachmentCategory struct {
ID uint
Name string
Pid uint
Children []*AttachmentCategory
CreatedAt time.Time
UpdatedAt time.Time
}
// AttachmentCategoryRepo 附件分类仓储接口
type AttachmentCategoryRepo interface {
Create(ctx context.Context, category *AttachmentCategory) error
Update(ctx context.Context, category *AttachmentCategory) error
Delete(ctx context.Context, id uint) error
FindByID(ctx context.Context, id uint) (*AttachmentCategory, error)
FindByNameAndPid(ctx context.Context, name string, pid uint) (*AttachmentCategory, error)
FindAll(ctx context.Context) ([]*AttachmentCategory, error)
HasChildren(ctx context.Context, id uint) (bool, error)
}
// AttachmentCategoryUsecase 附件分类用例
type AttachmentCategoryUsecase struct {
repo AttachmentCategoryRepo
}
// NewAttachmentCategoryUsecase 创建附件分类用例
func NewAttachmentCategoryUsecase(repo AttachmentCategoryRepo) *AttachmentCategoryUsecase {
return &AttachmentCategoryUsecase{repo: repo}
}
// AddCategory 创建/更新分类
func (uc *AttachmentCategoryUsecase) AddCategory(ctx context.Context, category *AttachmentCategory) error {
// 检查是否已存在相同名称的分类
existing, _ := uc.repo.FindByNameAndPid(ctx, category.Name, category.Pid)
if existing != nil && existing.ID != category.ID {
return errors.New("分类名称已存在")
}
if category.ID > 0 {
return uc.repo.Update(ctx, category)
}
return uc.repo.Create(ctx, category)
}
// DeleteCategory 删除分类
func (uc *AttachmentCategoryUsecase) DeleteCategory(ctx context.Context, id uint) error {
hasChildren, err := uc.repo.HasChildren(ctx, id)
if err != nil {
return err
}
if hasChildren {
return errors.New("请先删除子级")
}
return uc.repo.Delete(ctx, id)
}
// GetCategoryList 获取分类列表(树形)
func (uc *AttachmentCategoryUsecase) GetCategoryList(ctx context.Context) ([]*AttachmentCategory, error) {
categories, err := uc.repo.FindAll(ctx)
if err != nil {
return nil, err
}
return uc.buildTree(categories, 0), nil
}
// buildTree 构建树形结构
func (uc *AttachmentCategoryUsecase) buildTree(categories []*AttachmentCategory, parentID uint) []*AttachmentCategory {
var tree []*AttachmentCategory
for _, category := range categories {
if category.Pid == parentID {
category.Children = uc.buildTree(categories, category.ID)
tree = append(tree, category)
}
}
return tree
}
+87
View File
@@ -0,0 +1,87 @@
package example
import (
"context"
"time"
)
// Customer 客户实体
type Customer struct {
ID uint
CustomerName string
CustomerPhoneData string
SysUserID uint
SysUserAuthorityID uint
SysUserName string // 关联用户名
CreatedAt time.Time
UpdatedAt time.Time
}
// CustomerSearchReq 客户搜索请求
type CustomerSearchReq struct {
Page int
PageSize int
}
// CustomerRepo 客户仓储接口
type CustomerRepo interface {
Create(ctx context.Context, customer *Customer) error
Update(ctx context.Context, customer *Customer) error
Delete(ctx context.Context, id uint) error
FindByID(ctx context.Context, id uint) (*Customer, error)
List(ctx context.Context, authorityIds []uint, page, pageSize int) ([]*Customer, int64, error)
}
// DataAuthorityProvider 数据权限提供者接口
type DataAuthorityProvider interface {
GetDataAuthorityIds(ctx context.Context, authorityId uint) ([]uint, error)
}
// SimpleDataAuthorityProvider 简单数据权限提供者(返回自身ID)
type SimpleDataAuthorityProvider struct{}
func (s *SimpleDataAuthorityProvider) GetDataAuthorityIds(ctx context.Context, authorityId uint) ([]uint, error) {
return []uint{authorityId}, nil
}
// CustomerUsecase 客户用例
type CustomerUsecase struct {
repo CustomerRepo
authProvider DataAuthorityProvider
}
// NewCustomerUsecase 创建客户用例
func NewCustomerUsecase(repo CustomerRepo, authProvider DataAuthorityProvider) *CustomerUsecase {
return &CustomerUsecase{repo: repo, authProvider: authProvider}
}
// CreateExaCustomer 创建客户
func (uc *CustomerUsecase) CreateExaCustomer(ctx context.Context, customer *Customer) error {
return uc.repo.Create(ctx, customer)
}
// DeleteExaCustomer 删除客户
func (uc *CustomerUsecase) DeleteExaCustomer(ctx context.Context, id uint) error {
return uc.repo.Delete(ctx, id)
}
// UpdateExaCustomer 更新客户
func (uc *CustomerUsecase) UpdateExaCustomer(ctx context.Context, customer *Customer) error {
return uc.repo.Update(ctx, customer)
}
// GetExaCustomer 获取客户信息
func (uc *CustomerUsecase) GetExaCustomer(ctx context.Context, id uint) (*Customer, error) {
return uc.repo.FindByID(ctx, id)
}
// GetCustomerInfoList 分页获取客户列表
func (uc *CustomerUsecase) GetCustomerInfoList(ctx context.Context, authorityId uint, page, pageSize int) ([]*Customer, int64, error) {
// 获取数据权限ID列表
dataIds, err := uc.authProvider.GetDataAuthorityIds(ctx, authorityId)
if err != nil {
return nil, 0, err
}
return uc.repo.List(ctx, dataIds, page, pageSize)
}
+148
View File
@@ -0,0 +1,148 @@
package example
import (
"context"
"errors"
"mime/multipart"
"strings"
"time"
)
// FileUpload 文件上传实体
type FileUpload struct {
ID uint
Name string
ClassId int
Url string
Tag string
Key string
CreatedAt time.Time
UpdatedAt time.Time
}
// FileUploadSearchReq 文件搜索请求
type FileUploadSearchReq struct {
Page int
PageSize int
Keyword string
ClassId int
}
// OssUploader OSS上传接口(与 pkg/upload.OSS 兼容)
type OssUploader interface {
UploadFile(file *multipart.FileHeader) (string, string, error)
DeleteFile(key string) error
}
// NilOssUploader 空OSS上传器(用于未配置OSS时)
type NilOssUploader struct{}
func (n *NilOssUploader) UploadFile(file *multipart.FileHeader) (string, string, error) {
return "", "", errors.New("OSS未配置")
}
func (n *NilOssUploader) DeleteFile(key string) error {
return errors.New("OSS未配置")
}
// FileUploadRepo 文件上传仓储接口
type FileUploadRepo interface {
Create(ctx context.Context, file *FileUpload) error
Update(ctx context.Context, file *FileUpload) error
Delete(ctx context.Context, id uint) error
FindByID(ctx context.Context, id uint) (*FileUpload, error)
FindByKey(ctx context.Context, key string) (*FileUpload, error)
List(ctx context.Context, req *FileUploadSearchReq) ([]*FileUpload, int64, error)
BatchCreate(ctx context.Context, files []*FileUpload) error
}
// FileUploadUsecase 文件上传用例
type FileUploadUsecase struct {
repo FileUploadRepo
oss OssUploader
}
// NewFileUploadUsecase 创建文件上传用例
func NewFileUploadUsecase(repo FileUploadRepo, oss OssUploader) *FileUploadUsecase {
return &FileUploadUsecase{repo: repo, oss: oss}
}
// Upload 创建文件上传记录
func (uc *FileUploadUsecase) Upload(ctx context.Context, file *FileUpload) error {
return uc.repo.Create(ctx, file)
}
// FindFile 查询文件记录
func (uc *FileUploadUsecase) FindFile(ctx context.Context, id uint) (*FileUpload, error) {
return uc.repo.FindByID(ctx, id)
}
// DeleteFile 删除文件记录
func (uc *FileUploadUsecase) DeleteFile(ctx context.Context, id uint) error {
file, err := uc.repo.FindByID(ctx, id)
if err != nil {
return err
}
// 删除OSS文件
if uc.oss != nil && file.Key != "" {
if err := uc.oss.DeleteFile(file.Key); err != nil {
return errors.New("文件删除失败")
}
}
return uc.repo.Delete(ctx, id)
}
// EditFileName 编辑文件名
func (uc *FileUploadUsecase) EditFileName(ctx context.Context, id uint, name string) error {
file, err := uc.repo.FindByID(ctx, id)
if err != nil {
return err
}
file.Name = name
return uc.repo.Update(ctx, file)
}
// GetFileRecordInfoList 分页获取文件列表
func (uc *FileUploadUsecase) GetFileRecordInfoList(ctx context.Context, req *FileUploadSearchReq) ([]*FileUpload, int64, error) {
return uc.repo.List(ctx, req)
}
// UploadFile 上传文件
func (uc *FileUploadUsecase) UploadFile(ctx context.Context, header *multipart.FileHeader, noSave string, classId int) (*FileUpload, error) {
if uc.oss == nil {
return nil, errors.New("OSS未配置")
}
filePath, key, err := uc.oss.UploadFile(header)
if err != nil {
return nil, err
}
s := strings.Split(header.Filename, ".")
file := &FileUpload{
Url: filePath,
Name: header.Filename,
ClassId: classId,
Tag: s[len(s)-1],
Key: key,
}
if noSave == "0" {
// 检查是否已存在相同key的记录
existing, _ := uc.repo.FindByKey(ctx, key)
if existing == nil {
if err := uc.repo.Create(ctx, file); err != nil {
return nil, err
}
}
}
return file, nil
}
// ImportURL 导入URL
func (uc *FileUploadUsecase) ImportURL(ctx context.Context, files []*FileUpload) error {
return uc.repo.BatchCreate(ctx, files)
}