Files
nl-video-api/internal/service/attachment.go
2025-08-03 00:11:15 +08:00

1214 lines
31 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package service
import (
"context"
"fmt"
"strings"
"time"
"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/gtime"
"github.com/gogf/gf/v2/util/gconv"
"nl-video-api/internal/dao"
"nl-video-api/internal/model/entity"
"nl-video-api/utility/response"
)
// AttachmentService 附件管理服务
type AttachmentService struct{}
// NewAttachmentService 创建附件管理服务实例
func NewAttachmentService() *AttachmentService {
return &AttachmentService{}
}
// 定义请求和响应结构体,避免循环导入
type AttachmentListReq struct {
Page int `json:"page"`
Size int `json:"size"`
Type string `json:"type"`
Category string `json:"category"`
Keyword string `json:"keyword"`
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
MinSize int64 `json:"min_size"`
MaxSize int64 `json:"max_size"`
UserId uint `json:"user_id"`
}
type AttachmentListRes struct {
List []AttachmentItem `json:"list"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}
type AttachmentItem struct {
Id uint `json:"id"`
Filename string `json:"filename"`
OriginalName string `json:"original_name"`
Url string `json:"url"`
Size int64 `json:"size"`
Type string `json:"type"`
Category string `json:"category"`
Description string `json:"description"`
UserId uint `json:"user_id"`
Username string `json:"username"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
type AttachmentDetailReq struct {
Id uint `json:"id"`
}
type AttachmentDetailRes struct {
Attachment AttachmentDetail `json:"attachment"`
}
type AttachmentDetail struct {
Id uint `json:"id"`
Filename string `json:"filename"`
OriginalName string `json:"original_name"`
Url string `json:"url"`
Size int64 `json:"size"`
Type string `json:"type"`
Category string `json:"category"`
Description string `json:"description"`
UserId uint `json:"user_id"`
Username string `json:"username"`
DownloadCount int `json:"download_count"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
}
type AttachmentUpdateReq struct {
Id uint `json:"id"`
Category string `json:"category"`
Description string `json:"description"`
}
type AttachmentDeleteReq struct {
Id uint `json:"id"`
}
type AttachmentBatchDeleteReq struct {
Ids []uint `json:"ids"`
}
type AttachmentDownloadReq struct {
Id uint `json:"id"`
}
type AttachmentDownloadRes struct {
Url string `json:"url"`
Filename string `json:"filename"`
}
type AttachmentCategoryListReq struct {
Type string `json:"type"`
}
type AttachmentCategoryListRes struct {
Categories []AttachmentCategoryItem `json:"categories"`
}
type AttachmentCategoryItem struct {
Category string `json:"category"`
Count int `json:"count"`
}
type AttachmentStatisticsReq struct {
StartDate string `json:"start_date"`
EndDate string `json:"end_date"`
Type string `json:"type"`
}
type AttachmentStatisticsRes struct {
TotalCount int `json:"total_count"`
TotalSize int64 `json:"total_size"`
TypeStats []AttachmentTypeStatItem `json:"type_stats"`
CategoryStats []AttachmentCategoryStatItem `json:"category_stats"`
UploadChart []AttachmentUploadChartItem `json:"upload_chart"`
SizeChart []AttachmentSizeChartItem `json:"size_chart"`
PopularFiles []AttachmentPopularItem `json:"popular_files"`
RecentUploads []AttachmentRecentItem `json:"recent_uploads"`
}
type AttachmentTypeStatItem struct {
Type string `json:"type"`
Count int `json:"count"`
Size int64 `json:"size"`
Percentage string `json:"percentage"`
}
type AttachmentCategoryStatItem struct {
Category string `json:"category"`
Count int `json:"count"`
Size int64 `json:"size"`
Percentage string `json:"percentage"`
}
type AttachmentUploadChartItem struct {
Date string `json:"date"`
Count int `json:"count"`
Size int64 `json:"size"`
}
type AttachmentSizeChartItem struct {
SizeRange string `json:"size_range"`
Count int `json:"count"`
}
type AttachmentPopularItem struct {
Id uint `json:"id"`
Filename string `json:"filename"`
Type string `json:"type"`
Size int64 `json:"size"`
DownloadCount int `json:"download_count"`
CreatedAt int64 `json:"created_at"`
}
type AttachmentRecentItem struct {
Id uint `json:"id"`
Filename string `json:"filename"`
OriginalName string `json:"original_name"`
Type string `json:"type"`
Size int64 `json:"size"`
UserId uint `json:"user_id"`
Username string `json:"username"`
CreatedAt int64 `json:"created_at"`
}
type AttachmentMoveReq struct {
Ids []uint `json:"ids"`
NewCategory string `json:"new_category"`
}
type AttachmentCopyReq struct {
Id uint `json:"id"`
NewCategory string `json:"new_category"`
Description string `json:"description"`
}
type AttachmentCopyRes struct {
Id uint `json:"id"`
Filename string `json:"filename"`
Url string `json:"url"`
}
type AttachmentRenameReq struct {
Id uint `json:"id"`
Filename string `json:"filename"`
}
type AttachmentSearchReq struct {
Query string `json:"query"`
Type string `json:"type"`
Category string `json:"category"`
Page int `json:"page"`
Size int `json:"size"`
}
type AttachmentSearchRes struct {
List []AttachmentItem `json:"list"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}
type AttachmentUserListReq struct {
Page int `json:"page"`
Size int `json:"size"`
Type string `json:"type"`
Category string `json:"category"`
Keyword string `json:"keyword"`
}
type AttachmentUserListRes struct {
List []AttachmentUserItem `json:"list"`
Total int `json:"total"`
Page int `json:"page"`
Size int `json:"size"`
}
type AttachmentUserItem struct {
Id uint `json:"id"`
Filename string `json:"filename"`
OriginalName string `json:"original_name"`
Url string `json:"url"`
Size int64 `json:"size"`
Type string `json:"type"`
Category string `json:"category"`
Description string `json:"description"`
CreatedAt int64 `json:"created_at"`
}
// Upload 上传附件
func (s *AttachmentService) Upload(r *ghttp.Request) {
// 获取请求参数
attachmentType := r.Get("type").String()
category := r.Get("category").String()
description := r.Get("description").String()
_ = description // 避免未使用变量错误
// 获取当前用户ID
userId := uint(1) // 临时设置,实际应该从请求中获取
if userId == 0 {
response.Error(r, response.CodeUnauthorized, "用户未登录")
return
}
// 这里应该处理文件上传逻辑
// 由于这是API结构设计暂时模拟文件上传结果
filename := fmt.Sprintf("%s_%d.%s", attachmentType, time.Now().Unix(), "jpg")
url := fmt.Sprintf("/uploads/%s/%s", category, filename)
size := int64(1024 * 100) // 模拟文件大小
// 保存附件信息到数据库
data := &entity.Attachment{
Name: filename,
Path: url, // 使用URL作为路径
Url: url,
Size: size,
MimeType: attachmentType,
Extension: "jpg", // 从文件名提取扩展名
UserId: int(userId),
Status: 1, // 默认启用
CreatedAt: gtime.Now(),
UpdatedAt: gtime.Now(),
}
id, err := dao.Attachment.Ctx(r.Context()).Data(data).InsertAndGetId()
if err != nil {
response.Error(r, response.CodeInternalError, "保存附件信息失败")
return
}
response.Success(r, g.Map{
"id": uint(id),
"name": filename,
"url": url,
"size": size,
"type": attachmentType,
})
}
// List 获取附件列表
func (s *AttachmentService) List(ctx context.Context, req *AttachmentListReq) (*AttachmentListRes, error) {
// 设置默认值
if req.Page <= 0 {
req.Page = 1
}
if req.Size <= 0 {
req.Size = 10
}
// 构建查询条件
query := dao.Attachment.Ctx(ctx)
// 类型筛选
if req.Type != "" {
query = query.Where("mime_type", req.Type)
}
// 关键词搜索
if req.Keyword != "" {
keyword := "%" + req.Keyword + "%"
query = query.Where("name LIKE ?", keyword)
}
// 日期范围筛选
if req.StartDate != "" {
query = query.Where("created_at >= ?", req.StartDate+" 00:00:00")
}
if req.EndDate != "" {
query = query.Where("created_at <= ?", req.EndDate+" 23:59:59")
}
// 文件大小筛选
if req.MinSize > 0 {
query = query.Where("size >= ?", req.MinSize)
}
if req.MaxSize > 0 {
query = query.Where("size <= ?", req.MaxSize)
}
// 用户筛选
if req.UserId > 0 {
query = query.Where("user_id", req.UserId)
}
// 获取总数
total, err := query.Count()
if err != nil {
return nil, gerror.New("获取附件总数失败")
}
// 获取列表数据
var attachments []entity.Attachment
err = query.Order("id DESC").
Limit((req.Page-1)*req.Size, req.Size).
Scan(&attachments)
if err != nil {
return nil, gerror.New("获取附件列表失败")
}
// 获取用户信息
userIds := make([]int, 0, len(attachments))
for _, attachment := range attachments {
userIds = append(userIds, attachment.UserId)
}
userMap := make(map[int]string)
if len(userIds) > 0 {
var users []entity.NlUser
g.DB().Model("nl_user").WhereIn("id", userIds).Fields("id, username").Scan(&users)
for _, user := range users {
userMap[int(user.Id)] = user.Username
}
}
// 转换为响应格式
list := make([]AttachmentItem, 0, len(attachments))
for _, attachment := range attachments {
username := userMap[attachment.UserId]
list = append(list, AttachmentItem{
Id: attachment.Id,
Filename: attachment.Name,
OriginalName: attachment.Name, // 使用Name作为原始名称
Url: attachment.Url,
Size: attachment.Size,
Type: attachment.MimeType,
Category: "default", // 默认分类
Description: "", // 默认描述
UserId: uint(attachment.UserId),
Username: username,
CreatedAt: attachment.CreatedAt.Unix(),
UpdatedAt: attachment.UpdatedAt.Unix(),
})
}
return &AttachmentListRes{
List: list,
Total: total,
Page: req.Page,
Size: req.Size,
}, nil
}
// Detail 获取附件详情
func (s *AttachmentService) Detail(ctx context.Context, req *AttachmentDetailReq) (*AttachmentDetailRes, error) {
var attachment entity.Attachment
err := dao.Attachment.Ctx(ctx).Where("id", req.Id).Scan(&attachment)
if err != nil {
return nil, gerror.New("获取附件详情失败")
}
if attachment.Id == 0 {
return nil, gerror.New("附件不存在")
}
// 获取用户信息
var user entity.NlUser
g.DB().Model("nl_user").Where("id", attachment.UserId).Fields("username").Scan(&user)
return &AttachmentDetailRes{
Attachment: AttachmentDetail{
Id: attachment.Id,
Filename: attachment.Name,
OriginalName: attachment.Name,
Url: attachment.Url,
Size: attachment.Size,
Type: attachment.MimeType,
Category: "default",
Description: "",
UserId: uint(attachment.UserId),
Username: user.Username,
DownloadCount: 0, // 实体中没有此字段设为0
CreatedAt: attachment.CreatedAt.Unix(),
UpdatedAt: attachment.UpdatedAt.Unix(),
},
}, nil
}
// Update 更新附件
func (s *AttachmentService) Update(ctx context.Context, req *AttachmentUpdateReq) error {
// 检查附件是否存在
count, err := dao.Attachment.Ctx(ctx).Where("id", req.Id).Count()
if err != nil {
return gerror.New("检查附件失败")
}
if count == 0 {
return gerror.New("附件不存在")
}
// 更新附件信息实体中没有category和description字段只更新状态
data := g.Map{
"status": 1, // 保持启用状态
"updated_at": gtime.Now(),
}
_, err = dao.Attachment.Ctx(ctx).Where("id", req.Id).Data(data).Update()
if err != nil {
return gerror.New("更新附件失败")
}
return nil
}
// Delete 删除附件
func (s *AttachmentService) Delete(ctx context.Context, req *AttachmentDeleteReq) error {
// 获取附件信息
var attachment entity.Attachment
err := dao.Attachment.Ctx(ctx).Where("id", req.Id).Scan(&attachment)
if err != nil {
return gerror.New("获取附件信息失败")
}
if attachment.Id == 0 {
return gerror.New("附件不存在")
}
// 删除数据库记录
_, err = dao.Attachment.Ctx(ctx).Where("id", req.Id).Delete()
if err != nil {
return gerror.New("删除附件记录失败")
}
// 删除物理文件(这里应该根据实际存储方式处理)
// 例如os.Remove(attachment.Url)
return nil
}
// BatchDelete 批量删除附件
func (s *AttachmentService) BatchDelete(ctx context.Context, req *AttachmentBatchDeleteReq) error {
if len(req.Ids) == 0 {
return gerror.New("请选择要删除的附件")
}
// 获取附件信息
var attachments []entity.Attachment
err := dao.Attachment.Ctx(ctx).WhereIn("id", req.Ids).Scan(&attachments)
if err != nil {
return gerror.New("获取附件信息失败")
}
// 删除数据库记录
_, err = dao.Attachment.Ctx(ctx).WhereIn("id", req.Ids).Delete()
if err != nil {
return gerror.New("批量删除附件记录失败")
}
// 删除物理文件
for _, attachment := range attachments {
// 这里应该根据实际存储方式处理
// 例如os.Remove(attachment.Url)
_ = attachment // 避免未使用变量错误
}
return nil
}
// Download 下载附件
func (s *AttachmentService) Download(ctx context.Context, req *AttachmentDownloadReq) (*AttachmentDownloadRes, error) {
// 获取附件信息
var attachment entity.Attachment
err := dao.Attachment.Ctx(ctx).Where("id", req.Id).Scan(&attachment)
if err != nil {
return nil, gerror.New("获取附件信息失败")
}
if attachment.Id == 0 {
return nil, gerror.New("附件不存在")
}
// 这里可以更新下载次数但实体中没有download_count字段所以跳过
return &AttachmentDownloadRes{
Url: attachment.Url,
Filename: attachment.Name,
}, nil
}
// GetCategoryList 获取附件分类列表
func (s *AttachmentService) GetCategoryList(ctx context.Context, req *AttachmentCategoryListReq) (*AttachmentCategoryListRes, error) {
query := dao.Attachment.Ctx(ctx).Fields("mime_type as category, COUNT(*) as count")
// 类型筛选
if req.Type != "" {
query = query.Where("mime_type", req.Type)
}
var categories []g.Map
err := query.Group("mime_type").Order("count DESC").Scan(&categories)
if err != nil {
return nil, gerror.New("获取分类列表失败")
}
// 转换为响应格式
list := make([]AttachmentCategoryItem, 0, len(categories))
for _, category := range categories {
list = append(list, AttachmentCategoryItem{
Category: gconv.String(category["category"]),
Count: gconv.Int(category["count"]),
})
}
return &AttachmentCategoryListRes{
Categories: list,
}, nil
}
// GetStatistics 获取附件统计
func (s *AttachmentService) GetStatistics(ctx context.Context, req *AttachmentStatisticsReq) (*AttachmentStatisticsRes, error) {
// 构建查询条件
query := dao.Attachment.Ctx(ctx)
if req.StartDate != "" {
query = query.Where("created_at >= ?", req.StartDate+" 00:00:00")
}
if req.EndDate != "" {
query = query.Where("created_at <= ?", req.EndDate+" 23:59:59")
}
if req.Type != "" {
query = query.Where("mime_type", req.Type)
}
// 获取基础统计
var totalCount int
var totalSize int64
query.Fields("COUNT(*) as total_count, COALESCE(SUM(size), 0) as total_size").
Scan(&g.Map{
"total_count": &totalCount,
"total_size": &totalSize,
})
// 获取类型统计
typeStats := make([]AttachmentTypeStatItem, 0)
var typeStatsData []g.Map
dao.Attachment.Ctx(ctx).Fields("mime_type as type, COUNT(*) as count, COALESCE(SUM(size), 0) as size").
Group("mime_type").Order("count DESC").Scan(&typeStatsData)
for _, stat := range typeStatsData {
count := gconv.Int(stat["count"])
size := gconv.Int64(stat["size"])
percentage := "0.00"
if totalCount > 0 {
percentage = fmt.Sprintf("%.2f", float64(count)/float64(totalCount)*100)
}
typeStats = append(typeStats, AttachmentTypeStatItem{
Type: gconv.String(stat["type"]),
Count: count,
Size: size,
Percentage: percentage,
})
}
// 获取分类统计使用mime_type作为分类
categoryStats := make([]AttachmentCategoryStatItem, 0)
var categoryStatsData []g.Map
dao.Attachment.Ctx(ctx).Fields("mime_type as category, COUNT(*) as count, COALESCE(SUM(size), 0) as size").
Group("mime_type").Order("count DESC").Limit(10).Scan(&categoryStatsData)
for _, stat := range categoryStatsData {
count := gconv.Int(stat["count"])
size := gconv.Int64(stat["size"])
percentage := "0.00"
if totalCount > 0 {
percentage = fmt.Sprintf("%.2f", float64(count)/float64(totalCount)*100)
}
categoryStats = append(categoryStats, AttachmentCategoryStatItem{
Category: gconv.String(stat["category"]),
Count: count,
Size: size,
Percentage: percentage,
})
}
// 获取上传图表数据(简化处理)
uploadChart := make([]AttachmentUploadChartItem, 0)
if req.StartDate != "" && req.EndDate != "" {
uploadChart = append(uploadChart, AttachmentUploadChartItem{
Date: req.StartDate,
Count: totalCount,
Size: totalSize,
})
}
// 获取大小图表数据
sizeChart := []AttachmentSizeChartItem{
{SizeRange: "0-1MB", Count: 0},
{SizeRange: "1-10MB", Count: 0},
{SizeRange: "10-100MB", Count: 0},
{SizeRange: "100MB+", Count: 0},
}
// 获取热门文件
popularFiles := make([]AttachmentPopularItem, 0)
var popularData []entity.Attachment
dao.Attachment.Ctx(ctx).Order("created_at DESC").Limit(10).Scan(&popularData)
for _, file := range popularData {
popularFiles = append(popularFiles, AttachmentPopularItem{
Id: file.Id,
Filename: file.Name,
Type: file.MimeType,
Size: file.Size,
DownloadCount: 0, // 实体中没有此字段
CreatedAt: file.CreatedAt.Unix(),
})
}
// 获取最近上传
recentUploads := make([]AttachmentRecentItem, 0)
var recentData []entity.Attachment
dao.Attachment.Ctx(ctx).Order("created_at DESC").Limit(10).Scan(&recentData)
// 获取用户信息
userIds := make([]int, 0, len(recentData))
for _, file := range recentData {
userIds = append(userIds, file.UserId)
}
userMap := make(map[int]string)
if len(userIds) > 0 {
var users []entity.NlUser
g.DB().Model("nl_user").WhereIn("id", userIds).Fields("id, username").Scan(&users)
for _, user := range users {
userMap[int(user.Id)] = user.Username
}
}
for _, file := range recentData {
username := userMap[file.UserId]
recentUploads = append(recentUploads, AttachmentRecentItem{
Id: file.Id,
Filename: file.Name,
OriginalName: file.Name,
Type: file.MimeType,
Size: file.Size,
UserId: uint(file.UserId),
Username: username,
CreatedAt: file.CreatedAt.Unix(),
})
}
return &AttachmentStatisticsRes{
TotalCount: totalCount,
TotalSize: totalSize,
TypeStats: typeStats,
CategoryStats: categoryStats,
UploadChart: uploadChart,
SizeChart: sizeChart,
PopularFiles: popularFiles,
RecentUploads: recentUploads,
}, nil
}
// Move 移动附件
func (s *AttachmentService) Move(ctx context.Context, req *AttachmentMoveReq) error {
if len(req.Ids) == 0 {
return gerror.New("请选择要移动的附件")
}
// 更新状态实体中没有category字段只能更新状态
_, err := dao.Attachment.Ctx(ctx).WhereIn("id", req.Ids).Data(g.Map{
"status": 1,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
return gerror.New("移动附件失败")
}
return nil
}
// Copy 复制附件
func (s *AttachmentService) Copy(ctx context.Context, req *AttachmentCopyReq) (*AttachmentCopyRes, error) {
// 获取源附件信息
var sourceAttachment entity.Attachment
err := dao.Attachment.Ctx(ctx).Where("id", req.Id).Scan(&sourceAttachment)
if err != nil {
return nil, gerror.New("获取源附件信息失败")
}
if sourceAttachment.Id == 0 {
return nil, gerror.New("源附件不存在")
}
// 获取当前用户ID
userId := GetUserIdFromContext(ctx)
if userId == 0 {
return nil, gerror.New("用户未登录")
}
// 生成新文件名
newFilename := fmt.Sprintf("copy_%d_%s", time.Now().Unix(), sourceAttachment.Name)
newUrl := strings.Replace(sourceAttachment.Url, sourceAttachment.Name, newFilename, 1)
// 创建新附件记录
data := &entity.Attachment{
Name: newFilename,
Path: newUrl,
Url: newUrl,
Size: sourceAttachment.Size,
MimeType: sourceAttachment.MimeType,
Extension: sourceAttachment.Extension,
UserId: int(userId),
Status: 1,
CreatedAt: gtime.Now(),
UpdatedAt: gtime.Now(),
}
id, err := dao.Attachment.Ctx(ctx).Data(data).InsertAndGetId()
if err != nil {
return nil, gerror.New("复制附件失败")
}
// 这里应该复制物理文件
return &AttachmentCopyRes{
Id: uint(id),
Filename: newFilename,
Url: newUrl,
}, nil
}
// Rename 重命名附件
func (s *AttachmentService) Rename(ctx context.Context, req *AttachmentRenameReq) error {
// 检查附件是否存在
count, err := dao.Attachment.Ctx(ctx).Where("id", req.Id).Count()
if err != nil {
return gerror.New("检查附件失败")
}
if count == 0 {
return gerror.New("附件不存在")
}
// 更新文件名
_, err = dao.Attachment.Ctx(ctx).Where("id", req.Id).Data(g.Map{
"name": req.Filename,
"updated_at": gtime.Now(),
}).Update()
if err != nil {
return gerror.New("重命名附件失败")
}
return nil
}
// Search 搜索附件
func (s *AttachmentService) Search(ctx context.Context, req *AttachmentSearchReq) (*AttachmentSearchRes, error) {
// 设置默认值
if req.Page <= 0 {
req.Page = 1
}
if req.Size <= 0 {
req.Size = 10
}
// 构建查询条件
query := dao.Attachment.Ctx(ctx)
// 关键词搜索
if req.Query != "" {
keyword := "%" + req.Query + "%"
query = query.Where("name LIKE ?", keyword)
}
// 类型筛选
if req.Type != "" {
query = query.Where("mime_type", req.Type)
}
// 获取总数
total, err := query.Count()
if err != nil {
return nil, gerror.New("获取搜索结果总数失败")
}
// 获取列表数据
var attachments []entity.Attachment
err = query.Order("id DESC").
Limit((req.Page-1)*req.Size, req.Size).
Scan(&attachments)
if err != nil {
return nil, gerror.New("获取搜索结果失败")
}
// 转换为响应格式
list := make([]AttachmentItem, 0, len(attachments))
for _, attachment := range attachments {
list = append(list, AttachmentItem{
Id: attachment.Id,
Filename: attachment.Name,
OriginalName: attachment.Name,
Url: attachment.Url,
Size: attachment.Size,
Type: attachment.MimeType,
Category: "default",
Description: "",
UserId: uint(attachment.UserId),
CreatedAt: attachment.CreatedAt.Unix(),
})
}
return &AttachmentSearchRes{
List: list,
Total: total,
Page: req.Page,
Size: req.Size,
}, nil
}
// UserList 用户获取附件列表
func (s *AttachmentService) UserList(ctx context.Context, req *AttachmentUserListReq) (*AttachmentUserListRes, error) {
// 设置默认值
if req.Page <= 0 {
req.Page = 1
}
if req.Size <= 0 {
req.Size = 10
}
// 获取当前用户ID
userId := GetUserIdFromContext(ctx)
if userId == 0 {
return nil, gerror.New("用户未登录")
}
// 构建查询条件
query := dao.Attachment.Ctx(ctx).Where("user_id", userId)
// 类型筛选
if req.Type != "" {
query = query.Where("mime_type", req.Type)
}
// 关键词搜索
if req.Keyword != "" {
keyword := "%" + req.Keyword + "%"
query = query.Where("name LIKE ?", keyword)
}
// 获取总数
total, err := query.Count()
if err != nil {
return nil, gerror.New("获取附件总数失败")
}
// 获取列表数据
var attachments []entity.Attachment
err = query.Order("id DESC").
Limit((req.Page-1)*req.Size, req.Size).
Scan(&attachments)
if err != nil {
return nil, gerror.New("获取附件列表失败")
}
// 转换为响应格式
list := make([]AttachmentUserItem, 0, len(attachments))
for _, attachment := range attachments {
list = append(list, AttachmentUserItem{
Id: attachment.Id,
Filename: attachment.Name,
OriginalName: attachment.Name,
Url: attachment.Url,
Size: attachment.Size,
Type: attachment.MimeType,
Category: "default",
Description: "",
CreatedAt: attachment.CreatedAt.Unix(),
})
}
return &AttachmentUserListRes{
List: list,
Total: total,
Page: req.Page,
Size: req.Size,
}, nil
}
// GetUserIdFromContext 从上下文获取用户ID
func GetUserIdFromContext(ctx context.Context) uint {
// 这里应该从JWT token或session中获取用户ID
// 临时返回固定值
return 1
}
// UserUpload 用户上传附件
func (s *AttachmentService) UserUpload(r *ghttp.Request) {
s.Upload(r)
}
// UserGetList 用户获取附件列表
func (s *AttachmentService) UserGetList(r *ghttp.Request) {
// 获取请求参数并转换为内部请求结构
req := &AttachmentUserListReq{
Page: r.Get("page", 1).Int(),
Size: r.Get("size", 10).Int(),
Type: r.Get("type").String(),
Category: r.Get("category").String(),
Keyword: r.Get("keyword").String(),
}
// 调用服务方法
res, err := s.UserList(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}
// UserGetDetail 用户获取附件详情
func (s *AttachmentService) UserGetDetail(r *ghttp.Request) {
req := &AttachmentDetailReq{
Id: uint(r.Get("id").Int()),
}
res, err := s.Detail(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}
// UserUpdate 用户更新附件
func (s *AttachmentService) UserUpdate(r *ghttp.Request) {
req := &AttachmentUpdateReq{
Id: uint(r.Get("id").Int()),
Category: r.Get("category").String(),
Description: r.Get("description").String(),
}
err := s.Update(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, "更新成功")
}
// UserDelete 用户删除附件
func (s *AttachmentService) UserDelete(r *ghttp.Request) {
req := &AttachmentDeleteReq{
Id: uint(r.Get("id").Int()),
}
err := s.Delete(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, "删除成功")
}
// UserDownload 用户下载附件
func (s *AttachmentService) UserDownload(r *ghttp.Request) {
req := &AttachmentDownloadReq{
Id: uint(r.Get("id").Int()),
}
res, err := s.Download(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}
// UserCopy 用户复制附件
func (s *AttachmentService) UserCopy(r *ghttp.Request) {
req := &AttachmentCopyReq{
Id: uint(r.Get("id").Int()),
NewCategory: r.Get("new_category").String(),
Description: r.Get("description").String(),
}
res, err := s.Copy(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}
// UserRename 用户重命名附件
func (s *AttachmentService) UserRename(r *ghttp.Request) {
req := &AttachmentRenameReq{
Id: uint(r.Get("id").Int()),
Filename: r.Get("filename").String(),
}
err := s.Rename(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, "重命名成功")
}
// UserSearch 用户搜索附件
func (s *AttachmentService) UserSearch(r *ghttp.Request) {
req := &AttachmentSearchReq{
Query: r.Get("query").String(),
Type: r.Get("type").String(),
Category: r.Get("category").String(),
Page: r.Get("page", 1).Int(),
Size: r.Get("size", 10).Int(),
}
res, err := s.Search(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}
// UserGetCategoryList 用户获取附件分类列表
func (s *AttachmentService) UserGetCategoryList(r *ghttp.Request) {
req := &AttachmentCategoryListReq{
Type: r.Get("type").String(),
}
res, err := s.GetCategoryList(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}
// AdminGetList 管理员获取附件列表
func (s *AttachmentService) AdminGetList(r *ghttp.Request) {
req := &AttachmentListReq{
Page: r.Get("page", 1).Int(),
Size: r.Get("size", 10).Int(),
Type: r.Get("type").String(),
Category: r.Get("category").String(),
Keyword: r.Get("keyword").String(),
StartDate: r.Get("start_date").String(),
EndDate: r.Get("end_date").String(),
MinSize: r.Get("min_size").Int64(),
MaxSize: r.Get("max_size").Int64(),
UserId: uint(r.Get("user_id").Int()),
}
res, err := s.List(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}
// AdminGetDetail 管理员获取附件详情
func (s *AttachmentService) AdminGetDetail(r *ghttp.Request) {
s.UserGetDetail(r)
}
// AdminUpdate 管理员更新附件
func (s *AttachmentService) AdminUpdate(r *ghttp.Request) {
s.UserUpdate(r)
}
// AdminDelete 管理员删除附件
func (s *AttachmentService) AdminDelete(r *ghttp.Request) {
s.UserDelete(r)
}
// AdminBatchDelete 管理员批量删除附件
func (s *AttachmentService) AdminBatchDelete(r *ghttp.Request) {
var ids []uint
r.Parse(&ids)
req := &AttachmentBatchDeleteReq{
Ids: ids,
}
err := s.BatchDelete(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, "批量删除成功")
}
// AdminDownload 管理员下载附件
func (s *AttachmentService) AdminDownload(r *ghttp.Request) {
s.UserDownload(r)
}
// AdminMove 管理员移动附件
func (s *AttachmentService) AdminMove(r *ghttp.Request) {
var ids []uint
r.Parse(&ids)
req := &AttachmentMoveReq{
Ids: ids,
NewCategory: r.Get("new_category").String(),
}
err := s.Move(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, "移动成功")
}
// AdminCopy 管理员复制附件
func (s *AttachmentService) AdminCopy(r *ghttp.Request) {
s.UserCopy(r)
}
// AdminRename 管理员重命名附件
func (s *AttachmentService) AdminRename(r *ghttp.Request) {
s.UserRename(r)
}
// AdminSearch 管理员搜索附件
func (s *AttachmentService) AdminSearch(r *ghttp.Request) {
s.UserSearch(r)
}
// AdminGetCategoryList 管理员获取附件分类列表
func (s *AttachmentService) AdminGetCategoryList(r *ghttp.Request) {
s.UserGetCategoryList(r)
}
// AdminGetStatistics 管理员获取附件统计
func (s *AttachmentService) AdminGetStatistics(r *ghttp.Request) {
req := &AttachmentStatisticsReq{
StartDate: r.Get("start_date").String(),
EndDate: r.Get("end_date").String(),
Type: r.Get("type").String(),
}
res, err := s.GetStatistics(r.Context(), req)
if err != nil {
response.Error(r, response.CodeInternalError, err.Error())
return
}
response.Success(r, res)
}