Files
jiapuapp/scripts/check-frontend-parity.mjs

124 lines
3.8 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import fs from 'node:fs'
import path from 'node:path'
const workspaceRoot = process.cwd()
const referenceRoot = path.resolve(workspaceRoot, '..', 'Jiapu-App')
const referencePagesPath = path.join(referenceRoot, 'pages.json')
const parityDocumentPath = path.join(
workspaceRoot,
'docs',
'frontend-reference-parity-2026-08-17.md'
)
const stripJsonLineComments = (source) =>
source
.split(/\r?\n/u)
.map((line) => {
let inString = false
let escaped = false
for (let index = 0; index < line.length - 1; index += 1) {
const character = line[index]
if (escaped) {
escaped = false
continue
}
if (character === '\\' && inString) {
escaped = true
continue
}
if (character === '"') {
inString = !inString
continue
}
if (!inString && character === '/' && line[index + 1] === '/') {
return line.slice(0, index)
}
}
return line
})
.join('\n')
const fail = (message) => {
console.error(`FRONTEND PARITY CHECK FAIL: ${message}`)
process.exit(1)
}
if (!fs.existsSync(referencePagesPath)) {
fail(`参考项目不存在:${referencePagesPath}`)
}
if (!fs.existsSync(parityDocumentPath)) {
fail(`对比总表不存在:${parityDocumentPath}`)
}
const referenceConfig = JSON.parse(
stripJsonLineComments(fs.readFileSync(referencePagesPath, 'utf8'))
)
const referenceRoutes = referenceConfig.pages.map(({ path: routePath }) => routePath)
if (referenceRoutes.length !== 78) {
fail(`参考项目活动路由应为 78 条,实际为 ${referenceRoutes.length} 条`)
}
if (new Set(referenceRoutes).size !== referenceRoutes.length) {
fail('参考项目 pages.json 存在重复活动路由')
}
for (const routePath of referenceRoutes) {
const vuePath = path.join(referenceRoot, `${routePath}.vue`)
const nvuePath = path.join(referenceRoot, `${routePath}.nvue`)
if (!fs.existsSync(vuePath) && !fs.existsSync(nvuePath)) {
fail(`参考路由没有 .vue 或 .nvue 页面文件:${routePath}`)
}
}
const parityDocument = fs.readFileSync(parityDocumentPath, 'utf8')
const documentedRouteRows = parityDocument
.split(/\r?\n/u)
.filter((line) => /^\| `[^`]+` \|/u.test(line))
.map((line) => line.split('|').slice(1, -1).map((column) => column.trim()))
const documentedRoutes = documentedRouteRows.map(([routeCell]) => routeCell.slice(1, -1))
const allowedStatuses = new Set([
'覆盖',
'合并覆盖',
'升级替代',
'非产品页',
'本轮补齐',
'部分覆盖',
'部分合并',
'部分升级',
'前端待后端'
])
for (const columns of documentedRouteRows) {
if (columns.length !== 5 || columns.some((column) => !column)) {
fail(`对比总表路由行字段不完整${columns[0] || '未知路由'}`)
}
if (!allowedStatuses.has(columns[3])) {
fail(`对比总表路由状态无效${columns[0]} -> ${columns[3]}`)
}
}
const documentedRouteCounts = new Map()
for (const routePath of documentedRoutes) {
documentedRouteCounts.set(
routePath,
(documentedRouteCounts.get(routePath) || 0) + 1
)
}
const missingRoutes = referenceRoutes.filter(
(routePath) => !documentedRouteCounts.has(routePath)
)
const duplicateRoutes = [...documentedRouteCounts.entries()]
.filter(([, count]) => count !== 1)
.map(([routePath]) => routePath)
const unknownRoutes = documentedRoutes.filter(
(routePath) => !referenceRoutes.includes(routePath)
)
if (missingRoutes.length) fail(`对比总表遗漏路由${missingRoutes.join(', ')}`)
if (duplicateRoutes.length) fail(`对比总表重复路由${duplicateRoutes.join(', ')}`)
if (unknownRoutes.length) fail(`对比总表包含未知路由${unknownRoutes.join(', ')}`)
console.log(
`FRONTEND PARITY CHECK PASS referenceRoutes=${referenceRoutes.length} documentedRoutes=${documentedRoutes.length}`
)