type PayloadRecord = Record; function invalid(context: string, path: string, expected: string): never { const separator = path === "响应" ? "" : " "; throw new Error(`${context}数据格式错误:${path}${separator}必须是${expected}。`); } function requireRecord(value: unknown, path: string, context: string): PayloadRecord { if (typeof value !== "object" || value === null || Array.isArray(value)) { invalid(context, path, "对象"); } return value as PayloadRecord; } function requireArray(record: PayloadRecord, field: string, context: string, path = field): unknown[] { if (!Array.isArray(record[field])) invalid(context, path, "数组"); return record[field]; } function requireString(record: PayloadRecord, field: string, context: string, path: string): void { if (typeof record[field] !== "string") invalid(context, path, "字符串"); } function requireOptionalString(record: PayloadRecord, field: string, context: string, path: string): void { if (record[field] !== undefined && record[field] !== null && typeof record[field] !== "string") { invalid(context, path, "字符串"); } } function requireNumber(record: PayloadRecord, field: string, context: string, path: string): void { if (typeof record[field] !== "number" || !Number.isFinite(record[field])) { invalid(context, path, "有限数字"); } } function requireBoolean(record: PayloadRecord, field: string, context: string, path: string): void { if (typeof record[field] !== "boolean") invalid(context, path, "布尔值"); } function requireScalar(value: unknown, context: string, path: string): void { if (!(["string", "number", "boolean"] as string[]).includes(typeof value)) { invalid(context, path, "字符串、数字或布尔值"); } if (typeof value === "number" && !Number.isFinite(value)) invalid(context, path, "有限数字"); } function validateBillingAccount(value: unknown, context: string, path: string): void { const account = requireRecord(value, path, context); for (const field of ["accountName", "bankName", "accountNumber", "contact"]) { requireOptionalString(account, field, context, `${path}.${field}`); } } function validateWallet(value: unknown, context: string, path: string): void { const wallet = requireRecord(value, path, context); requireString(wallet, "organizationId", context, `${path}.organizationId`); for (const field of ["balanceFen", "totalRechargedFen", "totalChargedFen"]) { requireNumber(wallet, field, context, `${path}.${field}`); } requireString(wallet, "updatedAt", context, `${path}.updatedAt`); } function validateSummary(value: unknown, context: string, path: string): void { const summary = requireRecord(value, path, context); for (const field of ["rechargeFen", "chargedFen", "refundedFen", "netConsumedFen"]) { requireNumber(summary, field, context, `${path}.${field}`); } } function validateLedgerEntry(value: unknown, context: string, path: string): void { const entry = requireRecord(value, path, context); requireString(entry, "id", context, `${path}.id`); requireString(entry, "organizationId", context, `${path}.organizationId`); requireOptionalString(entry, "accountId", context, `${path}.accountId`); requireOptionalString(entry, "jobId", context, `${path}.jobId`); requireString(entry, "kind", context, `${path}.kind`); requireNumber(entry, "deltaFen", context, `${path}.deltaFen`); requireNumber(entry, "balanceAfterFen", context, `${path}.balanceAfterFen`); requireString(entry, "description", context, `${path}.description`); requireRecord(entry.metadata, `${path}.metadata`, context); requireString(entry, "createdAt", context, `${path}.createdAt`); if (Number.isNaN(Date.parse(entry.createdAt as string))) invalid(context, `${path}.createdAt`, "有效时间字符串"); } function validateOrganization(value: unknown, context: string, path: string): void { const organization = requireRecord(value, path, context); requireString(organization, "id", context, `${path}.id`); requireString(organization, "name", context, `${path}.name`); } function validateAdminOrganization(value: unknown, context: string, path: string): void { const organization = requireRecord(value, path, context); requireString(organization, "id", context, `${path}.id`); requireString(organization, "name", context, `${path}.name`); requireString(organization, "status", context, `${path}.status`); validateWallet(organization.wallet, context, `${path}.wallet`); } function validateAdminMember(value: unknown, context: string, path: string): void { const member = requireRecord(value, path, context); for (const field of ["id", "displayName", "phone", "role", "status"]) { requireString(member, field, context, `${path}.${field}`); } requireOptionalString(member, "organizationId", context, `${path}.organizationId`); } function validatePriceRule(value: unknown, context: string, path: string): void { const rule = requireRecord(value, path, context); for (const field of ["id", "provider", "capability", "unit"]) { requireString(rule, field, context, `${path}.${field}`); } requireOptionalString(rule, "reqKey", context, `${path}.reqKey`); requireOptionalString(rule, "variantKey", context, `${path}.variantKey`); requireOptionalString(rule, "note", context, `${path}.note`); requireNumber(rule, "standardUnitPriceFen", context, `${path}.standardUnitPriceFen`); requireNumber(rule, "markupMultiplier", context, `${path}.markupMultiplier`); requireBoolean(rule, "enabled", context, `${path}.enabled`); if (rule.conditions !== undefined && rule.conditions !== null) { requireRecord(rule.conditions, `${path}.conditions`, context); } if (rule.source !== undefined && rule.source !== null) { const source = requireRecord(rule.source, `${path}.source`, context); requireOptionalString(source, "url", context, `${path}.source.url`); } if (rule.parameterDimensions !== undefined && rule.parameterDimensions !== null) { if (!Array.isArray(rule.parameterDimensions)) invalid(context, `${path}.parameterDimensions`, "数组"); rule.parameterDimensions.forEach((dimension, dimensionIndex) => { const dimensionPath = `${path}.parameterDimensions[${dimensionIndex}]`; const item = requireRecord(dimension, dimensionPath, context); requireString(item, "key", context, `${dimensionPath}.key`); requireOptionalString(item, "label", context, `${dimensionPath}.label`); requireScalar(item.baselineValue, context, `${dimensionPath}.baselineValue`); if (item.defaultValue !== undefined && item.defaultValue !== null) { requireScalar(item.defaultValue, context, `${dimensionPath}.defaultValue`); } requireArray(item, "tiers", context, `${dimensionPath}.tiers`).forEach((tier, tierIndex) => { const tierPath = `${dimensionPath}.tiers[${tierIndex}]`; const tierItem = requireRecord(tier, tierPath, context); requireScalar(tierItem.value, context, `${tierPath}.value`); requireOptionalString(tierItem, "label", context, `${tierPath}.label`); requireNumber(tierItem, "standardFactor", context, `${tierPath}.standardFactor`); requireNumber(tierItem, "markupMultiplier", context, `${tierPath}.markupMultiplier`); requireBoolean(tierItem, "enabled", context, `${tierPath}.enabled`); requireOptionalString(tierItem, "note", context, `${tierPath}.note`); }); }); } } export function parseAdminBillingPayload(payload: T): T { const context = "超管计费"; const record = requireRecord(payload, "响应", context); validateBillingAccount(record.billingAccount, context, "billingAccount"); requireArray(record, "organizations", context).forEach((item, index) => validateAdminOrganization(item, context, `organizations[${index}]`)); requireArray(record, "members", context).forEach((item, index) => validateAdminMember(item, context, `members[${index}]`)); requireArray(record, "ledger", context).forEach((item, index) => validateLedgerEntry(item, context, `ledger[${index}]`)); requireArray(record, "priceRules", context).forEach((item, index) => validatePriceRule(item, context, `priceRules[${index}]`)); return payload; } export function parseMemberBillingPayload(payload: T): T { const context = "成员计费"; const record = requireRecord(payload, "响应", context); validateOrganization(record.organization, context, "organization"); validateBillingAccount(record.billingAccount, context, "billingAccount"); validateWallet(record.wallet, context, "wallet"); requireArray(record, "ledger", context).forEach((item, index) => validateLedgerEntry(item, context, `ledger[${index}]`)); validateSummary(record.summary, context, "summary"); validateSummary(record.personal, context, "personal"); return payload; }