初始化v1

This commit is contained in:
2025-08-03 00:11:15 +08:00
commit b88c8b8afa
171 changed files with 22353 additions and 0 deletions

View File

@@ -0,0 +1,337 @@
package movie
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"github.com/gogf/gf/v2/os/gtime"
"nl-video-api/internal/dao"
"nl-video-api/internal/service/movie"
"nl-video-api/utility/response"
)
// EpisodeController 集数控制器
type EpisodeController struct{}
var Episode = &EpisodeController{}
// Create 创建集数
func (c *EpisodeController) Create(r *ghttp.Request) {
var req *movie.EpisodeCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
episodeService := movie.NewEpisodeService()
err := episodeService.Create(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "创建成功",
"id": req.MovieId,
})
}
// Update 更新集数
func (c *EpisodeController) Update(r *ghttp.Request) {
var req *movie.EpisodeUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = id
}
}
if req.Id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
err := episodeService.Update(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// GetById 获取集数详情
func (c *EpisodeController) GetById(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
episode, err := episodeService.GetById(r.Context(), &movie.EpisodeDetailReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": episode,
})
}
// GetByMovieId 根据影片ID获取集数列表
func (c *EpisodeController) GetByMovieId(r *ghttp.Request) {
movieIdStr := r.Get("movie_id").String()
movieId, err := strconv.Atoi(movieIdStr)
if err != nil || movieId <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
episodeService := movie.NewEpisodeService()
episodes, err := episodeService.GetByMovieId(r.Context(), movieId)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"list": episodes,
"total": len(episodes),
"movie_id": movieId,
})
}
// Delete 删除集数
func (c *EpisodeController) Delete(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "集数ID无效")
return
}
episodeService := movie.NewEpisodeService()
err = episodeService.Delete(r.Context(), &movie.EpisodeDeleteReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "删除成功",
})
}
// BatchCreate 批量创建集数
func (c *EpisodeController) BatchCreate(r *ghttp.Request) {
type BatchCreateReq struct {
MovieId int `json:"movie_id" v:"required|min:1#请选择影片"`
Episodes []movie.EpisodeCreateReq `json:"episodes" v:"required#集数列表不能为空"`
}
var req BatchCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Episodes) == 0 {
response.Error(r, 1001, "集数列表不能为空")
return
}
// 设置影片ID
for i := range req.Episodes {
req.Episodes[i].MovieId = req.MovieId
}
episodeService := movie.NewEpisodeService()
// 由于BatchCreate方法不存在,我们逐个创建
successCount := 0
for _, episodeReq := range req.Episodes {
if err := episodeService.Create(r.Context(), &episodeReq); err != nil {
g.Log().Errorf(r.Context(), "创建集数失败: %v", err)
} else {
successCount++
}
}
response.Success(r, g.Map{
"message": "批量创建完成",
"movie_id": req.MovieId,
"total_count": len(req.Episodes),
"success_count": successCount,
"fail_count": len(req.Episodes) - successCount,
})
}
// UploadVideo 上传集数视频
func (c *EpisodeController) UploadVideo(r *ghttp.Request) {
file := r.GetUploadFile("video")
if file == nil {
response.Error(r, 1001, "请选择要上传的视频文件")
return
}
// 验证文件类型
allowedTypes := []string{"video/mp4", "video/avi", "video/mkv", "video/mov", "video/wmv"}
isValidType := false
for _, allowedType := range allowedTypes {
if file.Header.Get("Content-Type") == allowedType {
isValidType = true
break
}
}
if !isValidType {
response.Error(r, 1001, "不支持的视频格式")
return
}
// 检查文件大小(限制5GB)
maxSize := int64(5 * 1024 * 1024 * 1024)
if file.Size > maxSize {
response.Error(r, 1001, "视频文件过大,最大支持5GB")
return
}
// 生成文件名
timestamp := gtime.Now().TimestampStr()
filename := timestamp + "_" + file.Filename
uploadPath := "resource/public/uploads/episodes/" + filename
// 保存文件
if _, err := file.Save(uploadPath); err != nil {
response.Error(r, 1002, "视频上传失败: "+err.Error())
return
}
// 返回文件信息
relativePath := "/uploads/episodes/" + filename
response.Success(r, g.Map{
"message": "上传成功",
"url": relativePath,
"filename": filename,
"size": file.Size,
})
}
// GenerateThumbnail 生成缩略图
func (c *EpisodeController) GenerateThumbnail(r *ghttp.Request) {
videoUrl := r.Get("video_url").String()
if videoUrl == "" {
response.Error(r, 1001, "视频地址不能为空")
return
}
// 生成缩略图文件路径
timestamp := gtime.Now().TimestampStr()
filename := "thumb_" + timestamp + ".jpg"
thumbDir := "resource/public/uploads/thumbnails"
_ = thumbDir + "/" + filename // 避免未使用变量错误
// 提取缩略图 (这里需要实际的视频处理库)
// if err := video.ExtractCover(videoUrl, thumbPath); err != nil {
// response.Error(r, 1002, "生成缩略图失败: "+err.Error())
// return
// }
// 返回缩略图信息
relativePath := "/uploads/thumbnails/" + filename
response.Success(r, g.Map{
"message": "生成成功",
"thumbnail": relativePath,
"filename": filename,
})
}
// GetVideoInfo 获取视频信息
func (c *EpisodeController) GetVideoInfo(r *ghttp.Request) {
videoUrl := r.Get("video_url").String()
if videoUrl == "" {
response.Error(r, 1001, "视频地址不能为空")
return
}
// 获取视频信息 (这里需要实际的视频处理库)
// videoInfo, err := video.GetVideoInfo(videoUrl)
// if err != nil {
// response.Error(r, 1002, "获取视频信息失败: "+err.Error())
// return
// }
// 模拟返回视频信息
videoInfo := g.Map{
"duration": 0,
"width": 1920,
"height": 1080,
"bitrate": "2000kbps",
"format": "mp4",
"size": 0,
"created_at": "",
}
response.Success(r, g.Map{
"message": "获取成功",
"data": videoInfo,
})
}
// BatchUpdateStatus 批量更新集数状态
func (c *EpisodeController) BatchUpdateStatus(r *ghttp.Request) {
type BatchUpdateReq struct {
Ids []int `json:"ids" v:"required#请选择要操作的集数"`
Status int `json:"status" v:"required|in:0,1#状态只能为0或1"`
}
var req BatchUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Ids) == 0 {
response.Error(r, 1001, "请选择要操作的集数")
return
}
ctx := r.Context()
successCount := 0
failCount := 0
for _, id := range req.Ids {
updateData := g.Map{
"status": req.Status,
}
episodeDao := dao.NewEpisodeDao()
if err := episodeDao.Update(ctx, id, updateData); err != nil {
g.Log().Errorf(ctx, "批量更新集数状态失败: ID=%d, 错误=%v", id, err)
failCount++
} else {
successCount++
}
}
response.Success(r, g.Map{
"message": "批量更新完成",
"success_count": successCount,
"fail_count": failCount,
"total_count": len(req.Ids),
})
}

