修改未完成
This commit is contained in:
+121
-174
@@ -181,12 +181,6 @@ const request = (options, {
|
||||
if (!settled && requestController) requestController.bind(abortRequest)
|
||||
})
|
||||
|
||||
const authPayload = (payload) => ({
|
||||
clientId: runtimeConfig.clientId,
|
||||
tenantId: runtimeConfig.tenantId,
|
||||
...payload
|
||||
})
|
||||
|
||||
// 已核对接口使用这一严格边界:只接受 HTTP 200 与完整 JSON envelope,
|
||||
// 并统一限制弱网等待时间。尚未逐页治理的旧业务读取仍沿用上方通用 request。
|
||||
const requestStrict = (options, {
|
||||
@@ -241,7 +235,7 @@ const parseStrictUploadResponse = (responseText, requireData) => {
|
||||
}
|
||||
|
||||
const requestNativeFileChunk = ({ uploadId, chunkIndex, chunkMd5, filePath }, { requestController = null } = {}) => new Promise((resolve, reject) => {
|
||||
if (!globalThis.plus?.uploader?.createUpload) {
|
||||
if (typeof globalThis.uni?.uploadFile !== 'function') {
|
||||
reject(createRequestError('当前运行环境不支持文件上传', 'FILE_UPLOAD_UNAVAILABLE'))
|
||||
return
|
||||
}
|
||||
@@ -254,6 +248,7 @@ const requestNativeFileChunk = ({ uploadId, chunkIndex, chunkMd5, filePath }, {
|
||||
}
|
||||
let settled = false
|
||||
let task = null
|
||||
let cancelled = false
|
||||
const release = () => requestController?.release(abort)
|
||||
const resolveOnce = (value) => {
|
||||
if (settled) return
|
||||
@@ -269,34 +264,56 @@ const requestNativeFileChunk = ({ uploadId, chunkIndex, chunkMd5, filePath }, {
|
||||
}
|
||||
const abort = () => {
|
||||
if (settled) return
|
||||
cancelled = true
|
||||
task?.abort?.()
|
||||
rejectOnce(createRequestCancelledError())
|
||||
}
|
||||
const query = `uploadId=${encodeURIComponent(uploadId)}&chunkIndex=${encodeURIComponent(chunkIndex)}&chunkMd5=${encodeURIComponent(chunkMd5)}`
|
||||
const token = session.getToken()
|
||||
try {
|
||||
task = globalThis.plus.uploader.createUpload(
|
||||
`${runtimeConfig.baseUrl}/genealogy/app/files/resumable/chunk?${query}`,
|
||||
{ method: 'POST' },
|
||||
(upload, status) => {
|
||||
if (status !== 200) {
|
||||
rejectOnce(createRequestError(`文件分片上传失败(HTTP ${status})`, 'HTTP_ERROR', { httpStatus: status }))
|
||||
task = globalThis.uni.uploadFile({
|
||||
url: `${runtimeConfig.baseUrl}/genealogy/app/files/resumable/chunk`,
|
||||
filePath,
|
||||
name: 'file',
|
||||
formData: {
|
||||
uploadId,
|
||||
chunkIndex: String(chunkIndex),
|
||||
chunkMd5
|
||||
},
|
||||
header: {
|
||||
clientid: runtimeConfig.clientId,
|
||||
tenantId: runtimeConfig.tenantId,
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {})
|
||||
},
|
||||
timeout: REQUEST_TIMEOUT_MS,
|
||||
success: (upload) => {
|
||||
if (upload.statusCode !== 200) {
|
||||
rejectOnce(createRequestError(`文件分片上传失败(HTTP ${upload.statusCode})`, 'HTTP_ERROR', { httpStatus: upload.statusCode }))
|
||||
return
|
||||
}
|
||||
try {
|
||||
parseStrictUploadResponse(upload.responseText, false)
|
||||
parseStrictUploadResponse(upload.data, false)
|
||||
resolveOnce(null)
|
||||
} catch (error) {
|
||||
rejectOnce(error)
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
if (settled) return
|
||||
if (cancelled) {
|
||||
rejectOnce(createRequestCancelledError())
|
||||
return
|
||||
}
|
||||
const message = typeof error?.errMsg === 'string' && error.errMsg
|
||||
? error.errMsg
|
||||
: '文件分片上传失败'
|
||||
const timeout = /timeout/i.test(message)
|
||||
rejectOnce(createRequestError(
|
||||
timeout ? '文件分片上传超时' : message,
|
||||
timeout ? 'REQUEST_TIMEOUT' : 'UPLOAD_FAILED'
|
||||
))
|
||||
}
|
||||
)
|
||||
task.setRequestHeader('clientid', runtimeConfig.clientId)
|
||||
task.setRequestHeader('tenantId', runtimeConfig.tenantId)
|
||||
const token = session.getToken()
|
||||
if (token) task.setRequestHeader('Authorization', `Bearer ${token}`)
|
||||
task.addFile(filePath, { key: 'file' })
|
||||
})
|
||||
if (requestController) requestController.bind(abort)
|
||||
task.start()
|
||||
} catch (error) {
|
||||
rejectOnce(error)
|
||||
}
|
||||
@@ -315,17 +332,25 @@ const requestBrowserFileChunk = ({ uploadId, chunkIndex, chunkMd5, file }, { req
|
||||
return
|
||||
}
|
||||
let settled = false
|
||||
let timeoutId = null
|
||||
const abortController = new AbortController()
|
||||
const release = () => requestController?.release(abort)
|
||||
const clearRequestTimeout = () => {
|
||||
if (timeoutId === null) return
|
||||
clearTimeout(timeoutId)
|
||||
timeoutId = null
|
||||
}
|
||||
const resolveOnce = (value) => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
clearRequestTimeout()
|
||||
release()
|
||||
resolve(value)
|
||||
}
|
||||
const rejectOnce = (error) => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
clearRequestTimeout()
|
||||
release()
|
||||
reject(error)
|
||||
}
|
||||
@@ -334,12 +359,18 @@ const requestBrowserFileChunk = ({ uploadId, chunkIndex, chunkMd5, file }, { req
|
||||
abortController.abort()
|
||||
rejectOnce(createRequestCancelledError())
|
||||
}
|
||||
const query = `uploadId=${encodeURIComponent(uploadId)}&chunkIndex=${encodeURIComponent(chunkIndex)}&chunkMd5=${encodeURIComponent(chunkMd5)}`
|
||||
const token = session.getToken()
|
||||
const formData = new globalThis.FormData()
|
||||
formData.append('uploadId', uploadId)
|
||||
formData.append('chunkIndex', String(chunkIndex))
|
||||
formData.append('chunkMd5', chunkMd5)
|
||||
formData.append('file', file, file.name || 'image')
|
||||
if (requestController) requestController.bind(abort)
|
||||
globalThis.fetch(`${runtimeConfig.baseUrl}/genealogy/app/files/resumable/chunk?${query}`, {
|
||||
timeoutId = setTimeout(() => {
|
||||
abortController.abort()
|
||||
rejectOnce(createRequestError('文件分片上传超时', 'REQUEST_TIMEOUT'))
|
||||
}, REQUEST_TIMEOUT_MS)
|
||||
globalThis.fetch(`${runtimeConfig.baseUrl}/genealogy/app/files/resumable/chunk`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
clientid: runtimeConfig.clientId,
|
||||
@@ -360,67 +391,6 @@ const requestBrowserFileChunk = ({ uploadId, chunkIndex, chunkMd5, file }, { req
|
||||
})
|
||||
})
|
||||
|
||||
const requestNativeSingleFileUpload = ({ filePath }, { requestController = null } = {}) => new Promise((resolve, reject) => {
|
||||
if (requestController !== null && (
|
||||
typeof requestController.bind !== 'function' ||
|
||||
typeof requestController.release !== 'function'
|
||||
)) {
|
||||
reject(new TypeError('文件上传控制器格式无效'))
|
||||
return
|
||||
}
|
||||
let settled = false
|
||||
let task = null
|
||||
const release = () => requestController?.release(abort)
|
||||
const resolveOnce = (value) => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
release()
|
||||
resolve(value)
|
||||
}
|
||||
const rejectOnce = (error) => {
|
||||
if (settled) return
|
||||
settled = true
|
||||
release()
|
||||
reject(error)
|
||||
}
|
||||
const abort = () => {
|
||||
if (settled) return
|
||||
task?.abort?.()
|
||||
rejectOnce(createRequestCancelledError())
|
||||
}
|
||||
try {
|
||||
const token = session.getToken()
|
||||
task = uni.uploadFile({
|
||||
url: `${runtimeConfig.baseUrl}/genealogy/app/files/upload`,
|
||||
filePath,
|
||||
name: 'file',
|
||||
header: {
|
||||
clientid: runtimeConfig.clientId,
|
||||
tenantId: runtimeConfig.tenantId,
|
||||
...(token ? { Authorization: `Bearer ${token}` } : {})
|
||||
},
|
||||
success: ({ data, statusCode }) => {
|
||||
if (statusCode !== 200) {
|
||||
rejectOnce(createRequestError(`文件上传失败(HTTP ${statusCode})`, 'HTTP_ERROR', { httpStatus: statusCode }))
|
||||
return
|
||||
}
|
||||
try {
|
||||
resolveOnce(normalizeResumableCompleteResult(parseStrictUploadResponse(data, true)))
|
||||
} catch (error) {
|
||||
rejectOnce(error)
|
||||
}
|
||||
},
|
||||
fail: (error) => {
|
||||
const message = error?.errMsg || '文件上传网络连接失败'
|
||||
rejectOnce(createRequestError(message, /timeout/i.test(message) ? 'REQUEST_TIMEOUT' : 'NETWORK_ERROR'))
|
||||
}
|
||||
})
|
||||
if (requestController) requestController.bind(abort)
|
||||
} catch (error) {
|
||||
rejectOnce(error)
|
||||
}
|
||||
})
|
||||
|
||||
const requireRemoteAuth = () => {
|
||||
if (resolveRuntimeMode() !== 'remote') {
|
||||
const error = new Error('当前为本地预览模式,真实认证服务未启用')
|
||||
@@ -1095,21 +1065,18 @@ const normalizeLineageText = (value, label, { required = false } = {}) => {
|
||||
const lineageDatePart = (value, label) => {
|
||||
const normalized = normalizeLineageText(value, label)
|
||||
if (!normalized) return ''
|
||||
if (!/^\d{4}-\d{2}-\d{2}/.test(normalized)) throw lineageTreeError(`世系树${label}无效`)
|
||||
if (!/^\d{4}-\d{2}-\d{2}/.test(normalized)) {
|
||||
throw lineageTreeError(`世系树${label}无效`)
|
||||
}
|
||||
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 chinaTime = new Date(instant.getTime() + 8 * 60 * 60 * 1000)
|
||||
const year = chinaTime.getUTCFullYear()
|
||||
const month = String(chinaTime.getUTCMonth() + 1).padStart(2, '0')
|
||||
const day = String(chinaTime.getUTCDate()).padStart(2, '0')
|
||||
return `${year}-${month}-${day}`
|
||||
}
|
||||
|
||||
const normalizeLineageTree = (value) => {
|
||||
@@ -1870,7 +1837,7 @@ const normalizePhoneChangePayload = (payload) => {
|
||||
if (typeof payload.phone !== 'string' || !/^1\d{10}$/.test(payload.phone.trim())) {
|
||||
throw new TypeError('新手机号格式无效')
|
||||
}
|
||||
return authPayload({ phone: payload.phone.trim(), smsCode: assertSmsCode(payload.smsCode) })
|
||||
return { phone: payload.phone.trim(), smsCode: assertSmsCode(payload.smsCode) }
|
||||
}
|
||||
|
||||
const normalizeMemberUpdatePayload = (payload) => {
|
||||
@@ -1898,36 +1865,23 @@ const normalizeVipOrderPayload = (payload) => {
|
||||
return data
|
||||
}
|
||||
|
||||
const normalizeFileReferencePayload = (payload) => {
|
||||
assertPlainPayload(payload, new Set(['bizType', 'bizName', 'bizTable', 'bizId', 'bizField', 'ossId', 'ossIds', 'usageScene', 'usageName']), '文件引用请求')
|
||||
const normalizeSiteArticleQuery = (payload = {}) => {
|
||||
assertPlainPayload(payload, new Set(['articleType', 'limit']), '官网文章查询')
|
||||
const data = {}
|
||||
for (const field of ['bizType', 'bizName', 'bizTable', 'bizField', 'usageScene', 'usageName']) {
|
||||
const value = normalizeOptionalAuthText(payload[field], field)
|
||||
if (value) data[field] = value
|
||||
const articleType = normalizeOptionalAuthText(payload.articleType, '官网文章类型')
|
||||
if (articleType) data.articleType = articleType
|
||||
if (payload.limit !== undefined && payload.limit !== null && payload.limit !== '') {
|
||||
const limit = typeof payload.limit === 'number' ? payload.limit : Number(payload.limit)
|
||||
if (!Number.isSafeInteger(limit) || limit < 1) throw new TypeError('官网文章数量上限必须是正整数')
|
||||
data.limit = limit
|
||||
}
|
||||
for (const field of ['bizType', 'bizTable', 'bizField']) {
|
||||
if (!data[field]) throw new TypeError(`文件引用缺少 ${field}`)
|
||||
}
|
||||
data.bizId = Number(normalizeResourcePathId(payload.bizId, '业务标识'))
|
||||
if (payload.ossId !== undefined && payload.ossId !== null && payload.ossId !== '') {
|
||||
data.ossId = Number(normalizeResourcePathId(payload.ossId, '文件标识'))
|
||||
}
|
||||
const ossIds = normalizeOptionalOssIdList(payload.ossIds)
|
||||
if (ossIds) data.ossIds = ossIds
|
||||
if (!data.ossId && !data.ossIds) throw new TypeError('文件引用需要 ossId 或 ossIds')
|
||||
return data
|
||||
}
|
||||
|
||||
const normalizeFileReferenceReleasePayload = (payload) => {
|
||||
assertPlainPayload(payload, new Set(['bizTable', 'bizId', 'bizField']), '文件引用释放请求')
|
||||
const bizTable = normalizeOptionalAuthText(payload.bizTable, 'bizTable')
|
||||
const bizField = normalizeOptionalAuthText(payload.bizField, 'bizField')
|
||||
if (!bizTable || !bizField) throw new TypeError('文件引用释放缺少 bizTable 或 bizField')
|
||||
return {
|
||||
bizTable,
|
||||
bizId: normalizeResourcePathId(payload.bizId, '业务标识'),
|
||||
bizField
|
||||
}
|
||||
const normalizeSitePageKey = (pageKey) => {
|
||||
const normalized = normalizeOptionalAuthText(pageKey, '官网页面标识')
|
||||
if (!normalized) throw new TypeError('官网页面标识不能为空')
|
||||
return normalized
|
||||
}
|
||||
|
||||
const normalizeJoinApplicationPayload = (payload) => {
|
||||
@@ -2252,20 +2206,6 @@ export const appApi = {
|
||||
}
|
||||
}, requestOptions)
|
||||
},
|
||||
async sendLegacySmsCode({ phone, validToken }, requestOptions = {}) {
|
||||
requireRemoteAuth()
|
||||
const normalizedValidToken = normalizeOptionalValidToken(validToken)
|
||||
return requestAuthVoid({
|
||||
url: '/genealogy/app/auth/sms/code',
|
||||
method: 'POST',
|
||||
data: {
|
||||
tenantId: runtimeConfig.tenantId,
|
||||
grantType: 'sms',
|
||||
phone,
|
||||
...(normalizedValidToken ? { validToken: normalizedValidToken } : {})
|
||||
}
|
||||
}, requestOptions)
|
||||
},
|
||||
async loginWithPassword({ phone, passwordHash, validToken }, requestOptions = {}) {
|
||||
requireRemoteAuth()
|
||||
const normalizedValidToken = normalizeOptionalValidToken(validToken)
|
||||
@@ -2287,7 +2227,7 @@ export const appApi = {
|
||||
const result = await requestAuth({
|
||||
url: '/genealogy/app/auth/login/sms',
|
||||
method: 'POST',
|
||||
data: authPayload({ grantType: 'sms', phone, smsCode: assertSmsCode(smsCode) })
|
||||
data: { tenantId: runtimeConfig.tenantId, grantType: 'sms', phone, smsCode: assertSmsCode(smsCode) }
|
||||
}, requestOptions)
|
||||
return saveLogin(result)
|
||||
},
|
||||
@@ -2297,13 +2237,14 @@ export const appApi = {
|
||||
const result = await requestAuth({
|
||||
url: '/genealogy/app/auth/register',
|
||||
method: 'POST',
|
||||
data: authPayload({
|
||||
data: {
|
||||
tenantId: runtimeConfig.tenantId,
|
||||
grantType: 'password',
|
||||
phone,
|
||||
password: assertPasswordHash(passwordHash),
|
||||
smsCode: assertSmsCode(smsCode),
|
||||
...(normalizedNickName ? { nickName: normalizedNickName } : {})
|
||||
})
|
||||
}
|
||||
}, requestOptions)
|
||||
return saveLogin(result)
|
||||
},
|
||||
@@ -2312,12 +2253,13 @@ export const appApi = {
|
||||
return requestAuthVoid({
|
||||
url: '/genealogy/app/auth/password/reset',
|
||||
method: 'PUT',
|
||||
data: authPayload({
|
||||
data: {
|
||||
tenantId: runtimeConfig.tenantId,
|
||||
grantType: 'password',
|
||||
phone,
|
||||
newPassword: assertPasswordHash(passwordHash),
|
||||
smsCode: assertSmsCode(smsCode)
|
||||
})
|
||||
}
|
||||
}, requestOptions)
|
||||
},
|
||||
async changePassword({ oldPasswordHash, newPasswordHash }, requestOptions = {}) {
|
||||
@@ -2340,7 +2282,7 @@ export const appApi = {
|
||||
await requestStrict({
|
||||
url: '/genealogy/app/auth/account/deactivate',
|
||||
method: 'POST',
|
||||
data: { clientId: runtimeConfig.clientId, smsCode: assertSmsCode(smsCode) }
|
||||
data: { smsCode: assertSmsCode(smsCode) }
|
||||
}, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
@@ -2477,27 +2419,6 @@ export const appApi = {
|
||||
})
|
||||
return normalizeResumableCompleteResult(result)
|
||||
},
|
||||
async uploadSingleFile({ filePath }, requestOptions = {}) {
|
||||
if (typeof filePath !== 'string' || !filePath.trim()) {
|
||||
throw new TypeError('filePath必须是非空字符串')
|
||||
}
|
||||
requireRemoteResource('文件上传', '写入')
|
||||
return requestNativeSingleFileUpload({ filePath: filePath.trim() }, requestOptions)
|
||||
},
|
||||
async createFileReference(payload, requestOptions = {}) {
|
||||
return writeRemoteVoid(
|
||||
'/genealogy/app/files/reference',
|
||||
'POST',
|
||||
normalizeFileReferencePayload(payload),
|
||||
'文件引用',
|
||||
requestOptions
|
||||
)
|
||||
},
|
||||
async deleteFileReference(payload, requestOptions = {}) {
|
||||
const data = normalizeFileReferenceReleasePayload(payload)
|
||||
const query = `bizTable=${encodeURIComponent(data.bizTable)}&bizId=${encodeURIComponent(data.bizId)}&bizField=${encodeURIComponent(data.bizField)}`
|
||||
return writeRemoteVoid(`/genealogy/app/files/reference?${query}`, 'DELETE', undefined, '文件引用', requestOptions)
|
||||
},
|
||||
async getRegionChildren(parentCode, requestOptions = {}) {
|
||||
if (!hasRemoteConfig()) {
|
||||
const error = new Error('地区选择需要真实读取服务,当前本地预览不会伪造地区列表')
|
||||
@@ -2505,7 +2426,7 @@ export const appApi = {
|
||||
throw error
|
||||
}
|
||||
const result = await requestStrict({
|
||||
url: '/genealogy/region/children',
|
||||
url: '/genealogy/app/region/children',
|
||||
method: 'GET',
|
||||
data: { parentCode: normalizeRegionParentCode(parentCode) }
|
||||
}, {
|
||||
@@ -2516,7 +2437,7 @@ export const appApi = {
|
||||
async getRegionPath(regionCode, requestOptions = {}) {
|
||||
requireRemoteResource('行政区划路径', '读取')
|
||||
const result = await requestStrict({
|
||||
url: `/genealogy/region/path/${encodeURIComponent(normalizeRegionCode(regionCode))}`,
|
||||
url: `/genealogy/app/region/path/${encodeURIComponent(normalizeRegionCode(regionCode))}`,
|
||||
method: 'GET'
|
||||
}, {
|
||||
requestController: requestOptions.requestController ?? null
|
||||
@@ -2529,7 +2450,7 @@ export const appApi = {
|
||||
async searchRegions(payload, requestOptions = {}) {
|
||||
requireRemoteResource('行政区划搜索', '读取')
|
||||
const result = await requestStrict({
|
||||
url: '/genealogy/region/search',
|
||||
url: '/genealogy/app/region/search',
|
||||
method: 'GET',
|
||||
data: normalizeRegionSearchPayload(payload)
|
||||
}, {
|
||||
@@ -2543,7 +2464,7 @@ export const appApi = {
|
||||
async getRegion(regionCode, requestOptions = {}) {
|
||||
requireRemoteResource('行政区划详情', '读取')
|
||||
const result = await requestStrict({
|
||||
url: `/genealogy/region/${encodeURIComponent(normalizeRegionCode(regionCode))}`,
|
||||
url: `/genealogy/app/region/${encodeURIComponent(normalizeRegionCode(regionCode))}`,
|
||||
method: 'GET'
|
||||
}, {
|
||||
requestController: requestOptions.requestController ?? null
|
||||
@@ -3444,11 +3365,15 @@ export const appApi = {
|
||||
},
|
||||
async changePhone(payload, requestOptions = {}) {
|
||||
requireRemoteAuth()
|
||||
return requestAuthVoid({
|
||||
await requestStrict({
|
||||
url: '/genealogy/app/auth/phone',
|
||||
method: 'PUT',
|
||||
data: normalizePhoneChangePayload(payload)
|
||||
}, requestOptions)
|
||||
}, {
|
||||
requireData: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
return null
|
||||
},
|
||||
async getHelpArticles(requestOptions = {}) {
|
||||
return readRemoteList('/genealogy/app/help-articles', '帮助文章', requestOptions)
|
||||
@@ -3504,10 +3429,32 @@ export const appApi = {
|
||||
const id = normalizeGenealogyPathId(genealogyId)
|
||||
return readRemoteList(`/genealogy/app/genealogies/${id}/lineage/persons/options`, '世系人物选项', requestOptions)
|
||||
},
|
||||
async getContent(type, genealogyId, requestOptions = {}) {
|
||||
const loaders = { article: this.getArticles, album: this.getAlbums, ceremony: this.getCeremonies, record: this.getGrowthRecords }
|
||||
if (!loaders[type]) throw new Error('未知内容类型')
|
||||
return loaders[type].call(this, genealogyId, requestOptions)
|
||||
async getSiteArticles(payload = {}, requestOptions = {}) {
|
||||
const result = await requestStrict({
|
||||
url: '/genealogy/app/site/articles',
|
||||
method: 'GET',
|
||||
data: normalizeSiteArticleQuery(payload)
|
||||
}, {
|
||||
authenticated: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
if (!Array.isArray(result)) {
|
||||
throw createRequestError('官网文章列表响应不是数组', 'SITE_ARTICLE_LIST_RESPONSE_INVALID')
|
||||
}
|
||||
return result
|
||||
},
|
||||
async getSitePage(pageKey, requestOptions = {}) {
|
||||
const result = await requestStrict({
|
||||
url: `/genealogy/app/site/pages/${encodeURIComponent(normalizeSitePageKey(pageKey))}`,
|
||||
method: 'GET'
|
||||
}, {
|
||||
authenticated: false,
|
||||
requestController: requestOptions.requestController ?? null
|
||||
})
|
||||
if (!result || typeof result !== 'object' || Array.isArray(result)) {
|
||||
throw createRequestError('官网单页响应不是对象', 'SITE_PAGE_RESPONSE_INVALID')
|
||||
}
|
||||
return result
|
||||
},
|
||||
async getNotifications(requestOptions = {}) {
|
||||
if (!hasRemoteConfig()) return listNotificationFixtures()
|
||||
|
||||
Reference in New Issue
Block a user