fix feed empty list rendering
This commit is contained in:
@@ -37,6 +37,7 @@ func (f *FeedHandler) ListLatest(c *gin.Context) {
|
|||||||
c.JSON(500, gin.H{"error": err.Error()})
|
c.JSON(500, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
feedItems.VideoList = nonNilFeedVideoItems(feedItems.VideoList)
|
||||||
c.JSON(200, feedItems)
|
c.JSON(200, feedItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -85,6 +86,7 @@ func (f *FeedHandler) ListLikesCount(c *gin.Context) {
|
|||||||
c.JSON(500, gin.H{"error": err.Error()})
|
c.JSON(500, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
feedItems.VideoList = nonNilFeedVideoItems(feedItems.VideoList)
|
||||||
c.JSON(200, feedItems)
|
c.JSON(200, feedItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -110,6 +112,7 @@ func (f *FeedHandler) ListByFollowing(c *gin.Context) {
|
|||||||
c.JSON(500, gin.H{"error": err.Error()})
|
c.JSON(500, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
feedItems.VideoList = nonNilFeedVideoItems(feedItems.VideoList)
|
||||||
c.JSON(200, feedItems)
|
c.JSON(200, feedItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -160,5 +163,13 @@ func (f *FeedHandler) ListByPopularity(c *gin.Context) {
|
|||||||
c.JSON(500, gin.H{"error": err.Error()})
|
c.JSON(500, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
resp.VideoList = nonNilFeedVideoItems(resp.VideoList)
|
||||||
c.JSON(200, resp)
|
c.JSON(200, resp)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func nonNilFeedVideoItems(items []FeedVideoItem) []FeedVideoItem {
|
||||||
|
if items == nil {
|
||||||
|
return []FeedVideoItem{}
|
||||||
|
}
|
||||||
|
return items
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package social
|
package social
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"feedsystem_video_go/internal/account"
|
||||||
"feedsystem_video_go/internal/middleware/jwt"
|
"feedsystem_video_go/internal/middleware/jwt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
|
||||||
@@ -89,6 +90,9 @@ func (h *SocialHandler) GetAllFollowers(c *gin.Context) {
|
|||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if followers == nil {
|
||||||
|
followers = []*account.Account{}
|
||||||
|
}
|
||||||
c.JSON(http.StatusOK, GetAllFollowersResponse{Followers: followers})
|
c.JSON(http.StatusOK, GetAllFollowersResponse{Followers: followers})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,5 +118,8 @@ func (h *SocialHandler) GetAllVloggers(c *gin.Context) {
|
|||||||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if vloggers == nil {
|
||||||
|
vloggers = []*account.Account{}
|
||||||
|
}
|
||||||
c.JSON(http.StatusOK, GetAllVloggersResponse{Vloggers: vloggers})
|
c.JSON(http.StatusOK, GetAllVloggersResponse{Vloggers: vloggers})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -90,5 +90,8 @@ func (h *CommentHandler) GetAllComments(c *gin.Context) {
|
|||||||
c.JSON(400, gin.H{"error": err.Error()})
|
c.JSON(400, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if comments == nil {
|
||||||
|
comments = []Comment{}
|
||||||
|
}
|
||||||
c.JSON(200, comments)
|
c.JSON(200, comments)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -106,5 +106,8 @@ func (lh *LikeHandler) ListMyLikedVideos(c *gin.Context) {
|
|||||||
c.JSON(500, gin.H{"error": err.Error()})
|
c.JSON(500, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if videos == nil {
|
||||||
|
videos = []Video{}
|
||||||
|
}
|
||||||
c.JSON(200, videos)
|
c.JSON(200, videos)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -207,6 +207,9 @@ func (vh *VideoHandler) ListByAuthorID(c *gin.Context) {
|
|||||||
c.JSON(400, gin.H{"error": err.Error()})
|
c.JSON(400, gin.H{"error": err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if videos == nil {
|
||||||
|
videos = []Video{}
|
||||||
|
}
|
||||||
c.JSON(200, videos)
|
c.JSON(200, videos)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import { postJson } from './client'
|
import { postJson } from './client'
|
||||||
|
import { normalizeCommentList } from './normalize'
|
||||||
import type { Comment, MessageResponse } from './types'
|
import type { Comment, MessageResponse } from './types'
|
||||||
|
|
||||||
export function listAll(videoId: number) {
|
export async function listAll(videoId: number) {
|
||||||
return postJson<Comment[]>('/comment/listAll', { video_id: videoId })
|
const comments = await postJson<Comment[] | null>('/comment/listAll', { video_id: videoId })
|
||||||
|
return normalizeCommentList(comments)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function publish(videoId: number, content: string) {
|
export function publish(videoId: number, content: string) {
|
||||||
|
|||||||
@@ -1,23 +1,28 @@
|
|||||||
import { postJson } from './client'
|
import { postJson } from './client'
|
||||||
|
import { normalizeFeedVideoList } from './normalize'
|
||||||
import type { ListByFollowingResponse, ListByPopularityResponse, ListLatestResponse, ListLikesCountResponse } from './types'
|
import type { ListByFollowingResponse, ListByPopularityResponse, ListLatestResponse, ListLikesCountResponse } from './types'
|
||||||
|
|
||||||
export function listLatest(input: { limit: number; latest_time: number }) {
|
export async function listLatest(input: { limit: number; latest_time: number }) {
|
||||||
return postJson<ListLatestResponse>('/feed/listLatest', input)
|
const res = await postJson<ListLatestResponse>('/feed/listLatest', input)
|
||||||
|
return { ...res, video_list: normalizeFeedVideoList(res.video_list) }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listLikesCount(input: { limit: number; likes_count_before?: number; id_before?: number }) {
|
export async function listLikesCount(input: { limit: number; likes_count_before?: number; id_before?: number }) {
|
||||||
const body: Record<string, unknown> = { limit: input.limit }
|
const body: Record<string, unknown> = { limit: input.limit }
|
||||||
if (typeof input.likes_count_before === 'number' || typeof input.id_before === 'number') {
|
if (typeof input.likes_count_before === 'number' || typeof input.id_before === 'number') {
|
||||||
body.likes_count_before = input.likes_count_before ?? 0
|
body.likes_count_before = input.likes_count_before ?? 0
|
||||||
body.id_before = input.id_before ?? 0
|
body.id_before = input.id_before ?? 0
|
||||||
}
|
}
|
||||||
return postJson<ListLikesCountResponse>('/feed/listLikesCount', body)
|
const res = await postJson<ListLikesCountResponse>('/feed/listLikesCount', body)
|
||||||
|
return { ...res, video_list: normalizeFeedVideoList(res.video_list) }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listByPopularity(input: { limit: number; as_of: number; offset: number }) {
|
export async function listByPopularity(input: { limit: number; as_of: number; offset: number }) {
|
||||||
return postJson<ListByPopularityResponse>('/feed/listByPopularity', input)
|
const res = await postJson<ListByPopularityResponse>('/feed/listByPopularity', input)
|
||||||
|
return { ...res, video_list: normalizeFeedVideoList(res.video_list) }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listByFollowing(input: { limit: number; latest_time: number }) {
|
export async function listByFollowing(input: { limit: number; latest_time: number }) {
|
||||||
return postJson<ListByFollowingResponse>('/feed/listByFollowing', input, { authRequired: true })
|
const res = await postJson<ListByFollowingResponse>('/feed/listByFollowing', input, { authRequired: true })
|
||||||
|
return { ...res, video_list: normalizeFeedVideoList(res.video_list) }
|
||||||
}
|
}
|
||||||
|
|||||||
57
frontend/src/api/normalize.ts
Normal file
57
frontend/src/api/normalize.ts
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
import type { Account, Comment, FeedAuthor, FeedVideoItem, Video } from './types'
|
||||||
|
|
||||||
|
export function listOrEmpty<T>(value: T[] | null | undefined): T[] {
|
||||||
|
return Array.isArray(value) ? value : []
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeAccount(value: Account | null | undefined): Account {
|
||||||
|
return {
|
||||||
|
id: Number(value?.id ?? 0),
|
||||||
|
username: value?.username || '匿名用户',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function normalizeAuthor(value: FeedAuthor | null | undefined): FeedAuthor {
|
||||||
|
return {
|
||||||
|
id: Number(value?.id ?? 0),
|
||||||
|
username: value?.username || '匿名用户',
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeFeedVideoItem(value: FeedVideoItem): FeedVideoItem {
|
||||||
|
return {
|
||||||
|
...value,
|
||||||
|
author: normalizeAuthor(value.author),
|
||||||
|
title: value.title || '未命名视频',
|
||||||
|
description: value.description || '',
|
||||||
|
play_url: value.play_url || '',
|
||||||
|
cover_url: value.cover_url || '',
|
||||||
|
create_time: Number(value.create_time ?? 0),
|
||||||
|
likes_count: Number(value.likes_count ?? 0),
|
||||||
|
is_liked: Boolean(value.is_liked),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeFeedVideoList(value: FeedVideoItem[] | null | undefined): FeedVideoItem[] {
|
||||||
|
return listOrEmpty(value).map(normalizeFeedVideoItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeVideoList(value: Video[] | null | undefined): Video[] {
|
||||||
|
return listOrEmpty(value).map((video) => ({
|
||||||
|
...video,
|
||||||
|
username: video.username || '匿名用户',
|
||||||
|
title: video.title || '未命名视频',
|
||||||
|
description: video.description || '',
|
||||||
|
play_url: video.play_url || '',
|
||||||
|
cover_url: video.cover_url || '',
|
||||||
|
likes_count: Number(video.likes_count ?? 0),
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
export function normalizeCommentList(value: Comment[] | null | undefined): Comment[] {
|
||||||
|
return listOrEmpty(value).map((comment) => ({
|
||||||
|
...comment,
|
||||||
|
username: comment.username || '匿名用户',
|
||||||
|
content: comment.content || '',
|
||||||
|
}))
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { postJson } from './client'
|
import { postJson } from './client'
|
||||||
|
import { listOrEmpty, normalizeAccount } from './normalize'
|
||||||
import type { GetAllFollowersResponse, GetAllVloggersResponse, MessageResponse } from './types'
|
import type { GetAllFollowersResponse, GetAllVloggersResponse, MessageResponse } from './types'
|
||||||
|
|
||||||
export function follow(vloggerId: number) {
|
export function follow(vloggerId: number) {
|
||||||
@@ -9,18 +10,20 @@ export function unfollow(vloggerId: number) {
|
|||||||
return postJson<MessageResponse>('/social/unfollow', { vlogger_id: vloggerId }, { authRequired: true })
|
return postJson<MessageResponse>('/social/unfollow', { vlogger_id: vloggerId }, { authRequired: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAllFollowers(vloggerId?: number) {
|
export async function getAllFollowers(vloggerId?: number) {
|
||||||
return postJson<GetAllFollowersResponse>(
|
const res = await postJson<GetAllFollowersResponse>(
|
||||||
'/social/getAllFollowers',
|
'/social/getAllFollowers',
|
||||||
vloggerId ? { vlogger_id: vloggerId } : {},
|
vloggerId ? { vlogger_id: vloggerId } : {},
|
||||||
{ authRequired: true },
|
{ authRequired: true },
|
||||||
)
|
)
|
||||||
|
return { ...res, followers: listOrEmpty(res.followers).map(normalizeAccount) }
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAllVloggers(followerId?: number) {
|
export async function getAllVloggers(followerId?: number) {
|
||||||
return postJson<GetAllVloggersResponse>(
|
const res = await postJson<GetAllVloggersResponse>(
|
||||||
'/social/getAllVloggers',
|
'/social/getAllVloggers',
|
||||||
followerId ? { follower_id: followerId } : {},
|
followerId ? { follower_id: followerId } : {},
|
||||||
{ authRequired: true },
|
{ authRequired: true },
|
||||||
)
|
)
|
||||||
|
return { ...res, vloggers: listOrEmpty(res.vloggers).map(normalizeAccount) }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { postForm, postJson } from './client'
|
import { postForm, postJson } from './client'
|
||||||
|
import { normalizeVideoList } from './normalize'
|
||||||
import type { Video } from './types'
|
import type { Video } from './types'
|
||||||
|
|
||||||
export function publishVideo(input: { title: string; description: string; play_url: string; cover_url: string }) {
|
export function publishVideo(input: { title: string; description: string; play_url: string; cover_url: string }) {
|
||||||
@@ -19,8 +20,9 @@ export function uploadCover(file: File) {
|
|||||||
return postForm<UploadResponse>('/video/uploadCover', fd, { authRequired: true })
|
return postForm<UploadResponse>('/video/uploadCover', fd, { authRequired: true })
|
||||||
}
|
}
|
||||||
|
|
||||||
export function listByAuthorId(authorId: number) {
|
export async function listByAuthorId(authorId: number) {
|
||||||
return postJson<Video[]>('/video/listByAuthorID', { author_id: authorId })
|
const videos = await postJson<Video[] | null>('/video/listByAuthorID', { author_id: authorId })
|
||||||
|
return normalizeVideoList(videos)
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getDetail(id: number) {
|
export function getDetail(id: number) {
|
||||||
|
|||||||
Reference in New Issue
Block a user