feat(posts): add preview URL fields for post images
Add PreviewURL and PreviewURLLarge fields to PostImage model and responses. Image data now supports format "url|preview_url|preview_url_large" for storing multiple image variants. Also change comment cursor pagination to sort by created_at ASC (oldest first) to display earliest comments as first floor, and make AdminReviewVerificationRequest.Approve field optional.
This commit is contained in:
@@ -1404,7 +1404,7 @@ type AdminVerificationDetailResponse struct {
|
|||||||
|
|
||||||
// AdminReviewVerificationRequest 管理端审核认证请求
|
// AdminReviewVerificationRequest 管理端审核认证请求
|
||||||
type AdminReviewVerificationRequest struct {
|
type AdminReviewVerificationRequest struct {
|
||||||
Approve bool `json:"approve" binding:"required"`
|
Approve bool `json:"approve"`
|
||||||
RejectReason string `json:"reject_reason" binding:"omitempty,max=500"`
|
RejectReason string `json:"reject_reason" binding:"omitempty,max=500"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ func ConvertPostImageToResponse(img *model.PostImage) PostImageResponse {
|
|||||||
return PostImageResponse{}
|
return PostImageResponse{}
|
||||||
}
|
}
|
||||||
return PostImageResponse{
|
return PostImageResponse{
|
||||||
ID: img.ID,
|
ID: img.ID,
|
||||||
URL: img.URL,
|
URL: img.URL,
|
||||||
ThumbnailURL: img.ThumbnailURL,
|
ThumbnailURL: img.ThumbnailURL,
|
||||||
Width: img.Width,
|
PreviewURL: img.PreviewURL,
|
||||||
Height: img.Height,
|
PreviewURLLarge: img.PreviewURLLarge,
|
||||||
|
Width: img.Width,
|
||||||
|
Height: img.Height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -495,14 +495,14 @@ func (r *commentRepository) GetCommentsByPostIDForAdmin(postID string, page, pag
|
|||||||
// ========== Cursor Pagination Methods ==========
|
// ========== Cursor Pagination Methods ==========
|
||||||
|
|
||||||
// GetCommentsByCursor 游标分页获取帖子评论(包含回复)
|
// GetCommentsByCursor 游标分页获取帖子评论(包含回复)
|
||||||
// 排序方式:created_at DESC
|
// 排序方式:created_at ASC(最早发布的为一楼)
|
||||||
func (r *commentRepository) GetCommentsByCursor(ctx context.Context, postID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Comment], error) {
|
func (r *commentRepository) GetCommentsByCursor(ctx context.Context, postID string, req *cursor.PageRequest) (*cursor.CursorPageResult[*model.Comment], error) {
|
||||||
// 构建基础查询 - 只查询顶级评论
|
// 构建基础查询 - 只查询顶级评论
|
||||||
query := r.db.WithContext(ctx).Model(&model.Comment{}).
|
query := r.db.WithContext(ctx).Model(&model.Comment{}).
|
||||||
Where("post_id = ? AND parent_id IS NULL AND status = ?", postID, model.CommentStatusPublished)
|
Where("post_id = ? AND parent_id IS NULL AND status = ?", postID, model.CommentStatusPublished)
|
||||||
|
|
||||||
// 使用游标构建器
|
// 使用游标构建器
|
||||||
builder := cursor.NewBuilder(query, cursor.SortByCreatedAtDesc).
|
builder := cursor.NewBuilder(query, cursor.SortByCreatedAtAsc).
|
||||||
WithCursor(req.Cursor, req.Direction).
|
WithCursor(req.Cursor, req.Direction).
|
||||||
WithPageSize(req.PageSize)
|
WithPageSize(req.PageSize)
|
||||||
|
|
||||||
@@ -539,7 +539,7 @@ func (r *commentRepository) GetCommentsByCursor(ctx context.Context, postID stri
|
|||||||
nextCursor = cursor.NewCursor(
|
nextCursor = cursor.NewCursor(
|
||||||
cursor.FormatTime(lastComment.CreatedAt),
|
cursor.FormatTime(lastComment.CreatedAt),
|
||||||
lastComment.ID,
|
lastComment.ID,
|
||||||
cursor.SortByCreatedAtDesc,
|
cursor.SortByCreatedAtAsc,
|
||||||
).Encode()
|
).Encode()
|
||||||
}
|
}
|
||||||
// 上一页游标
|
// 上一页游标
|
||||||
@@ -547,7 +547,7 @@ func (r *commentRepository) GetCommentsByCursor(ctx context.Context, postID stri
|
|||||||
prevCursor = cursor.NewCursor(
|
prevCursor = cursor.NewCursor(
|
||||||
cursor.FormatTime(firstComment.CreatedAt),
|
cursor.FormatTime(firstComment.CreatedAt),
|
||||||
firstComment.ID,
|
firstComment.ID,
|
||||||
cursor.SortByCreatedAtDesc,
|
cursor.SortByCreatedAtAsc,
|
||||||
).Encode()
|
).Encode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -148,11 +148,22 @@ func (r *postRepository) UpdateWithImages(post *model.Post, images *[]string) er
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, url := range *images {
|
for i, imageData := range *images {
|
||||||
|
parts := strings.Split(imageData, "|")
|
||||||
|
url := parts[0]
|
||||||
|
var previewURL, previewURLLarge string
|
||||||
|
if len(parts) >= 2 && parts[1] != "" {
|
||||||
|
previewURL = parts[1]
|
||||||
|
}
|
||||||
|
if len(parts) >= 3 && parts[2] != "" {
|
||||||
|
previewURLLarge = parts[2]
|
||||||
|
}
|
||||||
image := &model.PostImage{
|
image := &model.PostImage{
|
||||||
PostID: post.ID,
|
PostID: post.ID,
|
||||||
URL: url,
|
URL: url,
|
||||||
SortOrder: i,
|
PreviewURL: previewURL,
|
||||||
|
PreviewURLLarge: previewURLLarge,
|
||||||
|
SortOrder: i,
|
||||||
}
|
}
|
||||||
if err := tx.Create(image).Error; err != nil {
|
if err := tx.Create(image).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -695,11 +706,23 @@ func (r *postRepository) createWithTx(tx *gorm.DB, post *model.Post, images []st
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 创建图片记录
|
// 创建图片记录
|
||||||
for i, url := range images {
|
// 支持格式:["url", "url|preview_url|preview_url_large", ...]
|
||||||
|
for i, imageData := range images {
|
||||||
|
parts := strings.Split(imageData, "|")
|
||||||
|
url := parts[0]
|
||||||
|
var previewURL, previewURLLarge string
|
||||||
|
if len(parts) >= 2 && parts[1] != "" {
|
||||||
|
previewURL = parts[1]
|
||||||
|
}
|
||||||
|
if len(parts) >= 3 && parts[2] != "" {
|
||||||
|
previewURLLarge = parts[2]
|
||||||
|
}
|
||||||
image := &model.PostImage{
|
image := &model.PostImage{
|
||||||
PostID: post.ID,
|
PostID: post.ID,
|
||||||
URL: url,
|
URL: url,
|
||||||
SortOrder: i,
|
PreviewURL: previewURL,
|
||||||
|
PreviewURLLarge: previewURLLarge,
|
||||||
|
SortOrder: i,
|
||||||
}
|
}
|
||||||
if err := tx.Create(image).Error; err != nil {
|
if err := tx.Create(image).Error; err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -256,11 +256,13 @@ func convertPostToAdminListResponse(post *model.Post) dto.AdminPostListResponse
|
|||||||
images := make([]dto.PostImageResponse, len(post.Images))
|
images := make([]dto.PostImageResponse, len(post.Images))
|
||||||
for i, img := range post.Images {
|
for i, img := range post.Images {
|
||||||
images[i] = dto.PostImageResponse{
|
images[i] = dto.PostImageResponse{
|
||||||
ID: img.ID,
|
ID: img.ID,
|
||||||
URL: img.URL,
|
URL: img.URL,
|
||||||
ThumbnailURL: img.ThumbnailURL,
|
ThumbnailURL: img.ThumbnailURL,
|
||||||
Width: img.Width,
|
PreviewURL: img.PreviewURL,
|
||||||
Height: img.Height,
|
PreviewURLLarge: img.PreviewURLLarge,
|
||||||
|
Width: img.Width,
|
||||||
|
Height: img.Height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -298,11 +300,13 @@ func convertPostToAdminDetailResponse(post *model.Post) *dto.AdminPostDetailResp
|
|||||||
images := make([]dto.PostImageResponse, len(post.Images))
|
images := make([]dto.PostImageResponse, len(post.Images))
|
||||||
for i, img := range post.Images {
|
for i, img := range post.Images {
|
||||||
images[i] = dto.PostImageResponse{
|
images[i] = dto.PostImageResponse{
|
||||||
ID: img.ID,
|
ID: img.ID,
|
||||||
URL: img.URL,
|
URL: img.URL,
|
||||||
ThumbnailURL: img.ThumbnailURL,
|
ThumbnailURL: img.ThumbnailURL,
|
||||||
Width: img.Width,
|
PreviewURL: img.PreviewURL,
|
||||||
Height: img.Height,
|
PreviewURLLarge: img.PreviewURLLarge,
|
||||||
|
Width: img.Width,
|
||||||
|
Height: img.Height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user