待测试
This commit is contained in:
+184
-46
@@ -479,12 +479,19 @@ const normalizeProfileAvatar = (value) => {
|
||||
return Number.isSafeInteger(numericValue) ? numericValue : null
|
||||
}
|
||||
|
||||
const normalizeProfileUserId = (value) => {
|
||||
if (value === undefined || value === null || value === '') return ''
|
||||
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('个人资料字段 userId 无效', 'PROFILE_RESPONSE_INVALID')
|
||||
}
|
||||
|
||||
const normalizeAppProfile = (payload) => {
|
||||
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
||||
throw createRequestError('个人资料响应格式无效', 'PROFILE_RESPONSE_INVALID')
|
||||
}
|
||||
return {
|
||||
userId: normalizeProfileAvatar(payload.userId),
|
||||
userId: normalizeProfileUserId(payload.userId),
|
||||
tenantId: normalizeProfileResponseText(payload.tenantId, 'tenantId'),
|
||||
userNo: normalizeProfileResponseText(payload.userNo, 'userNo'),
|
||||
phone: normalizeProfileResponseText(payload.phone, 'phone'),
|
||||
@@ -524,8 +531,8 @@ const normalizeProfileUpdatePayload = (payload) => {
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'birthday')) {
|
||||
const value = normalizeOptionalAuthText(payload.birthday, 'birthday')
|
||||
if (value) {
|
||||
if (!/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{1,9})?(?:Z|[+-]\d{2}:\d{2})?$/.test(value)) {
|
||||
throw new TypeError('birthday 必须是 ISO 日期时间')
|
||||
if (!/^\d{4}-\d{2}-\d{2}$/.test(value)) {
|
||||
throw new TypeError('birthday 必须是 yyyy-MM-dd 日期')
|
||||
}
|
||||
normalized.birthday = value
|
||||
}
|
||||
@@ -633,6 +640,13 @@ const normalizeUploadOssId = (value, field) => {
|
||||
return id
|
||||
}
|
||||
|
||||
const normalizeOssIdString = (value, field) => {
|
||||
if (typeof value !== 'string' || !/^[1-9]\d*$/.test(value)) {
|
||||
throw new TypeError(`${field} 必须是正整数 OSS ID 字符串`)
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
const normalizeResumableInitResult = (payload) => {
|
||||
if (!payload || typeof payload !== 'object' || Array.isArray(payload)) {
|
||||
throw createRequestError('文件初始化响应格式无效', 'FILE_RESPONSE_INVALID')
|
||||
@@ -838,13 +852,7 @@ const normalizeGenealogyCreatePayload = (payload) => {
|
||||
if (value) normalized[field] = value
|
||||
}
|
||||
if (payload.coverOssId !== undefined && payload.coverOssId !== null && payload.coverOssId !== '') {
|
||||
const numericOssId = typeof payload.coverOssId === 'number'
|
||||
? payload.coverOssId
|
||||
: Number(payload.coverOssId)
|
||||
if (!Number.isSafeInteger(numericOssId) || numericOssId <= 0) {
|
||||
throw new TypeError('创建家谱字段 coverOssId 必须是正整数')
|
||||
}
|
||||
normalized.coverOssId = numericOssId
|
||||
normalized.coverOssId = normalizeOssIdString(payload.coverOssId, '创建家谱字段 coverOssId')
|
||||
}
|
||||
return normalized
|
||||
}
|
||||
@@ -887,13 +895,7 @@ const normalizeGenealogyUpdatePayload = (payload) => {
|
||||
if (value) normalized[field] = value
|
||||
}
|
||||
if (Object.prototype.hasOwnProperty.call(payload, 'coverOssId') && payload.coverOssId !== null && payload.coverOssId !== '') {
|
||||
const numericOssId = typeof payload.coverOssId === 'number'
|
||||
? payload.coverOssId
|
||||
: Number(payload.coverOssId)
|
||||
if (!Number.isSafeInteger(numericOssId) || numericOssId <= 0) {
|
||||
throw new TypeError('更新家谱字段 coverOssId 必须是正整数')
|
||||
}
|
||||
normalized.coverOssId = numericOssId
|
||||
normalized.coverOssId = normalizeOssIdString(payload.coverOssId, '更新家谱字段 coverOssId')
|
||||
}
|
||||
if (!Object.keys(normalized).length) throw new TypeError('请至少填写一项需要更新的家谱信息')
|
||||
return normalized
|
||||
@@ -1082,14 +1084,28 @@ const lineageDatePart = (value, label) => {
|
||||
const normalized = normalizeLineageText(value, label)
|
||||
if (!normalized) return ''
|
||||
if (!/^\d{4}-\d{2}-\d{2}/.test(normalized)) throw lineageTreeError(`世系树${label}无效`)
|
||||
return normalized.slice(0, 10)
|
||||
if (normalized.length === 10) return normalized
|
||||
const instant = new Date(normalized)
|
||||
if (Number.isNaN(instant.getTime())) throw lineageTreeError(`世系树${label}无效`)
|
||||
const parts = Object.fromEntries(
|
||||
new Intl.DateTimeFormat('en-CA', {
|
||||
timeZone: 'Asia/Shanghai',
|
||||
year: 'numeric',
|
||||
month: '2-digit',
|
||||
day: '2-digit'
|
||||
}).formatToParts(instant)
|
||||
.filter((part) => part.type !== 'literal')
|
||||
.map((part) => [part.type, part.value])
|
||||
)
|
||||
return `${parts.year}-${parts.month}-${parts.day}`
|
||||
}
|
||||
|
||||
const normalizeLineageTree = (value) => {
|
||||
if (!Array.isArray(value)) throw lineageTreeError('世系树响应不是列表')
|
||||
const seen = new Set()
|
||||
const normalized = []
|
||||
const appendNode = (node, parentId, relationOverride = '') => {
|
||||
const normalizedById = new Map()
|
||||
const appendNode = (node, parentId, relationOverride = '', spouseOf = '') => {
|
||||
if (!node || typeof node !== 'object' || Array.isArray(node)) {
|
||||
throw lineageTreeError('世系树包含无效节点')
|
||||
}
|
||||
@@ -1101,16 +1117,19 @@ const normalizeLineageTree = (value) => {
|
||||
throw lineageTreeError('世系树人物世代无效')
|
||||
}
|
||||
const generationName = normalizeLineageText(node.generationName, '字辈')
|
||||
const relationName = normalizeLineageText(node.relationName, '人物关系')
|
||||
const birthDate = lineageDatePart(node.birthDate, '出生日期')
|
||||
const deathDate = lineageDatePart(node.deathDate, '逝世日期')
|
||||
normalized.push({
|
||||
const normalizedNode = {
|
||||
id,
|
||||
parentId,
|
||||
...(spouseOf ? { spouseOf } : {}),
|
||||
name: normalizeLineageText(node.name, '人物姓名', { required: true }),
|
||||
relation:
|
||||
relationOverride ||
|
||||
normalizeLineageText(node.relationName, '人物关系') ||
|
||||
(parentId ? '后代' : '始祖'),
|
||||
(parentId
|
||||
? (relationName && relationName !== '配偶' ? relationName : '后代')
|
||||
: relationName || '始祖'),
|
||||
generation: node.generation,
|
||||
branch: generationName
|
||||
? (generationName.endsWith('字辈') ? generationName : `${generationName}字辈`)
|
||||
@@ -1121,19 +1140,38 @@ const normalizeLineageTree = (value) => {
|
||||
: '生卒待补',
|
||||
sex: normalizeLineageText(node.sex, '性别'),
|
||||
personStatus: normalizeLineageText(node.personStatus, '人物状态')
|
||||
})
|
||||
}
|
||||
normalized.push(normalizedNode)
|
||||
normalizedById.set(id, normalizedNode)
|
||||
return id
|
||||
}
|
||||
const walk = (node, parentId = null, depth = 0) => {
|
||||
if (depth > 64) throw lineageTreeError('世系树深度超出客户端上限')
|
||||
const id = appendNode(node, parentId)
|
||||
if (!node || typeof node !== 'object' || Array.isArray(node)) {
|
||||
throw lineageTreeError('世系树包含无效节点')
|
||||
}
|
||||
const spouses = node.spouses ?? []
|
||||
const children = node.children ?? []
|
||||
if (!Array.isArray(spouses) || !Array.isArray(children)) {
|
||||
throw lineageTreeError('世系树亲属集合无效')
|
||||
}
|
||||
spouses.forEach((spouse) => appendNode(spouse, parentId, '配偶'))
|
||||
children.forEach((child) => walk(child, id, depth + 1))
|
||||
const id = normalizeLineagePersonId(node.personId)
|
||||
const knownSpouseId = spouses
|
||||
.map((spouse) => normalizeLineagePersonId(spouse?.personId))
|
||||
.find((spouseId) => normalizedById.has(spouseId)) || ''
|
||||
if (seen.has(id)) {
|
||||
if (knownSpouseId) return id
|
||||
throw lineageTreeError('世系树包含重复人物标识')
|
||||
}
|
||||
const knownSpouse = knownSpouseId ? normalizedById.get(knownSpouseId) : null
|
||||
const nodeParentId = knownSpouse ? knownSpouse.parentId : parentId
|
||||
const appendedId = appendNode(node, nodeParentId, knownSpouse ? '配偶' : '', knownSpouseId)
|
||||
spouses.forEach((spouse) => {
|
||||
const spouseId = normalizeLineagePersonId(spouse?.personId)
|
||||
if (seen.has(spouseId)) return
|
||||
appendNode(spouse, nodeParentId, '配偶', appendedId)
|
||||
})
|
||||
children.forEach((child) => walk(child, knownSpouseId || appendedId, depth + 1))
|
||||
}
|
||||
value.forEach((root) => walk(root))
|
||||
return normalized
|
||||
@@ -1148,6 +1186,11 @@ const normalizeLineagePersonIdentity = (value, label) => {
|
||||
throw lineagePersonError(`成员详情${label}无效`)
|
||||
}
|
||||
|
||||
const normalizeOptionalLineagePersonIdentity = (value, label) => {
|
||||
if (value === undefined || value === null || value === '') return ''
|
||||
return normalizeLineagePersonIdentity(value, label)
|
||||
}
|
||||
|
||||
const normalizeLineagePersonText = (value, label, { required = false } = {}) => {
|
||||
if (value === undefined || value === null) {
|
||||
if (required) throw lineagePersonError(`成员详情缺少${label}`)
|
||||
@@ -1162,7 +1205,7 @@ const normalizeLineagePersonText = (value, label, { required = false } = {}) =>
|
||||
const normalizeLineagePersonDate = (value, label) => {
|
||||
const normalized = normalizeLineagePersonText(value, label)
|
||||
if (!normalized) return ''
|
||||
if (!/^\d{4}-\d{2}-\d{2}(?:T.*)?$/.test(normalized)) {
|
||||
if (!/^\d{4}-\d{2}-\d{2}(?:[T\s].*)?$/.test(normalized)) {
|
||||
throw lineagePersonError(`成员详情${label}无效`)
|
||||
}
|
||||
const datePart = normalized.slice(0, 10)
|
||||
@@ -1193,8 +1236,17 @@ const normalizeLineagePersonDetail = (
|
||||
throw lineagePersonError('成员详情世代无效')
|
||||
}
|
||||
const name = normalizeLineagePersonText(value.name, '姓名', { required: true })
|
||||
const appUserId = normalizeOptionalLineagePersonIdentity(value.appUserId, '绑定用户标识')
|
||||
const bindingMode = value.bindingMode === undefined || value.bindingMode === null || value.bindingMode === ''
|
||||
? (appUserId ? 'SPECIFIED' : 'NONE')
|
||||
: normalizeLineagePersonText(value.bindingMode, '身份认领方式')
|
||||
if (!['NONE', 'SELF', 'SPECIFIED'].includes(bindingMode)) {
|
||||
throw lineagePersonError('成员详情身份认领方式无效')
|
||||
}
|
||||
const personNo = normalizeLineagePersonText(value.personNo, '人物编号')
|
||||
const generationName = normalizeLineagePersonText(value.generationName, '字辈')
|
||||
const aliasName = normalizeLineagePersonText(value.aliasName, '别名或曾用名')
|
||||
const avatarOssId = normalizeOptionalLineagePersonIdentity(value.avatarOssId, '头像文件标识')
|
||||
const birthDate = normalizeLineagePersonDate(value.birthDate, '出生日期')
|
||||
const deathDate = normalizeLineagePersonDate(value.deathDate, '逝世日期')
|
||||
const birthLunar = normalizeLineagePersonText(value.birthLunar, '出生农历')
|
||||
@@ -1206,6 +1258,10 @@ const normalizeLineagePersonDetail = (
|
||||
const personStatus = normalizeLineagePersonText(value.personStatus, '人物状态')
|
||||
const biography = normalizeLineagePersonText(value.biography, '生平')
|
||||
const remark = normalizeLineagePersonText(value.remark, '备注')
|
||||
const relationName = normalizeLineagePersonText(value.relationName, '关系显示名称')
|
||||
const sortOrder = value.sortOrder === undefined || value.sortOrder === null
|
||||
? null
|
||||
: normalizeOptionalSafeInteger(value.sortOrder, '人物排序值')
|
||||
const relatives = []
|
||||
for (const relation of [
|
||||
{ id: value.fatherId, name: value.fatherName, label: '父亲' },
|
||||
@@ -1227,9 +1283,13 @@ const normalizeLineagePersonDetail = (
|
||||
genealogyId,
|
||||
genealogyName: normalizeLineagePersonText(value.genealogyName, '家谱名称') || '当前家谱',
|
||||
name,
|
||||
appUserId,
|
||||
bindingMode,
|
||||
personNo,
|
||||
aliasName,
|
||||
generation: value.generation,
|
||||
generationName,
|
||||
avatarOssId,
|
||||
relation: value.generation === 1 ? '始祖' : '家谱成员',
|
||||
branch: generationName
|
||||
? (generationName.endsWith('字辈') ? generationName : `${generationName}字辈`)
|
||||
@@ -1247,6 +1307,8 @@ const normalizeLineagePersonDetail = (
|
||||
personStatus,
|
||||
biography,
|
||||
remark,
|
||||
relationName,
|
||||
sortOrder,
|
||||
status: ['DECEASED', 'DEAD'].includes(personStatus.toUpperCase()) ? 'deceased' : 'normal',
|
||||
relatives
|
||||
}
|
||||
@@ -1376,8 +1438,8 @@ const normalizeFamilyFeedRows = (value, expectedGenealogyId) => {
|
||||
if (genealogyId && genealogyId !== expectedGenealogyId) {
|
||||
throw createRequestError('家族动态归属与请求不匹配', 'FEED_RESPONSE_INVALID')
|
||||
}
|
||||
const id = normalizeOptionalNumericId(item.feedId ?? item.id, '动态标识', 'FEED_RESPONSE_INVALID')
|
||||
const content = normalizeOptionalGenealogyText(item.feedContent ?? item.content, 'feedContent')
|
||||
const id = normalizeOptionalNumericId(item.feedId, '动态标识', 'FEED_RESPONSE_INVALID')
|
||||
const content = normalizeOptionalGenealogyText(item.feedContent, 'feedContent')
|
||||
if (!id || !content) {
|
||||
throw createRequestError('家族动态响应缺少标识或内容', 'FEED_RESPONSE_INVALID')
|
||||
}
|
||||
@@ -1385,14 +1447,14 @@ const normalizeFamilyFeedRows = (value, expectedGenealogyId) => {
|
||||
id,
|
||||
genealogyId: expectedGenealogyId,
|
||||
content,
|
||||
publisher: normalizeOptionalGenealogyText(item.publisherNickName ?? item.author, 'publisherNickName') || '家族成员',
|
||||
type: normalizeOptionalGenealogyText(item.feedType ?? item.tag, 'feedType') || '文字动态',
|
||||
time: normalizeOptionalGenealogyText(item.createTime ?? item.time, 'createTime'),
|
||||
publisher: normalizeOptionalGenealogyText(item.publisherNickName, 'publisherNickName') || '家族成员',
|
||||
type: normalizeOptionalGenealogyText(item.feedType, 'feedType') || '文字动态',
|
||||
time: normalizeOptionalGenealogyText(item.createTime, 'createTime'),
|
||||
mediaOssIds: normalizeOptionalGenealogyText(item.mediaOssIds, 'mediaOssIds'),
|
||||
likeCount: normalizeOptionalNonnegativeInteger(item.likeCount, '动态点赞数', 'FEED_RESPONSE_INVALID'),
|
||||
commentCount: normalizeOptionalNonnegativeInteger(item.commentCount, '动态评论数', 'FEED_RESPONSE_INVALID'),
|
||||
likedByMe: typeof item.likedByMe === 'boolean' ? item.likedByMe : null,
|
||||
pinned: item.pinned === true
|
||||
pinned: normalizeOptionalGenealogyText(item.pinned, 'pinned')
|
||||
}
|
||||
})
|
||||
if (new Set(rows.map((item) => item.id)).size !== rows.length) {
|
||||
@@ -1475,12 +1537,15 @@ const normalizeArticleCreatePayload = (payload) => {
|
||||
const value = normalizeOptionalAuthText(payload[field], field)
|
||||
if (value) data[field] = value
|
||||
}
|
||||
for (const field of ['categoryId', 'coverOssId', 'sortOrder']) {
|
||||
for (const field of ['categoryId', 'sortOrder']) {
|
||||
if (payload[field] === undefined || payload[field] === null || payload[field] === '') continue
|
||||
const value = typeof payload[field] === 'number' ? payload[field] : Number(payload[field])
|
||||
if (!Number.isSafeInteger(value)) throw new TypeError(`${field} 必须是安全整数`)
|
||||
data[field] = value
|
||||
}
|
||||
if (payload.coverOssId !== undefined && payload.coverOssId !== null && payload.coverOssId !== '') {
|
||||
data.coverOssId = normalizeOssIdString(payload.coverOssId, 'coverOssId')
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
@@ -1495,7 +1560,10 @@ const normalizeAlbumCreatePayload = (payload) => {
|
||||
const value = normalizeOptionalAuthText(payload[field], field)
|
||||
if (value) data[field] = value
|
||||
}
|
||||
for (const field of ['coverOssId', 'sortOrder']) {
|
||||
if (payload.coverOssId !== undefined && payload.coverOssId !== null && payload.coverOssId !== '') {
|
||||
data.coverOssId = normalizeOssIdString(payload.coverOssId, 'coverOssId')
|
||||
}
|
||||
for (const field of ['sortOrder']) {
|
||||
if (payload[field] === undefined || payload[field] === null || payload[field] === '') continue
|
||||
const value = typeof payload[field] === 'number' ? payload[field] : Number(payload[field])
|
||||
if (!Number.isSafeInteger(value)) throw new TypeError(`${field} 必须是安全整数`)
|
||||
@@ -1507,8 +1575,7 @@ const normalizeAlbumCreatePayload = (payload) => {
|
||||
const normalizeAlbumPhotoCreatePayload = (payload) => {
|
||||
const allowedFields = new Set(['ossId', 'photoTitle', 'photoDesc', 'photographer', 'shootTime', 'sortOrder', 'status'])
|
||||
assertPlainPayload(payload, allowedFields, '相册照片请求')
|
||||
const ossId = normalizeOptionalSafeInteger(payload.ossId, 'ossId')
|
||||
if (!ossId || ossId < 1) throw new TypeError('相册照片需要真实上传回执中的 ossId')
|
||||
const ossId = normalizeOssIdString(payload.ossId, '相册照片 ossId')
|
||||
const data = { ossId }
|
||||
for (const field of ['photoTitle', 'photoDesc', 'photographer', 'shootTime', 'status']) {
|
||||
const value = normalizeOptionalAuthText(payload[field], field)
|
||||
@@ -1530,9 +1597,12 @@ const normalizeCeremonyPayload = (payload) => {
|
||||
const value = normalizeOptionalAuthText(payload[field], field)
|
||||
if (value) data[field] = value
|
||||
}
|
||||
for (const field of ['coverOssId', 'sortOrder']) {
|
||||
const value = normalizeOptionalSafeInteger(payload[field], field)
|
||||
if (value !== undefined) data[field] = value
|
||||
if (payload.coverOssId !== undefined && payload.coverOssId !== null && payload.coverOssId !== '') {
|
||||
data.coverOssId = normalizeOssIdString(payload.coverOssId, 'coverOssId')
|
||||
}
|
||||
const sortOrder = normalizeOptionalSafeInteger(payload.sortOrder, 'sortOrder')
|
||||
if (sortOrder !== undefined) {
|
||||
data.sortOrder = sortOrder
|
||||
}
|
||||
return data
|
||||
}
|
||||
@@ -1657,6 +1727,44 @@ const normalizeResourcePathId = (value, label) => {
|
||||
throw new TypeError(`${label}必须是有效的正整数标识`)
|
||||
}
|
||||
|
||||
const normalizeNotificationText = (value, field) => {
|
||||
if (value === undefined || value === null) return ''
|
||||
if (typeof value !== 'string') {
|
||||
throw createRequestError(`通知详情字段 ${field} 无效`, 'NOTIFICATION_DETAIL_RESPONSE_INVALID')
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
const normalizeNotificationDetail = (value, expectedNotificationId) => {
|
||||
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
||||
throw createRequestError('通知详情响应格式无效', 'NOTIFICATION_DETAIL_RESPONSE_INVALID')
|
||||
}
|
||||
const notificationId = normalizeOptionalNumericId(value.notificationId, '通知标识', 'NOTIFICATION_DETAIL_RESPONSE_INVALID')
|
||||
if (!notificationId || notificationId !== expectedNotificationId) {
|
||||
throw createRequestError('通知详情响应标识不匹配', 'NOTIFICATION_DETAIL_RESPONSE_INVALID')
|
||||
}
|
||||
return {
|
||||
notificationId,
|
||||
genealogyId: normalizeOptionalNumericId(value.genealogyId, '通知家谱标识', 'NOTIFICATION_DETAIL_RESPONSE_INVALID'),
|
||||
genealogyNo: normalizeNotificationText(value.genealogyNo, 'genealogyNo'),
|
||||
genealogyName: normalizeNotificationText(value.genealogyName, 'genealogyName'),
|
||||
senderUserId: normalizeOptionalNumericId(value.senderUserId, '通知发送人标识', 'NOTIFICATION_DETAIL_RESPONSE_INVALID'),
|
||||
senderNickName: normalizeNotificationText(value.senderNickName, 'senderNickName'),
|
||||
senderPhone: normalizeNotificationText(value.senderPhone, 'senderPhone'),
|
||||
noticeType: normalizeNotificationText(value.noticeType, 'noticeType'),
|
||||
noticeTitle: normalizeNotificationText(value.noticeTitle, 'noticeTitle'),
|
||||
noticeContent: normalizeNotificationText(value.noticeContent, 'noticeContent'),
|
||||
bizType: normalizeNotificationText(value.bizType, 'bizType'),
|
||||
bizId: normalizeOptionalNumericId(value.bizId, '通知关联业务标识', 'NOTIFICATION_DETAIL_RESPONSE_INVALID'),
|
||||
bizSummary: normalizeNotificationText(value.bizSummary, 'bizSummary'),
|
||||
publishTime: normalizeNotificationText(value.publishTime, 'publishTime'),
|
||||
readStatus: normalizeNotificationText(value.readStatus, 'readStatus'),
|
||||
readTime: normalizeNotificationText(value.readTime, 'readTime'),
|
||||
status: normalizeNotificationText(value.status, 'status'),
|
||||
remark: normalizeNotificationText(value.remark, 'remark')
|
||||
}
|
||||
}
|
||||
|
||||
const requireRemoteResource = (label, operation) => {
|
||||
if (hasRemoteConfig()) return
|
||||
throw createRequestError(`${label}${operation}需要真实服务,当前本地预览不会伪造结果`, operation === '读取' ? 'REMOTE_READ_REQUIRED' : 'REMOTE_WRITE_REQUIRED')
|
||||
@@ -1947,6 +2055,7 @@ const normalizeLineageWritePayload = (payload) => {
|
||||
throw new TypeError('人物写入请求必须是普通对象')
|
||||
}
|
||||
const allowedFields = new Set([
|
||||
'bindingMode',
|
||||
'appUserId',
|
||||
'personNo',
|
||||
'name',
|
||||
@@ -1975,16 +2084,29 @@ const normalizeLineageWritePayload = (payload) => {
|
||||
}
|
||||
const name = normalizeLineagePersonText(payload.name, '姓名', { required: true })
|
||||
if (name.length > 20) throw new TypeError('人物姓名长度超出当前页面合同')
|
||||
const data = { name }
|
||||
const bindingMode = normalizeLineagePersonText(payload.bindingMode, '身份认领方式')
|
||||
if (!['NONE', 'SELF', 'SPECIFIED'].includes(bindingMode)) {
|
||||
throw new TypeError('人物身份认领方式必须是 NONE、SELF 或 SPECIFIED')
|
||||
}
|
||||
const data = { bindingMode, name }
|
||||
if (bindingMode === 'SPECIFIED') {
|
||||
if (payload.appUserId === undefined || payload.appUserId === null || payload.appUserId === '') {
|
||||
throw new TypeError('指定业务用户绑定必须提供业务用户标识')
|
||||
}
|
||||
data.appUserId = normalizeLineagePersonIdentity(payload.appUserId, '绑定用户标识')
|
||||
} else if (payload.appUserId !== undefined && payload.appUserId !== null && payload.appUserId !== '') {
|
||||
throw new TypeError(`${bindingMode} 身份认领不能提供业务用户标识`)
|
||||
}
|
||||
for (const [field, label] of [
|
||||
['appUserId', '绑定用户标识'],
|
||||
['fatherId', '父亲标识'],
|
||||
['motherId', '母亲标识'],
|
||||
['avatarOssId', '头像文件标识']
|
||||
['motherId', '母亲标识']
|
||||
]) {
|
||||
if (payload[field] === undefined || payload[field] === null || payload[field] === '') continue
|
||||
data[field] = normalizeLineagePersonIdentity(payload[field], label)
|
||||
}
|
||||
if (payload.avatarOssId !== undefined && payload.avatarOssId !== null && payload.avatarOssId !== '') {
|
||||
data.avatarOssId = normalizeOssIdString(payload.avatarOssId, '头像文件标识')
|
||||
}
|
||||
if (payload.generation !== undefined) {
|
||||
if (!Number.isSafeInteger(payload.generation) || payload.generation < 1) {
|
||||
throw new TypeError('人物世代必须是正安全整数')
|
||||
@@ -2708,13 +2830,14 @@ export const appApi = {
|
||||
if (!hasRemoteConfig()) {
|
||||
throw createRequestError('修改动态需要真实服务,当前本地预览不会伪造保存成功', 'REMOTE_WRITE_REQUIRED')
|
||||
}
|
||||
return requestStrict({
|
||||
const result = await requestStrict({
|
||||
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/feeds/${normalizedFeedId}`,
|
||||
method: 'PUT',
|
||||
data: normalizeFeedCreatePayload(payload)
|
||||
}, {
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
return normalizeFamilyFeed(result, normalizedGenealogyId, normalizedFeedId)
|
||||
},
|
||||
async deleteFeed(genealogyId, feedId, requestOptions = {}) {
|
||||
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
|
||||
@@ -2750,13 +2873,15 @@ export const appApi = {
|
||||
async createFeed(genealogyId, payload, requestOptions = {}) {
|
||||
if (hasRemoteConfig()) {
|
||||
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
|
||||
return requestStrict({
|
||||
const result = await requestStrict({
|
||||
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/feeds`,
|
||||
method: 'POST',
|
||||
data: normalizeFeedCreatePayload(payload)
|
||||
}, {
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
const [feed] = normalizeFamilyFeedRows([result], normalizedGenealogyId)
|
||||
return feed
|
||||
}
|
||||
const error = new Error('动态发布接口尚未接入,当前内容不会保存')
|
||||
error.code = 'WRITE_UNAVAILABLE'
|
||||
@@ -3313,6 +3438,19 @@ export const appApi = {
|
||||
if (!hasRemoteConfig()) return listNotificationFixtures()
|
||||
return readRemoteList('/genealogy/app/notifications', '消息通知', requestOptions)
|
||||
},
|
||||
async getNotificationDetail(notificationId, requestOptions = {}) {
|
||||
const normalizedNotificationId = normalizeResourcePathId(notificationId, '通知标识')
|
||||
if (!hasRemoteConfig()) {
|
||||
throw createRequestError('通知详情需要真实服务读取,当前本地预览不伪造通知正文', 'REMOTE_READ_REQUIRED')
|
||||
}
|
||||
const result = await requestStrict({
|
||||
url: `/genealogy/app/notifications/${normalizedNotificationId}`,
|
||||
method: 'GET'
|
||||
}, {
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
return normalizeNotificationDetail(result, normalizedNotificationId)
|
||||
},
|
||||
async getUnreadNotificationCount(requestOptions = {}) {
|
||||
requireRemoteResource('未读通知数量', '读取')
|
||||
const value = await requestStrict({
|
||||
|
||||
Reference in New Issue
Block a user