feat: migrate app routes and business modules

This commit is contained in:
2026-08-12 18:22:59 +08:00
parent 555aa00043
commit cc706378c2
247 changed files with 28623 additions and 14988 deletions
+166
View File
@@ -0,0 +1,166 @@
import { listPreviewFamilyArticles } from '@/data/preview/family-content.js'
import { hasRemoteConfig } from '@/utils/runtime-config.js'
import {
normalizeAppArticle,
normalizeAppArticles,
normalizeArticleCategoryOptions,
normalizeArticleCreatePayload,
normalizePreviewFamilyArticles
} from './family-article-contract.js'
import { normalizeGenealogyPathId } from './genealogy-contract.js'
import { normalizeResourcePathId } from './request-normalizers.js'
import {
contentAccessHeader,
normalizeContentAccessGrant,
normalizeContentPasswordPayload
} from './protected-content-contract.js'
import { createRequestError, requestStrict } from './request-client.js'
const requireRemoteArticle = (message, code) => {
if (hasRemoteConfig()) return
throw createRequestError(message, code)
}
const requestArticleContentProtection = async ({
genealogyId,
articleId,
method,
data,
requestOptions
}) => {
requireRemoteArticle('谱文内容保护需要真实服务,当前本地预览不会伪造结果', 'REMOTE_WRITE_REQUIRED')
return requestStrict({
url: `/genealogy/app/genealogies/${genealogyId}/articles/${articleId}/content-protection`,
method,
...(data === undefined ? {} : { data })
}, {
requireData: false,
requestController: requestOptions.requestController ?? null
})
}
export const familyArticleApi = {
async createArticle(genealogyId, payload, requestOptions = {}) {
requireRemoteArticle('谱文创建需要真实服务,当前本地预览不会伪造创建成功', 'REMOTE_WRITE_REQUIRED')
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
return requestStrict({
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/articles`,
method: 'POST',
data: normalizeArticleCreatePayload(payload)
}, {
requestController: requestOptions.requestController ?? null
})
},
async getArticles(genealogyId, requestOptions = {}) {
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
if (!hasRemoteConfig()) {
return normalizePreviewFamilyArticles(
listPreviewFamilyArticles(normalizedGenealogyId),
normalizedGenealogyId
)
}
const articles = await requestStrict({
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/articles`,
method: 'GET'
}, {
requestController: requestOptions.requestController ?? null
})
return normalizeAppArticles(articles, normalizedGenealogyId)
},
async getArticleDetail(genealogyId, articleId, accessToken = '', requestOptions = {}) {
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
const normalizedArticleId = normalizeResourcePathId(articleId, '谱文标识')
requireRemoteArticle('谱文详情需要真实读取服务,当前本地预览不会伪造详情', 'REMOTE_READ_REQUIRED')
const article = await requestStrict({
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/articles/${normalizedArticleId}`,
method: 'GET',
header: contentAccessHeader(accessToken)
}, {
requestController: requestOptions.requestController ?? null
})
return normalizeAppArticle(article, normalizedGenealogyId, normalizedArticleId)
},
async updateArticle(genealogyId, articleId, payload, requestOptions = {}) {
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
const normalizedArticleId = normalizeResourcePathId(articleId, '谱文标识')
requireRemoteArticle('修改谱文需要真实服务,当前本地预览不会伪造保存成功', 'REMOTE_WRITE_REQUIRED')
const article = await requestStrict({
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/articles/${normalizedArticleId}`,
method: 'PUT',
data: normalizeArticleCreatePayload(payload)
}, {
requestController: requestOptions.requestController ?? null
})
return normalizeAppArticle(article, normalizedGenealogyId, normalizedArticleId)
},
async deleteArticle(genealogyId, articleId, requestOptions = {}) {
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
const normalizedArticleId = normalizeResourcePathId(articleId, '谱文标识')
requireRemoteArticle('删除谱文需要真实服务,当前本地预览不会伪造删除成功', 'REMOTE_WRITE_REQUIRED')
await requestStrict({
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/articles/${normalizedArticleId}`,
method: 'DELETE'
}, {
requireData: false,
requestController: requestOptions.requestController ?? null
})
return null
},
async setArticlePassword(genealogyId, articleId, password, requestOptions = {}) {
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
const normalizedArticleId = normalizeResourcePathId(articleId, '谱文标识')
const passwordPayload = normalizeContentPasswordPayload(password)
await requestArticleContentProtection({
genealogyId: normalizedGenealogyId,
articleId: normalizedArticleId,
method: 'PUT',
data: passwordPayload,
requestOptions
})
return null
},
async unlockArticle(genealogyId, articleId, password, requestOptions = {}) {
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
const normalizedArticleId = normalizeResourcePathId(articleId, '谱文标识')
const passwordPayload = normalizeContentPasswordPayload(password)
requireRemoteArticle('谱文内容解锁需要真实服务,当前本地预览不会伪造结果', 'REMOTE_WRITE_REQUIRED')
const accessGrant = await requestStrict({
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/articles/${normalizedArticleId}/content-unlock`,
method: 'POST',
data: passwordPayload
}, {
requestController: requestOptions.requestController ?? null
})
return normalizeContentAccessGrant(accessGrant)
},
async disableArticlePassword(genealogyId, articleId, requestOptions = {}) {
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
const normalizedArticleId = normalizeResourcePathId(articleId, '谱文标识')
await requestArticleContentProtection({
genealogyId: normalizedGenealogyId,
articleId: normalizedArticleId,
method: 'DELETE',
requestOptions
})
return null
},
async getArticleCategories(genealogyId, requestOptions = {}) {
const normalizedGenealogyId = normalizeGenealogyPathId(genealogyId)
requireRemoteArticle('谱文分类读取需要真实服务,当前本地预览不会伪造结果', 'REMOTE_READ_REQUIRED')
const categories = await requestStrict({
url: `/genealogy/app/genealogies/${normalizedGenealogyId}/article-categories`,
method: 'GET'
}, {
requestController: requestOptions.requestController ?? null
})
return normalizeArticleCategoryOptions(categories)
}
}