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
+127
View File
@@ -0,0 +1,127 @@
import { assertPlainPayload, normalizeOssIdString } from './request-normalizers.js'
import {
LINEAGE_PERSON_OPTIONS,
LINEAGE_RELATION_TYPE
} from './lineage-person-options.js'
import {
normalizeLineagePersonDate,
normalizeLineagePersonIdentity,
normalizeLineagePersonText
} from './lineage-person-contract.js'
const lineageWriteOptionValues = Object.freeze({
bindingMode: new Set(LINEAGE_PERSON_OPTIONS.bindingMode.map(({ value }) => value)),
sex: new Set(LINEAGE_PERSON_OPTIONS.sex.map(({ value }) => value)),
birthLunar: new Set(LINEAGE_PERSON_OPTIONS.lunar.map(({ value }) => value)),
deathLunar: new Set(LINEAGE_PERSON_OPTIONS.lunar.map(({ value }) => value)),
personStatus: new Set(LINEAGE_PERSON_OPTIONS.personStatus.map(({ value }) => value))
})
export const normalizeLineageWritePayload = (payload) => {
const allowedFields = new Set([
'bindingMode',
'appUserId',
'personNo',
'name',
'aliasName',
'sex',
'generationName',
'fatherId',
'motherId',
'avatarOssId',
'birthDate',
'birthLunar',
'birthPlace',
'deathDate',
'deathLunar',
'deathPlace',
'burialPlace',
'biography',
'remark',
'relationName',
'generation',
'personStatus',
'sortOrder'
])
assertPlainPayload(payload, allowedFields, '人物写入请求')
const name = normalizeLineagePersonText(payload.name, '姓名', { required: true })
if (name.length > 20) throw new TypeError('人物姓名长度超出当前页面合同')
const bindingMode = normalizeLineagePersonText(payload.bindingMode, '身份认领方式')
if (!lineageWriteOptionValues.bindingMode.has(bindingMode)) {
throw new TypeError('人物身份认领方式必须是 NONE、SELF 或 SPECIFIED')
}
const normalizedPayload = { bindingMode, name }
if (bindingMode === 'SPECIFIED') {
if (payload.appUserId === undefined || payload.appUserId === null || payload.appUserId === '') {
throw new TypeError('指定业务用户绑定必须提供业务用户标识')
}
normalizedPayload.appUserId = normalizeLineagePersonIdentity(payload.appUserId, '绑定用户标识')
} else if (payload.appUserId !== undefined && payload.appUserId !== null && payload.appUserId !== '') {
throw new TypeError(`${bindingMode} 身份认领不能提供业务用户标识`)
}
for (const [field, label] of [
['fatherId', '父亲标识'],
['motherId', '母亲标识']
]) {
if (payload[field] === undefined || payload[field] === null || payload[field] === '') continue
normalizedPayload[field] = normalizeLineagePersonIdentity(payload[field], label)
}
if (payload.avatarOssId !== undefined && payload.avatarOssId !== null && payload.avatarOssId !== '') {
normalizedPayload.avatarOssId = normalizeOssIdString(payload.avatarOssId, '头像文件标识')
}
if (payload.generation !== undefined) {
if (!Number.isSafeInteger(payload.generation) || payload.generation < 1) {
throw new TypeError('人物世代必须是正安全整数')
}
normalizedPayload.generation = payload.generation
}
for (const [field, label, maxLength] of [
['personNo', '人物编号', null],
['sex', '性别', null],
['generationName', '字辈', 12],
['aliasName', '别名或曾用名', null],
['birthLunar', '出生农历', null],
['birthPlace', '出生地', null],
['deathLunar', '逝世农历', null],
['deathPlace', '逝世地', null],
['burialPlace', '安葬地', null],
['biography', '人物简介', 500],
['remark', '备注', null],
['relationName', '关系显示名称', null],
['personStatus', '人物状态', null]
]) {
if (payload[field] === undefined) continue
const normalizedText = normalizeLineagePersonText(payload[field], label)
if (maxLength && normalizedText.length > maxLength) throw new TypeError(`人物${label}长度超出当前页面合同`)
if (normalizedText && lineageWriteOptionValues[field] && !lineageWriteOptionValues[field].has(normalizedText)) {
throw new TypeError(`人物${label}字典值无效`)
}
if (normalizedText) normalizedPayload[field] = normalizedText
}
for (const [field, label] of [
['birthDate', '出生日期'],
['deathDate', '离世日期']
]) {
if (payload[field] === undefined) continue
const normalizedDate = normalizeLineagePersonDate(payload[field], label)
if (normalizedDate) normalizedPayload[field] = normalizedDate
}
if (normalizedPayload.birthDate && normalizedPayload.deathDate && normalizedPayload.deathDate < normalizedPayload.birthDate) {
throw new TypeError('人物离世日期不能早于出生日期')
}
if (payload.sortOrder !== undefined && payload.sortOrder !== null && payload.sortOrder !== '') {
const sortOrder = typeof payload.sortOrder === 'number' ? payload.sortOrder : Number(payload.sortOrder)
if (!Number.isSafeInteger(sortOrder)) throw new TypeError('人物排序值必须是安全整数')
normalizedPayload.sortOrder = sortOrder
}
return normalizedPayload
}
export const lineageRelationPath = Object.freeze({
[LINEAGE_RELATION_TYPE.FATHER]: 'parents',
[LINEAGE_RELATION_TYPE.MOTHER]: 'parents',
[LINEAGE_RELATION_TYPE.SPOUSE]: 'spouses',
[LINEAGE_RELATION_TYPE.SIBLING]: 'siblings',
[LINEAGE_RELATION_TYPE.SON]: 'children',
[LINEAGE_RELATION_TYPE.DAUGHTER]: 'children'
})