feat: 完成前端业务闭环与后端联调
This commit is contained in:
@@ -0,0 +1,189 @@
|
||||
import { createRequestError } from './request-client.js'
|
||||
import {
|
||||
normalizeNormalDisableResponseStatus,
|
||||
normalizeOptionalNonnegativeInteger
|
||||
} from './response-normalizers.js'
|
||||
import { assertPlainPayload } from './request-normalizers.js'
|
||||
|
||||
export const VIDEO_COMMENT_LEVEL = Object.freeze({
|
||||
ROOT: 'root',
|
||||
REPLY: 'reply'
|
||||
})
|
||||
|
||||
const commentLevels = new Set(Object.values(VIDEO_COMMENT_LEVEL))
|
||||
|
||||
const normalizeCommentId = (value, label) => {
|
||||
if (typeof value === 'string' && /^[1-9]\d*$/.test(value)) return value
|
||||
if (typeof value === 'number' && Number.isSafeInteger(value) && value > 0) return String(value)
|
||||
throw createRequestError(`视频评论${label}无效`, 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
|
||||
const normalizeCommentText = (value, label, { required = false } = {}) => {
|
||||
if (value === undefined || value === null) {
|
||||
if (required) throw createRequestError(`视频评论缺少${label}`, 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
return ''
|
||||
}
|
||||
if (typeof value !== 'string') {
|
||||
throw createRequestError(`视频评论${label}无效`, 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
const normalized = value.trim()
|
||||
if (required && !normalized) {
|
||||
throw createRequestError(`视频评论缺少${label}`, 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
|
||||
const normalizeParentCommentId = (value) => {
|
||||
if (value === undefined || value === null || value === 0) return null
|
||||
return normalizeCommentId(value, '父评论标识')
|
||||
}
|
||||
|
||||
const normalizeVideoComment = (
|
||||
item,
|
||||
expectedVideoId,
|
||||
{ expectedGenealogyId = '', expectedLevel = '', expectedParentCommentId = '' } = {}
|
||||
) => {
|
||||
if (!item || typeof item !== 'object' || Array.isArray(item)) {
|
||||
throw createRequestError('视频评论响应包含无效条目', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
const videoId = normalizeCommentId(item.videoId, '视频标识')
|
||||
if (videoId !== expectedVideoId) {
|
||||
throw createRequestError('视频评论归属与请求视频不匹配', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
if (expectedGenealogyId) {
|
||||
const genealogyId = normalizeCommentId(item.genealogyId, '家谱标识')
|
||||
if (genealogyId !== expectedGenealogyId) {
|
||||
throw createRequestError('视频评论归属与请求家谱不匹配', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
} else if (item.genealogyId !== undefined && item.genealogyId !== null) {
|
||||
throw createRequestError('平台视频评论不能携带家谱归属', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
|
||||
const parentCommentId = normalizeParentCommentId(item.parentCommentId)
|
||||
const declaredLevel = normalizeCommentText(item.commentLevel, '层级')
|
||||
const level = declaredLevel || (parentCommentId ? VIDEO_COMMENT_LEVEL.REPLY : VIDEO_COMMENT_LEVEL.ROOT)
|
||||
if (!commentLevels.has(level) || (expectedLevel && level !== expectedLevel)) {
|
||||
throw createRequestError('视频评论层级无效', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
if (
|
||||
(level === VIDEO_COMMENT_LEVEL.ROOT && parentCommentId !== null) ||
|
||||
(level === VIDEO_COMMENT_LEVEL.REPLY && parentCommentId === null) ||
|
||||
(expectedParentCommentId && parentCommentId !== expectedParentCommentId)
|
||||
) {
|
||||
throw createRequestError('视频评论父级与层级不匹配', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
const deletedStatus = item.userDeleted
|
||||
if (deletedStatus !== '0' && deletedStatus !== '1') {
|
||||
throw createRequestError('视频评论删除状态无效', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
if (typeof item.canDelete !== 'boolean') {
|
||||
throw createRequestError('视频评论删除权限无效', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
const userDeleted = deletedStatus === '1'
|
||||
return {
|
||||
id: normalizeCommentId(item.commentId, '标识'),
|
||||
author: normalizeCommentText(item.appUserNickName, '用户昵称') || '未署名成员',
|
||||
content: userDeleted
|
||||
? '该评论已删除'
|
||||
: normalizeCommentText(item.commentContent, '内容', { required: true }),
|
||||
time: normalizeCommentText(item.createTime, '创建时间', { required: true }),
|
||||
parentCommentId,
|
||||
parentAuthor: normalizeCommentText(item.parentAppUserNickName, '被回复用户昵称'),
|
||||
level,
|
||||
userDeleted,
|
||||
canDelete: item.canDelete,
|
||||
replyCount: normalizeOptionalNonnegativeInteger(
|
||||
item.replyCount,
|
||||
'视频评论回复数',
|
||||
'VIDEO_COMMENT_RESPONSE_INVALID'
|
||||
),
|
||||
status: normalizeNormalDisableResponseStatus(
|
||||
item.status,
|
||||
'视频评论状态',
|
||||
'VIDEO_COMMENT_RESPONSE_INVALID'
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export const normalizeVideoComments = (
|
||||
value,
|
||||
expectedVideoId,
|
||||
options = {}
|
||||
) => {
|
||||
if (!Array.isArray(value)) {
|
||||
throw createRequestError('视频评论响应不是列表', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
const comments = value.map((item) => normalizeVideoComment(item, expectedVideoId, options))
|
||||
if (new Set(comments.map((comment) => comment.id)).size !== comments.length) {
|
||||
throw createRequestError('视频评论响应包含重复标识', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
return comments
|
||||
}
|
||||
|
||||
export const normalizeCreatedVideoComment = (
|
||||
value,
|
||||
expectedVideoId,
|
||||
options = {}
|
||||
) => normalizeVideoComment(value, expectedVideoId, options)
|
||||
|
||||
const normalizePlatformVideoComment = (item, expectedVideoId) => {
|
||||
if (!item || typeof item !== 'object' || Array.isArray(item)) {
|
||||
throw createRequestError('平台视频评论响应包含无效条目', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
const videoId = normalizeCommentId(item.platformVideoId, '平台视频标识')
|
||||
if (videoId !== expectedVideoId || normalizeParentCommentId(item.parentCommentId) !== null) {
|
||||
throw createRequestError('平台视频评论归属或层级无效', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
if (item.userDeleted !== '0' && item.userDeleted !== '1') {
|
||||
throw createRequestError('平台视频评论删除状态无效', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
if (typeof item.canDelete !== 'boolean') {
|
||||
throw createRequestError('平台视频评论删除权限无效', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
const userDeleted = item.userDeleted === '1'
|
||||
return {
|
||||
id: normalizeCommentId(item.commentId, '标识'),
|
||||
author: normalizeCommentText(item.appUserNickName, '用户昵称') || '未署名用户',
|
||||
content: userDeleted
|
||||
? '该评论已删除'
|
||||
: normalizeCommentText(item.commentContent, '内容', { required: true }),
|
||||
time: normalizeCommentText(item.createTime, '创建时间', { required: true }),
|
||||
parentCommentId: null,
|
||||
parentAuthor: '',
|
||||
level: VIDEO_COMMENT_LEVEL.ROOT,
|
||||
userDeleted,
|
||||
canDelete: item.canDelete,
|
||||
replyCount: 0,
|
||||
status: '0'
|
||||
}
|
||||
}
|
||||
|
||||
export const normalizePlatformVideoComments = (value, expectedVideoId) => {
|
||||
if (!Array.isArray(value)) {
|
||||
throw createRequestError('平台视频评论响应不是列表', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
const comments = value.map((item) => normalizePlatformVideoComment(item, expectedVideoId))
|
||||
if (new Set(comments.map((comment) => comment.id)).size !== comments.length) {
|
||||
throw createRequestError('平台视频评论响应包含重复标识', 'VIDEO_COMMENT_RESPONSE_INVALID')
|
||||
}
|
||||
return comments
|
||||
}
|
||||
|
||||
export const normalizeCreatedPlatformVideoComment = (value, expectedVideoId) =>
|
||||
normalizePlatformVideoComment(value, expectedVideoId)
|
||||
|
||||
export const normalizeVideoCommentPayload = (payload) => {
|
||||
assertPlainPayload(payload, new Set(['parentCommentId', 'commentContent']), '视频评论请求')
|
||||
if (typeof payload.commentContent !== 'string' || !payload.commentContent.trim()) {
|
||||
throw new TypeError('视频评论内容不能为空')
|
||||
}
|
||||
const commentContent = payload.commentContent.trim()
|
||||
if (Array.from(commentContent).length > 1000) {
|
||||
throw new TypeError('视频评论不能超过 1000 个字符')
|
||||
}
|
||||
const normalizedPayload = { commentContent }
|
||||
if (payload.parentCommentId !== undefined && payload.parentCommentId !== null) {
|
||||
normalizedPayload.parentCommentId = normalizeCommentId(payload.parentCommentId, '父评论标识')
|
||||
}
|
||||
return normalizedPayload
|
||||
}
|
||||
Reference in New Issue
Block a user