feat: 完成前端业务闭环与后端联调
This commit is contained in:
@@ -0,0 +1,218 @@
|
||||
import { normalizeGenealogyPathId } from './genealogy-contract.js'
|
||||
import { normalizeResourcePathId } from './request-normalizers.js'
|
||||
import { createRequestError, requestStrict } from './request-client.js'
|
||||
import {
|
||||
normalizePlatformVideoPlacement,
|
||||
normalizePlatformVideos
|
||||
} from './family-media-contract.js'
|
||||
import {
|
||||
VIDEO_COMMENT_LEVEL,
|
||||
normalizeCreatedPlatformVideoComment,
|
||||
normalizeCreatedVideoComment,
|
||||
normalizePlatformVideoComments,
|
||||
normalizeVideoCommentPayload,
|
||||
normalizeVideoComments
|
||||
} from './video-comment-contract.js'
|
||||
import {
|
||||
normalizeMemberPermissionAssignment,
|
||||
normalizeMemberPermissionPayload,
|
||||
normalizePermissionCatalog
|
||||
} from './genealogy-permission-contract.js'
|
||||
|
||||
const assertPage = (value, label) => {
|
||||
if (!value || typeof value !== 'object' || !Array.isArray(value.rows) || !Number.isSafeInteger(value.total)) {
|
||||
throw createRequestError(`${label}响应无效`, 'PAGE_RESPONSE_INVALID')
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
const assertCompleteness = (value) => {
|
||||
const isCount = (count) => Number.isSafeInteger(count) && count >= 0
|
||||
if (
|
||||
!value ||
|
||||
typeof value !== 'object' ||
|
||||
!isCount(value.totalCount) ||
|
||||
value.totalCount === 0 ||
|
||||
!isCount(value.completedCount) ||
|
||||
value.completedCount > value.totalCount ||
|
||||
!Number.isSafeInteger(value.completionRate) ||
|
||||
value.completionRate < 0 ||
|
||||
value.completionRate > 100 ||
|
||||
!Array.isArray(value.missingItems)
|
||||
) {
|
||||
throw createRequestError('资料完整度响应无效', 'COMPLETENESS_RESPONSE_INVALID')
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
export const genealogyCapabilityApi = {
|
||||
async getCompleteness(genealogyId, requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId)
|
||||
const completeness = await requestStrict({ url: `/genealogy/app/genealogies/${id}/completeness`, method: 'GET' }, { requestController: requestOptions.requestController ?? null })
|
||||
return assertCompleteness(completeness)
|
||||
},
|
||||
|
||||
async getRecyclePage(genealogyId, query = {}, requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId)
|
||||
const page = await requestStrict({ url: `/genealogy/app/genealogies/${id}/recycle-bin/page`, method: 'GET', data: query }, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
return assertPage(page, '回收站')
|
||||
},
|
||||
|
||||
async restoreRecycleItem(genealogyId, resourceType, resourceId, requestOptions = {}) {
|
||||
if (typeof resourceType !== 'string' || !resourceType.trim()) throw new TypeError('资源类型不能为空')
|
||||
const id = normalizeGenealogyPathId(genealogyId)
|
||||
const resource = normalizeResourcePathId(resourceId, '资源标识')
|
||||
return requestStrict({ url: `/genealogy/app/genealogies/${id}/recycle-bin/${encodeURIComponent(resourceType.trim())}/${resource}/restore`, method: 'PUT' }, { requestController: requestOptions.requestController ?? null })
|
||||
},
|
||||
|
||||
async getPermissionCatalog(genealogyId, requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId)
|
||||
const catalog = await requestStrict({
|
||||
url: `/genealogy/app/genealogies/${id}/permission-catalog`,
|
||||
method: 'GET'
|
||||
}, { requestController: requestOptions.requestController ?? null })
|
||||
return normalizePermissionCatalog(catalog)
|
||||
},
|
||||
|
||||
async getMemberPermissions(genealogyId, memberId, enabledCodes, requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId); const member = normalizeResourcePathId(memberId, '成员标识')
|
||||
const assignment = await requestStrict({ url: `/genealogy/app/genealogies/${id}/members/${member}/permissions`, method: 'GET' }, { requestController: requestOptions.requestController ?? null })
|
||||
return normalizeMemberPermissionAssignment(assignment, enabledCodes, {
|
||||
expectedGenealogyId: id,
|
||||
expectedMemberId: member
|
||||
})
|
||||
},
|
||||
|
||||
async saveMemberPermissions(genealogyId, memberId, permissionCodes, reason = '', enabledCodes = [], requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId); const member = normalizeResourcePathId(memberId, '成员标识')
|
||||
const assignment = await requestStrict({
|
||||
url: `/genealogy/app/genealogies/${id}/members/${member}/permissions`,
|
||||
method: 'PUT',
|
||||
data: normalizeMemberPermissionPayload(permissionCodes, reason, enabledCodes)
|
||||
}, { requestController: requestOptions.requestController ?? null })
|
||||
return normalizeMemberPermissionAssignment(assignment, enabledCodes, {
|
||||
expectedGenealogyId: id,
|
||||
expectedMemberId: member
|
||||
})
|
||||
},
|
||||
|
||||
async setVideoLike(genealogyId, videoId, liked, requestOptions = {}) {
|
||||
if (typeof liked !== 'boolean') throw new TypeError('点赞状态无效')
|
||||
const id = normalizeGenealogyPathId(genealogyId); const video = normalizeResourcePathId(videoId, '视频标识')
|
||||
return requestStrict({ url: `/genealogy/app/genealogies/${id}/videos/${video}/likes`, method: liked ? 'POST' : 'DELETE' }, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
},
|
||||
|
||||
async getVideoComments(genealogyId, videoId, requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId); const video = normalizeResourcePathId(videoId, '视频标识')
|
||||
const page = assertPage(await requestStrict({
|
||||
url: `/genealogy/app/genealogies/${id}/videos/${video}/comments/page`,
|
||||
method: 'GET',
|
||||
data: { pageNum: 1, pageSize: 100 }
|
||||
}, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
}), '视频评论')
|
||||
return normalizeVideoComments(page.rows, video, { expectedGenealogyId: id })
|
||||
},
|
||||
|
||||
async getVideoCommentReplies(genealogyId, videoId, commentId, requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId)
|
||||
const video = normalizeResourcePathId(videoId, '视频标识')
|
||||
const comment = normalizeResourcePathId(commentId, '父评论标识')
|
||||
const page = assertPage(await requestStrict({
|
||||
url: `/genealogy/app/genealogies/${id}/videos/${video}/comments/${comment}/replies/page`,
|
||||
method: 'GET',
|
||||
data: { pageNum: 1, pageSize: 100 }
|
||||
}, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
}), '视频评论回复')
|
||||
return normalizeVideoComments(page.rows, video, {
|
||||
expectedGenealogyId: id,
|
||||
expectedLevel: VIDEO_COMMENT_LEVEL.REPLY,
|
||||
expectedParentCommentId: comment
|
||||
})
|
||||
},
|
||||
|
||||
async createVideoComment(genealogyId, videoId, content, parentCommentId = null, requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId); const video = normalizeResourcePathId(videoId, '视频标识')
|
||||
const payload = normalizeVideoCommentPayload({
|
||||
commentContent: content,
|
||||
...(parentCommentId ? { parentCommentId } : {})
|
||||
})
|
||||
const comment = await requestStrict({
|
||||
url: `/genealogy/app/genealogies/${id}/videos/${video}/comments`,
|
||||
method: 'POST',
|
||||
data: payload
|
||||
}, { requestController: requestOptions.requestController ?? null })
|
||||
return normalizeCreatedVideoComment(comment, video, {
|
||||
expectedGenealogyId: id,
|
||||
expectedLevel: parentCommentId ? VIDEO_COMMENT_LEVEL.REPLY : VIDEO_COMMENT_LEVEL.ROOT,
|
||||
expectedParentCommentId: payload.parentCommentId || ''
|
||||
})
|
||||
},
|
||||
|
||||
async deleteVideoComment(genealogyId, videoId, commentId, requestOptions = {}) {
|
||||
const id = normalizeGenealogyPathId(genealogyId); const video = normalizeResourcePathId(videoId, '视频标识'); const comment = normalizeResourcePathId(commentId, '评论标识')
|
||||
return requestStrict({ url: `/genealogy/app/genealogies/${id}/videos/${video}/comments/${comment}`, method: 'DELETE' }, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
},
|
||||
|
||||
async getPlatformVideos(placement, requestOptions = {}) {
|
||||
const normalizedPlacement = normalizePlatformVideoPlacement(placement)
|
||||
const videos = await requestStrict({
|
||||
url: '/genealogy/app/platform-videos',
|
||||
method: 'GET',
|
||||
data: { placement: normalizedPlacement }
|
||||
}, {
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
return normalizePlatformVideos(videos, normalizedPlacement)
|
||||
},
|
||||
|
||||
async setPlatformVideoLike(videoId, liked, requestOptions = {}) {
|
||||
if (typeof liked !== 'boolean') throw new TypeError('点赞状态无效')
|
||||
return requestStrict({ url: `/genealogy/app/platform-videos/${normalizeResourcePathId(videoId, '平台视频标识')}/likes`, method: liked ? 'POST' : 'DELETE' }, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
},
|
||||
|
||||
async getPlatformVideoComments(videoId, requestOptions = {}) {
|
||||
const video = normalizeResourcePathId(videoId, '平台视频标识')
|
||||
const comments = await requestStrict({ url: `/genealogy/app/platform-videos/${video}/comments`, method: 'GET' }, {
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
return normalizePlatformVideoComments(comments, video)
|
||||
},
|
||||
|
||||
async createPlatformVideoComment(videoId, content, requestOptions = {}) {
|
||||
const video = normalizeResourcePathId(videoId, '平台视频标识')
|
||||
const payload = normalizeVideoCommentPayload({ commentContent: content })
|
||||
const comment = await requestStrict({ url: `/genealogy/app/platform-videos/${video}/comments`, method: 'POST', data: payload }, {
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
return normalizeCreatedPlatformVideoComment(comment, video)
|
||||
},
|
||||
|
||||
async deletePlatformVideoComment(videoId, commentId, requestOptions = {}) {
|
||||
const video = normalizeResourcePathId(videoId, '平台视频标识')
|
||||
const comment = normalizeResourcePathId(commentId, '平台视频评论标识')
|
||||
await requestStrict({
|
||||
url: `/genealogy/app/platform-videos/${video}/comments/${comment}`,
|
||||
method: 'DELETE'
|
||||
}, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
return null
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user