feat: 完成前端业务闭环与后端联调

This commit is contained in:
2026-08-24 23:37:56 +08:00
parent c59e36f933
commit 9ad572907b
175 changed files with 10711 additions and 1740 deletions
+123
View File
@@ -0,0 +1,123 @@
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}`
)