feat: 开源项目门户站首版(iotLCM / 秀杰 DTU / XiuAdmin 三项目,注册表驱动)

This commit is contained in:
技小云
2026-11-04 11:08:47 +08:00
committed by MiFaZhan
commit fe63dacae2
27 changed files with 3786 additions and 0 deletions
+49
View File
@@ -0,0 +1,49 @@
#!/usr/bin/env node
/**
* 校验「项目注册表」与「详情页目录」是否一一对应。
*
* 门户的项目清单由 data/projects.ts 单一驱动。如果注册表加了项目却忘了写详情页,
* 或者写了详情页却没登记进注册表,首页卡片与侧边栏就会和实际内容脱节。
* 这个脚本在 dev / build 之前自动跑,不一致直接退出非零。
*/
import { readdirSync, readFileSync, existsSync } from 'node:fs'
import { fileURLToPath } from 'node:url'
import { dirname, join } from 'node:path'
const root = join(dirname(fileURLToPath(import.meta.url)), '..')
const dataDir = join(root, 'data')
const pagesDir = join(root, 'pages', 'projects')
// 注册表是 TS 源文件,这里只需要 id 列表,正则抽取即可,不引入编译步骤
const registrySrc = readdirSync(dataDir)
.filter((f) => f.endsWith('.ts'))
.map((f) => readFileSync(join(dataDir, f), 'utf-8'))
.join('\n')
const registered = [...registrySrc.matchAll(/\bid:\s*'([^']+)'/g)].map((m) => m[1])
if (registered.length === 0) {
console.error('[check] 注册表里没解析到任何项目,检查 data/projects.ts 的格式')
process.exit(1)
}
const onDisk = existsSync(pagesDir)
? readdirSync(pagesDir, { withFileTypes: true })
.filter((d) => d.isDirectory())
.map((d) => d.name)
: []
const missingPages = registered.filter((id) => !onDisk.includes(id))
const missingEntries = onDisk.filter((id) => !registered.includes(id))
if (missingPages.length || missingEntries.length) {
if (missingPages.length) {
console.error(`[check] 注册表里有项目但缺详情页:${missingPages.join(', ')}`)
}
if (missingEntries.length) {
console.error(`[check] 有详情页但没登记进注册表:${missingEntries.join(', ')}`)
}
process.exit(1)
}
console.log(`[check] OK:注册表 ${registered.length} 个项目与详情页一一对应(${registered.join(', ')})`)