View File

@@ -0,0 +1,418 @@
package movie
import (
"strconv"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/net/ghttp"
"nl-video-api/internal/service/movie"
"nl-video-api/utility/response"
)
// MovieController 影片控制器
type MovieController struct{}
var Movie = &MovieController{}
// Create 创建影片
func (c *MovieController) Create(r *ghttp.Request) {
var req *movie.MovieCreateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
movieService := movie.NewMovieService()
err := movieService.Create(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "创建成功",
})
}
// Update 更新影片
func (c *MovieController) Update(r *ghttp.Request) {
var req *movie.MovieUpdateReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 从URL路径获取ID
if req.Id == 0 {
idStr := r.Get("id").String()
if id, err := strconv.Atoi(idStr); err == nil {
req.Id = id
}
}
if req.Id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
movieService := movie.NewMovieService()
err := movieService.Update(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// GetById 获取影片详情
func (c *MovieController) GetById(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
movieService := movie.NewMovieService()
movieDetail, err := movieService.GetById(r.Context(), &movie.MovieDetailReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": movieDetail,
})
}
// GetList 获取影片列表
func (c *MovieController) GetList(r *ghttp.Request) {
var req *movie.MovieListReq
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
// 设置默认分页参数
if req.Page <= 0 {
req.Page = 1
}
if req.PageSize <= 0 {
req.PageSize = 10
}
movieService := movie.NewMovieService()
result, err := movieService.GetList(r.Context(), req)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": result,
})
}
// Delete 删除影片
func (c *MovieController) Delete(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
movieService := movie.NewMovieService()
err = movieService.Delete(r.Context(), &movie.MovieDeleteReq{Id: id})
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "删除成功",
})
}
// GetHot 获取热门影片
func (c *MovieController) GetHot(r *ghttp.Request) {
limitStr := r.Get("limit", "10").String()
limit, err := strconv.Atoi(limitStr)
if err != nil || limit <= 0 {
limit = 10
}
movieService := movie.NewMovieService()
movies, err := movieService.GetHotMovies(r.Context(), limit)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": movies,
})
}
// GetRecommend 获取推荐影片
func (c *MovieController) GetRecommend(r *ghttp.Request) {
limitStr := r.Get("limit", "10").String()
limit, err := strconv.Atoi(limitStr)
if err != nil || limit <= 0 {
limit = 10
}
movieService := movie.NewMovieService()
movies, err := movieService.GetRecommendMovies(r.Context(), limit)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": movies,
})
}
// GetNew 获取最新影片
func (c *MovieController) GetNew(r *ghttp.Request) {
limitStr := r.Get("limit", "10").String()
limit, err := strconv.Atoi(limitStr)
if err != nil || limit <= 0 {
limit = 10
}
movieService := movie.NewMovieService()
movies, err := movieService.GetNewMovies(r.Context(), limit)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": movies,
})
}
// Search 搜索影片
func (c *MovieController) Search(r *ghttp.Request) {
keyword := r.Get("keyword").String()
if keyword == "" {
response.Error(r, 1001, "搜索关键词不能为空")
return
}
pageStr := r.Get("page", "1").String()
page, err := strconv.Atoi(pageStr)
if err != nil || page <= 0 {
page = 1
}
pageSizeStr := r.Get("page_size", "10").String()
pageSize, err := strconv.Atoi(pageSizeStr)
if err != nil || pageSize <= 0 {
pageSize = 10
}
movieService := movie.NewMovieService()
movies, total, err := movieService.SearchMovies(r.Context(), keyword, page, pageSize)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "搜索成功",
"data": g.Map{
"list": movies,
"total": total,
"page": page,
"page_size": pageSize,
"keyword": keyword,
},
})
}
// GetByCategory 根据分类获取影片
func (c *MovieController) GetByCategory(r *ghttp.Request) {
categoryIdStr := r.Get("category_id").String()
categoryId, err := strconv.Atoi(categoryIdStr)
if err != nil || categoryId <= 0 {
response.Error(r, 1001, "分类ID无效")
return
}
pageStr := r.Get("page", "1").String()
page, err := strconv.Atoi(pageStr)
if err != nil || page <= 0 {
page = 1
}
pageSizeStr := r.Get("page_size", "10").String()
pageSize, err := strconv.Atoi(pageSizeStr)
if err != nil || pageSize <= 0 {
pageSize = 10
}
movieService := movie.NewMovieService()
movies, total, err := movieService.GetMoviesByCategory(r.Context(), categoryId, page, pageSize)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": g.Map{
"list": movies,
"total": total,
"page": page,
"page_size": pageSize,
"category_id": categoryId,
},
})
}
// UpdateViewCount 更新观看次数
func (c *MovieController) UpdateViewCount(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
movieService := movie.NewMovieService()
err = movieService.UpdateViewCount(r.Context(), id)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// UpdateLikeCount 更新点赞数
func (c *MovieController) UpdateLikeCount(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
incrementStr := r.Get("increment", "1").String()
increment, err := strconv.Atoi(incrementStr)
if err != nil {
increment = 1
}
movieService := movie.NewMovieService()
err = movieService.UpdateLikeCount(r.Context(), id, increment)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// UpdateCollectCount 更新收藏数
func (c *MovieController) UpdateCollectCount(r *ghttp.Request) {
idStr := r.Get("id").String()
id, err := strconv.Atoi(idStr)
if err != nil || id <= 0 {
response.Error(r, 1001, "影片ID无效")
return
}
incrementStr := r.Get("increment", "1").String()
increment, err := strconv.Atoi(incrementStr)
if err != nil {
increment = 1
}
movieService := movie.NewMovieService()
err = movieService.UpdateCollectCount(r.Context(), id, increment)
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "更新成功",
})
}
// GetStatistics 获取影片统计
func (c *MovieController) GetStatistics(r *ghttp.Request) {
movieService := movie.NewMovieService()
stats, err := movieService.GetStatistics(r.Context())
if err != nil {
response.Error(r, 1002, err.Error())
return
}
response.Success(r, g.Map{
"message": "获取成功",
"data": stats,
})
}
// BatchUpdate 批量更新影片
func (c *MovieController) BatchUpdate(r *ghttp.Request) {
var req struct {
Ids []int `json:"ids" v:"required#影片ID列表不能为空"`
Status *int `json:"status"`
IsVip *int `json:"is_vip"`
}
if err := r.Parse(&req); err != nil {
response.Error(r, 1001, "参数解析失败: "+err.Error())
return
}
if len(req.Ids) == 0 {
response.Error(r, 1001, "影片ID列表不能为空")
return
}
// TODO: 实现批量更新逻辑
response.Success(r, g.Map{
"message": "批量更新成功",
})
}
// UploadVideo 上传视频
func (c *MovieController) UploadVideo(r *ghttp.Request) {
// TODO: 实现视频上传逻辑
response.Success(r, g.Map{
"message": "视频上传成功",
"data": g.Map{
"url": "/uploads/videos/example.mp4",
},
})
}
// UploadPoster 上传海报
func (c *MovieController) UploadPoster(r *ghttp.Request) {
// TODO: 实现海报上传逻辑
response.Success(r, g.Map{
"message": "海报上传成功",
"data": g.Map{
"url": "/uploads/posters/example.jpg",
},
})
}